From 69e0b8dbb71c10cb63fb0b99456167ad9eb5d0ee Mon Sep 17 00:00:00 2001 From: Tim Schumacher Date: Tue, 12 Jul 2022 23:28:10 +0200 Subject: [PATCH] LibCore: Make copying permissions, ownership and timestamps combineable --- Userland/Libraries/LibCore/File.cpp | 10 +++++++--- Userland/Libraries/LibCore/File.h | 8 ++++++-- Userland/Utilities/cp.cpp | 7 ++++++- 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/Userland/Libraries/LibCore/File.cpp b/Userland/Libraries/LibCore/File.cpp index 6e19918534..1f9596cc81 100644 --- a/Userland/Libraries/LibCore/File.cpp +++ b/Userland/Libraries/LibCore/File.cpp @@ -408,16 +408,18 @@ ErrorOr 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 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; diff --git a/Userland/Libraries/LibCore/File.h b/Userland/Libraries/LibCore/File.h index 2c21396ae2..b9394b53d7 100644 --- a/Userland/Libraries/LibCore/File.h +++ b/Userland/Libraries/LibCore/File.h @@ -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); + } diff --git a/Userland/Utilities/cp.cpp b/Userland/Utilities/cp.cpp index ce53476eca..ce7fef9c75 100644 --- a/Userland/Utilities/cp.cpp +++ b/Userland/Utilities/cp.cpp @@ -41,6 +41,11 @@ ErrorOr 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 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)