LibCore: Make copying permissions, ownership and timestamps combineable

This commit is contained in:
Tim Schumacher 2022-07-12 23:28:10 +02:00 committed by Linus Groh
parent a85b728768
commit 69e0b8dbb7
Notes: sideshowbarker 2024-07-17 08:59:27 +09:00
3 changed files with 19 additions and 6 deletions

View file

@ -408,16 +408,18 @@ ErrorOr<void, File::CopyError> File::copy_file(String const& dst_path, struct st
auto my_umask = umask(0);
umask(my_umask);
// NOTE: We don't copy the set-uid and set-gid bits unless requested.
if (preserve_mode != PreserveMode::PermissionsOwnershipTimestamps)
if (!has_flag(preserve_mode, PreserveMode::Permissions))
my_umask |= 06000;
if (fchmod(dst_fd, src_stat.st_mode & ~my_umask) < 0)
return CopyError { errno, false };
if (preserve_mode == PreserveMode::PermissionsOwnershipTimestamps) {
if (has_flag(preserve_mode, PreserveMode::Ownership)) {
if (fchown(dst_fd, src_stat.st_uid, src_stat.st_gid) < 0)
return CopyError { errno, false };
}
if (has_flag(preserve_mode, PreserveMode::Timestamps)) {
// FIXME: Implement utimens() and use it here.
struct utimbuf timbuf;
timbuf.actime = src_stat.st_atime;
@ -462,10 +464,12 @@ ErrorOr<void, File::CopyError> File::copy_directory(String const& dst_path, Stri
if (chmod(dst_path.characters(), src_stat.st_mode & ~my_umask) < 0)
return CopyError { errno, false };
if (preserve_mode == PreserveMode::PermissionsOwnershipTimestamps) {
if (has_flag(preserve_mode, PreserveMode::Ownership)) {
if (chown(dst_path.characters(), src_stat.st_uid, src_stat.st_gid) < 0)
return CopyError { errno, false };
}
if (has_flag(preserve_mode, PreserveMode::Timestamps)) {
// FIXME: Implement utimens() and use it here.
struct utimbuf timbuf;
timbuf.actime = src_stat.st_atime;

View file

@ -56,8 +56,10 @@ public:
};
enum class PreserveMode {
Nothing,
PermissionsOwnershipTimestamps,
Nothing = 0,
Permissions = (1 << 0),
Ownership = (1 << 1),
Timestamps = (1 << 2),
};
struct CopyError : public Error {
@ -113,4 +115,6 @@ private:
ShouldCloseFileDescriptor m_should_close_file_descriptor { ShouldCloseFileDescriptor::Yes };
};
AK_ENUM_BITWISE_OPERATORS(File::PreserveMode);
}

View file

@ -41,6 +41,11 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
bool destination_is_existing_dir = Core::File::is_directory(destination);
auto preserve_mode = Core::File::PreserveMode::Nothing;
if (preserve)
preserve_mode = Core::File::PreserveMode::Permissions | Core::File::PreserveMode::Ownership | Core::File::PreserveMode::Timestamps;
for (auto& source : sources) {
auto destination_path = destination_is_existing_dir
? String::formatted("{}/{}", destination, LexicalPath::basename(source))
@ -51,7 +56,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
recursion_allowed ? Core::File::RecursionMode::Allowed : Core::File::RecursionMode::Disallowed,
link ? Core::File::LinkMode::Allowed : Core::File::LinkMode::Disallowed,
Core::File::AddDuplicateFileMarker::No,
preserve ? Core::File::PreserveMode::PermissionsOwnershipTimestamps : Core::File::PreserveMode::Nothing);
preserve_mode);
if (result.is_error()) {
if (result.error().tried_recursing)