diff --git a/apps/chown.cpp b/apps/chown.cpp index 36f88b7e..c3b3ff58 100644 --- a/apps/chown.cpp +++ b/apps/chown.cpp @@ -1,24 +1,78 @@ +#include #include +#include #include #include #include -int main(int argc, char** argv) +Result 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 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; }