copy: Add COPY_GRACEFUL_WARN
When copying between filesystems, sometimes the target filesystem might not support symlinks/fifos/sockets/... and we want to log and ignore any failures to copy such files when copying. Let's introduce a new flag to enable this behavior.
This commit is contained in:
+27
-9
@@ -486,11 +486,17 @@ static int fd_copy_symlink(
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = symlinkat(target, dt, to);
|
||||
r = RET_NERRNO(symlinkat(target, dt, to));
|
||||
if (copy_flags & COPY_MAC_CREATE)
|
||||
mac_selinux_create_file_clear();
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r < 0) {
|
||||
if (FLAGS_SET(copy_flags, COPY_GRACEFUL_WARN) && (ERRNO_IS_PRIVILEGE(r) || ERRNO_IS_NOT_SUPPORTED(r))) {
|
||||
log_notice_errno(r, "Failed to copy symlink '%s', ignoring: %m", from);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
if (fchownat(dt, to,
|
||||
uid_is_valid(override_uid) ? override_uid : st->st_uid,
|
||||
@@ -798,11 +804,17 @@ static int fd_copy_fifo(
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = mkfifoat(dt, to, st->st_mode & 07777);
|
||||
r = RET_NERRNO(mkfifoat(dt, to, st->st_mode & 07777));
|
||||
if (copy_flags & COPY_MAC_CREATE)
|
||||
mac_selinux_create_file_clear();
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r < 0) {
|
||||
if (FLAGS_SET(copy_flags, COPY_GRACEFUL_WARN) && (ERRNO_IS_PRIVILEGE(r) || ERRNO_IS_NOT_SUPPORTED(r))) {
|
||||
log_notice_errno(r, "Failed to copy fifo '%s', ignoring: %m", from);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
if (fchownat(dt, to,
|
||||
uid_is_valid(override_uid) ? override_uid : st->st_uid,
|
||||
@@ -846,11 +858,17 @@ static int fd_copy_node(
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
r = mknodat(dt, to, st->st_mode, st->st_rdev);
|
||||
r = RET_NERRNO(mknodat(dt, to, st->st_mode, st->st_rdev));
|
||||
if (copy_flags & COPY_MAC_CREATE)
|
||||
mac_selinux_create_file_clear();
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
if (r < 0) {
|
||||
if (FLAGS_SET(copy_flags, COPY_GRACEFUL_WARN) && (ERRNO_IS_PRIVILEGE(r) || ERRNO_IS_NOT_SUPPORTED(r))) {
|
||||
log_notice_errno(r, "Failed to copy node '%s', ignoring: %m", from);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
if (fchownat(dt, to,
|
||||
uid_is_valid(override_uid) ? override_uid : st->st_uid,
|
||||
|
||||
+16
-15
@@ -12,21 +12,22 @@
|
||||
#include "set.h"
|
||||
|
||||
typedef enum CopyFlags {
|
||||
COPY_REFLINK = 1 << 0, /* Try to reflink */
|
||||
COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
|
||||
COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
|
||||
COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
|
||||
COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
|
||||
COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */
|
||||
COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */
|
||||
COPY_SIGTERM = 1 << 7, /* ditto, but for SIGTERM */
|
||||
COPY_MAC_CREATE = 1 << 8, /* Create files with the correct MAC label (currently SELinux only) */
|
||||
COPY_HARDLINKS = 1 << 9, /* Try to reproduce hard links */
|
||||
COPY_FSYNC = 1 << 10, /* fsync() after we are done */
|
||||
COPY_FSYNC_FULL = 1 << 11, /* fsync_full() after we are done */
|
||||
COPY_SYNCFS = 1 << 12, /* syncfs() the *top-level* dir after we are done */
|
||||
COPY_ALL_XATTRS = 1 << 13, /* Preserve all xattrs when copying, not just those in the user namespace */
|
||||
COPY_HOLES = 1 << 14, /* Copy holes */
|
||||
COPY_REFLINK = 1 << 0, /* Try to reflink */
|
||||
COPY_MERGE = 1 << 1, /* Merge existing trees with our new one to copy */
|
||||
COPY_REPLACE = 1 << 2, /* Replace an existing file if there's one */
|
||||
COPY_SAME_MOUNT = 1 << 3, /* Don't descend recursively into other file systems, across mount point boundaries */
|
||||
COPY_MERGE_EMPTY = 1 << 4, /* Merge an existing, empty directory with our new tree to copy */
|
||||
COPY_CRTIME = 1 << 5, /* Generate a user.crtime_usec xattr off the source crtime if there is one, on copying */
|
||||
COPY_SIGINT = 1 << 6, /* Check for SIGINT regularly and return EINTR if seen (caller needs to block SIGINT) */
|
||||
COPY_SIGTERM = 1 << 7, /* ditto, but for SIGTERM */
|
||||
COPY_MAC_CREATE = 1 << 8, /* Create files with the correct MAC label (currently SELinux only) */
|
||||
COPY_HARDLINKS = 1 << 9, /* Try to reproduce hard links */
|
||||
COPY_FSYNC = 1 << 10, /* fsync() after we are done */
|
||||
COPY_FSYNC_FULL = 1 << 11, /* fsync_full() after we are done */
|
||||
COPY_SYNCFS = 1 << 12, /* syncfs() the *top-level* dir after we are done */
|
||||
COPY_ALL_XATTRS = 1 << 13, /* Preserve all xattrs when copying, not just those in the user namespace */
|
||||
COPY_HOLES = 1 << 14, /* Copy holes */
|
||||
COPY_GRACEFUL_WARN = 1 << 15, /* Skip copying file types that aren't supported by the target filesystem */
|
||||
} CopyFlags;
|
||||
|
||||
typedef int (*copy_progress_bytes_t)(uint64_t n_bytes, void *userdata);
|
||||
|
||||
Reference in New Issue
Block a user