diff --git a/doc/reference.html b/doc/reference.html index b6a32e699..9d7edf8f8 100644 --- a/doc/reference.html +++ b/doc/reference.html @@ -708,6 +708,7 @@

Header <boost/filesystem.hpp&g update_existing, synchronize_data, synchronize, + ignore_attribute_errors, // copy options recursive, copy_symlinks, @@ -3198,6 +3199,7 @@

Operational functions [fs.op.funcs]

diff --git a/include/boost/filesystem/operations.hpp b/include/boost/filesystem/operations.hpp index ab2103a22..b556e668c 100644 --- a/include/boost/filesystem/operations.hpp +++ b/include/boost/filesystem/operations.hpp @@ -54,20 +54,21 @@ BOOST_SCOPED_ENUM_UT_DECLARE_BEGIN(copy_options, unsigned int) none = 0u, // Default. For copy_file: error if the target file exists. For copy: do not recurse, follow symlinks, copy file contents. // copy_file options: - skip_existing = 1u, // Don't overwrite the existing target file, don't report an error - overwrite_existing = 1u << 1, // Overwrite existing file - update_existing = 1u << 2, // Overwrite existing file if its last write time is older than the replacement file - synchronize_data = 1u << 3, // Flush all buffered data written to the target file to permanent storage - synchronize = 1u << 4, // Flush all buffered data and attributes written to the target file to permanent storage + skip_existing = 1u, // Don't overwrite the existing target file, don't report an error + overwrite_existing = 1u << 1u, // Overwrite existing file + update_existing = 1u << 2u, // Overwrite existing file if its last write time is older than the replacement file + synchronize_data = 1u << 3u, // Flush all buffered data written to the target file to permanent storage + synchronize = 1u << 4u, // Flush all buffered data and attributes written to the target file to permanent storage + ignore_attribute_errors = 1u << 5u, // Ignore errors of copying file attributes // copy options: - recursive = 1u << 8, // Recurse into sub-directories - copy_symlinks = 1u << 9, // Copy symlinks as symlinks instead of copying the referenced file - skip_symlinks = 1u << 10, // Don't copy symlinks - directories_only = 1u << 11, // Only copy directory structure, do not copy non-directory files - create_symlinks = 1u << 12, // Create symlinks instead of copying files - create_hard_links = 1u << 13, // Create hard links instead of copying files - _detail_recursing = 1u << 14 // Internal use only, do not use + recursive = 1u << 8u, // Recurse into sub-directories + copy_symlinks = 1u << 9u, // Copy symlinks as symlinks instead of copying the referenced file + skip_symlinks = 1u << 10u, // Don't copy symlinks + directories_only = 1u << 11u, // Only copy directory structure, do not copy non-directory files + create_symlinks = 1u << 12u, // Create symlinks instead of copying files + create_hard_links = 1u << 13u, // Create hard links instead of copying files + _detail_recursing = 1u << 14u // Internal use only, do not use } BOOST_SCOPED_ENUM_DECLARE_END(copy_options) diff --git a/src/operations.cpp b/src/operations.cpp index 3ffa49980..8e3af57aa 100644 --- a/src/operations.cpp +++ b/src/operations.cpp @@ -3061,7 +3061,7 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod goto fail; } - mode_t to_mode = from_mode; + mode_t to_mode = from_mode & fs::perms_mask; #if !defined(BOOST_FILESYSTEM_USE_WASI) // Enable writing for the newly created files. Having write permission set is important e.g. for NFS, // which checks the file permission on the server, even if the client's file descriptor supports writing. @@ -3184,10 +3184,13 @@ bool copy_file(path const& from, path const& to, unsigned int options, error_cod #if !defined(BOOST_FILESYSTEM_USE_WASI) // If we created a new file with an explicitly added S_IWUSR permission, // we may need to update its mode bits to match the source file. - if (to_mode != from_mode) + if ((to_mode & fs::perms_mask) != (from_mode & fs::perms_mask)) { - if (BOOST_UNLIKELY(::fchmod(outfile.fd, from_mode) != 0)) + if (BOOST_UNLIKELY(::fchmod(outfile.fd, (from_mode & fs::perms_mask)) != 0 && + (options & static_cast< unsigned int >(copy_options::ignore_attribute_errors)) == 0u)) + { goto fail_errno; + } } #endif