apio
b4a6e4d56d
All checks were successful
continuous-integration/drone/push Build is passing
This avoids creating a PathParser to use them, which allocates memory that won't be used.
66 lines
1.6 KiB
C++
66 lines
1.6 KiB
C++
#include <luna/NumberParsing.h>
|
|
#include <luna/PathParser.h>
|
|
#include <os/ArgumentParser.h>
|
|
#include <os/FileSystem.h>
|
|
#include <sys/stat.h>
|
|
|
|
static mode_t s_umask = 0;
|
|
|
|
static void read_umask()
|
|
{
|
|
s_umask = umask(0);
|
|
}
|
|
|
|
Result<void> mkdir_recursively(StringView path, mode_t mode)
|
|
{
|
|
begin:
|
|
auto rc = os::FileSystem::create_directory(path, mode);
|
|
if (!rc.has_error()) return {};
|
|
|
|
if (rc.error() == EEXIST) return {};
|
|
if (rc.error() == ENOENT)
|
|
{
|
|
auto parent = TRY(PathParser::dirname(path));
|
|
|
|
TRY(mkdir_recursively(parent.view(), (0777 & ~s_umask) | S_IWUSR | S_IXUSR));
|
|
|
|
goto begin;
|
|
}
|
|
|
|
return rc.release_error();
|
|
}
|
|
|
|
Result<int> luna_main(int argc, char** argv)
|
|
{
|
|
StringView path;
|
|
StringView mode_string;
|
|
bool recursive;
|
|
|
|
os::ArgumentParser parser;
|
|
parser.add_description("Create directories."_sv);
|
|
parser.add_system_program_info("mkdir"_sv);
|
|
parser.add_positional_argument(path, "path"_sv, true);
|
|
parser.add_value_argument(mode_string, 'm', "mode"_sv, "set the mode for the newly created directory");
|
|
parser.add_switch_argument(recursive, 'p', "parents"_sv,
|
|
"if parent directories do not exist, create them as well"_sv);
|
|
parser.parse(argc, argv);
|
|
|
|
read_umask();
|
|
|
|
mode_t mode;
|
|
|
|
if (mode_string.is_empty()) mode = 0777 & ~s_umask;
|
|
else
|
|
mode = (mode_t)parse_unsigned_integer(mode_string.chars(), nullptr, 8) & 01777;
|
|
|
|
if (recursive)
|
|
{
|
|
TRY(mkdir_recursively(path, mode));
|
|
return 0;
|
|
}
|
|
|
|
TRY(os::FileSystem::create_directory(path, mode));
|
|
|
|
return 0;
|
|
}
|