Compare commits

...

2 Commits

Author SHA1 Message Date
f0a7098470
apps: Add cp
All checks were successful
continuous-integration/drone/push Build is passing
2023-07-02 16:38:24 +02:00
6db0a2649c
libluna: Add a variant of PathParser::join() for relative paths 2023-07-02 16:38:12 +02:00
4 changed files with 60 additions and 3 deletions

View File

@ -32,3 +32,4 @@ luna_app(ln.cpp ln)
luna_app(mktemp.cpp mktemp) luna_app(mktemp.cpp mktemp)
luna_app(sysfuzz.cpp sysfuzz) luna_app(sysfuzz.cpp sysfuzz)
luna_app(pivot_root.cpp pivot_root) luna_app(pivot_root.cpp pivot_root)
luna_app(cp.cpp cp)

50
apps/cp.cpp Normal file
View File

@ -0,0 +1,50 @@
#include <luna/PathParser.h>
#include <os/ArgumentParser.h>
#include <os/File.h>
#include <os/FileSystem.h>
using os::File;
Result<int> luna_main(int argc, char** argv)
{
StringView source;
StringView destination;
bool verbose { false };
os::ArgumentParser parser;
parser.add_description("Copy files or directories."_sv);
parser.add_system_program_info("cp"_sv);
parser.add_positional_argument(source, "source"_sv, true);
parser.add_positional_argument(destination, "destination"_sv, true);
parser.add_switch_argument(verbose, 'v', "verbose"_sv, "show more information"_sv);
parser.parse(argc, argv);
SharedPtr<File> source_file = TRY(os::File::open(source, File::ReadOnly));
SharedPtr<File> destination_file;
struct stat st;
TRY(os::FileSystem::stat(source_file->fd(), st, true));
umask(0);
if (os::FileSystem::is_directory(destination, true))
{
auto basename = TRY(PathParser::basename(source));
auto path = TRY(PathParser::join_paths(destination, basename.view()));
destination_file = TRY(File::open_or_create(path.view(), File::ReadWrite, st.st_mode & ~S_IFMT));
}
else
destination_file = TRY(File::open_or_create(destination, File::ReadWrite, st.st_mode & ~S_IFMT));
if (verbose) os::eprintln("copying %s to %s", source.chars(), destination.chars());
auto buf = TRY(Buffer::create_sized(4096));
while (1)
{
TRY(source_file->read(buf, 4096));
if (buf.is_empty()) break;
destination_file->write(buf);
}
return 0;
}

View File

@ -17,6 +17,7 @@ class PathParser
PathParser(const PathParser&) = delete; PathParser(const PathParser&) = delete;
static Result<String> join(StringView path1, StringView path2); static Result<String> join(StringView path1, StringView path2);
static Result<String> join_paths(StringView path1, StringView path2);
static Result<String> realpath(StringView path); static Result<String> realpath(StringView path);

View File

@ -62,6 +62,13 @@ Result<String> PathParser::dirname(StringView path)
} }
Result<String> PathParser::join(StringView path1, StringView path2) Result<String> PathParser::join(StringView path1, StringView path2)
{
String result = TRY(join_paths(path1, path2));
return realpath(result.view());
}
Result<String> PathParser::join_paths(StringView path1, StringView path2)
{ {
StringBuilder sb; StringBuilder sb;
TRY(sb.add(path1)); TRY(sb.add(path1));
@ -70,9 +77,7 @@ Result<String> PathParser::join(StringView path1, StringView path2)
TRY(sb.add(path2)); TRY(sb.add(path2));
String result = TRY(sb.string()); return sb.string();
return realpath(result.view());
} }
Result<String> PathParser::realpath(StringView path) Result<String> PathParser::realpath(StringView path)