Compare commits

...

2 Commits

Author SHA1 Message Date
15b76f94f4
chown: Parse the owner and group properly
All checks were successful
continuous-integration/drone/push Build is passing
2023-04-20 20:08:49 +02:00
fb79e12248
StringView: Add split_once and to_uint 2023-04-20 20:08:49 +02:00
4 changed files with 105 additions and 9 deletions

View File

@ -1,24 +1,78 @@
#include <luna/String.h>
#include <os/ArgumentParser.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv)
Result<int> luna_main(int argc, char** argv)
{
StringView user;
StringView user_and_group;
StringView path;
os::ArgumentParser parser;
parser.add_description("Change the owner and group of a file."_sv);
parser.add_positional_argument(user, "user"_sv, true);
parser.add_positional_argument(user_and_group, "owner"_sv, true);
parser.add_positional_argument(path, "path"_sv, true);
parser.parse(argc, argv);
u32 id = (u32)strtoul(user.chars(), NULL, 0);
u32 uid = -1;
Option<u32> gid = -1;
if (chown(path.chars(), id, id) < 0)
auto names = TRY(user_and_group.split_once(':'));
if (names.size() > 1)
{
auto& group = names[1];
if (group.is_empty()) { gid = {}; }
else
{
auto rc = group.view().to_uint();
if (rc.has_value()) { gid = (u32)rc.value(); }
else
{
fprintf(stderr, "FIXME: read entry from group file to determine GID for group %s\n", group.chars());
return 1;
}
}
}
if (names.size() > 0)
{
auto& owner = names[0];
if (!owner.is_empty())
{
auto rc = owner.view().to_uint();
if (rc.has_value()) { uid = (u32)rc.value(); }
else
{
struct passwd* pw = getpwnam(owner.chars());
if (!pw)
{
fprintf(stderr, "%s: unknown user %s!\n", argv[0], owner.chars());
return 1;
}
uid = pw->pw_uid;
}
if (!gid.has_value())
{
struct passwd* pw = getpwuid(uid);
if (!pw)
{
fprintf(stderr, "%s: unknown user id %u!\n", argv[0], uid);
return 1;
}
gid = pw->pw_gid;
}
}
}
if (chown(path.chars(), uid, gid.value_or(-1)) < 0)
{
perror("chown");
return 1;
}
return 0;
}

View File

@ -27,6 +27,10 @@ class String
Result<String> substring(usize begin, usize size) const;
Result<Vector<String>> split(StringView delim) const;
Result<Vector<String>> split_once(char delim) const
{
return view().split_once(delim);
}
static Result<String> format(const String& fmt, ...);
static Result<String> format(StringView fmt, ...);

View File

@ -41,6 +41,9 @@ class StringView
bool operator==(StringView other) const;
Result<Vector<String>> split(StringView delim) const;
Result<Vector<String>> split_once(char delim) const;
Result<usize> to_uint() const;
Iterator begin() const
{

View File

@ -1,4 +1,6 @@
#include <luna/CString.h>
#include <luna/NumberParsing.h>
#include <luna/ScopeGuard.h>
#include <luna/String.h>
#include <luna/StringView.h>
@ -62,9 +64,10 @@ Result<Vector<String>> StringView::split(StringView delim) const
String str;
char* copy = strndup(m_string, m_length);
auto guard = make_scope_guard([copy] { free_impl(copy); });
char* segment = strtok(copy, delim.chars());
if (!segment) goto end;
if (!segment) return result;
str = TRY(String::from_cstring(segment));
TRY(result.try_append(move(str)));
@ -72,14 +75,46 @@ Result<Vector<String>> StringView::split(StringView delim) const
while (true)
{
segment = strtok(nullptr, delim.chars());
if (!segment) goto end;
if (!segment) return result;
str = TRY(String::from_cstring(segment));
TRY(result.try_append(move(str)));
}
end:
free_impl(copy);
return result;
}
Result<Vector<String>> StringView::split_once(char delim) const
{
Vector<String> result;
char* copy = strndup(m_string, m_length);
auto guard = make_scope_guard([copy] { free_impl(copy); });
char* middle = strchr(copy, delim);
if (!middle)
{
auto str = TRY(String::from_cstring(copy));
TRY(result.try_append(move(str)));
return result;
}
*middle = '\0';
auto begin = TRY(String::from_cstring(copy));
auto end = TRY(String::from_cstring(middle + 1));
TRY(result.try_append(move(begin)));
TRY(result.try_append(move(end)));
return result;
}
Result<usize> StringView::to_uint() const
{
const char* endptr = nullptr;
auto result = parse_unsigned_integer(m_string, &endptr, 0);
if (endptr == m_string) return err(EINVAL);
return result;
}