void *userdata) {
_cleanup_close_ int fdf = -EBADF, fdt = -EBADF;
+ unsigned attrs = 0;
int r, q;
assert(st);
if (fdf < 0)
return fdf;
+ r = read_attr_fd(fdf, &attrs);
+ if (r < 0 && !ERRNO_IS_NOT_SUPPORTED(r) && r != -ELOOP)
+ return r;
+
if (copy_flags & COPY_MAC_CREATE) {
r = mac_selinux_create_file_prepare_at(dt, to, S_IFREG);
if (r < 0)
if (fdt < 0)
return -errno;
+ if (attrs != 0)
+ (void) chattr_full(fdt, NULL, attrs, CHATTR_EARLY_FL, NULL, NULL, CHATTR_FALLBACK_BITWISE);
+
r = copy_bytes_full(fdf, fdt, UINT64_MAX, copy_flags, NULL, NULL, progress, userdata);
if (r < 0)
goto fail;
(void) futimens(fdt, (struct timespec[]) { st->st_atim, st->st_mtim });
(void) copy_xattr(fdf, NULL, fdt, NULL, copy_flags);
+ if (attrs != 0)
+ (void) chattr_full(fdt, NULL, attrs, ~CHATTR_EARLY_FL, NULL, NULL, CHATTR_FALLBACK_BITWISE);
+
if (FLAGS_SET(copy_flags, COPY_VERIFY_LINKED)) {
r = fd_verify_linked(fdf);
if (r < 0)
_cleanup_close_ int fdf = -EBADF, fdt = -EBADF;
struct stat st;
+ unsigned attrs = 0;
int r;
assert(dir_fdf >= 0 || dir_fdf == AT_FDCWD);
if (r < 0)
return r;
+ r = read_attr_at(dir_fdf, from, &attrs);
+ if (r < 0 && !ERRNO_IS_NOT_SUPPORTED(r) && r != -ELOOP)
+ return r;
+
WITH_UMASK(0000) {
fdt = xopenat_lock_full(dir_fdt, to,
flags|O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY,
goto fail;
}
- if (chattr_mask != 0)
- (void) chattr_fd(fdt, chattr_flags, chattr_mask & CHATTR_EARLY_FL, NULL);
+ attrs = (attrs & ~chattr_mask) | (chattr_flags & chattr_mask);
+
+ if (attrs != 0)
+ (void) chattr_full(fdt, NULL, attrs, CHATTR_EARLY_FL, NULL, NULL, CHATTR_FALLBACK_BITWISE);
r = copy_bytes_full(fdf, fdt, UINT64_MAX, copy_flags & ~COPY_LOCK_BSD, NULL, NULL, progress_bytes, userdata);
if (r < 0)
goto fail;
}
- if (chattr_mask != 0)
- (void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL);
+ if (attrs != 0)
+ (void) chattr_full(fdt, NULL, attrs, ~CHATTR_EARLY_FL, NULL, NULL, CHATTR_FALLBACK_BITWISE);
if (copy_flags & (COPY_FSYNC|COPY_FSYNC_FULL)) {
if (fsync(fdt) < 0) {
_cleanup_(unlink_and_freep) char *t = NULL;
_cleanup_close_ int fdt = -EBADF;
+ unsigned attrs = 0;
int r;
assert(to);
if (fdt < 0)
return fdt;
- if (chattr_mask != 0)
- (void) chattr_fd(fdt, chattr_flags, chattr_mask & CHATTR_EARLY_FL, NULL);
+ r = read_attr_at(dir_fdf, from, &attrs);
+ if (r < 0 && !ERRNO_IS_NOT_SUPPORTED(r) && r != -ELOOP)
+ return r;
+
+ attrs = (attrs & ~chattr_mask) | (chattr_flags & chattr_mask);
+
+ if (attrs != 0)
+ (void) chattr_full(fdt, NULL, attrs, CHATTR_EARLY_FL, NULL, NULL, CHATTR_FALLBACK_BITWISE);
r = copy_file_fd_at_full(dir_fdf, from, fdt, copy_flags, progress_bytes, userdata);
if (r < 0)
t = mfree(t);
- if (chattr_mask != 0)
- (void) chattr_fd(fdt, chattr_flags, chattr_mask & ~CHATTR_EARLY_FL, NULL);
+ if (attrs != 0)
+ (void) chattr_full(fdt, NULL, attrs, ~CHATTR_EARLY_FL, NULL, NULL, CHATTR_FALLBACK_BITWISE);
r = close_nointr(TAKE_FD(fdt)); /* even if this fails, the fd is now invalidated */
if (r < 0)