From: Daan De Meyer Date: Wed, 30 Nov 2022 16:01:09 +0000 (+0100) Subject: copy: Add COPY_GRACEFUL_WARN X-Git-Tag: v253-rc1~400^2~1 X-Git-Url: http://git-history.diyao.me/?a=commitdiff_plain;h=494f7fc096a43b8ec267483110af30dc0fc2eed6;p=systemd%2F.git 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. --- diff --git a/src/shared/copy.c b/src/shared/copy.c index 2b492c38a5..e6265e2c96 100644 --- a/src/shared/copy.c +++ b/src/shared/copy.c @@ -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, diff --git a/src/shared/copy.h b/src/shared/copy.h index d19361c9a2..1eb6d1ce05 100644 --- a/src/shared/copy.h +++ b/src/shared/copy.h @@ -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);