if (errno != ENOENT)
return log_error_errno(errno, "Failed to open destination '%s': %m", arg_target);
- r = copy_tree_at(source_fd, ".", dfd, bn, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS, NULL);
+ r = copy_tree_at(source_fd, ".", dfd, bn, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS, NULL, NULL);
} else
- r = copy_tree_at(source_fd, ".", target_fd, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS, NULL);
+ r = copy_tree_at(source_fd, ".", target_fd, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to copy '%s' to '%s' in image '%s': %m", arg_source, arg_target, arg_image);
assert(root_fd >= 0);
- r = copy_tree_at(AT_FDCWD, skel, root_fd, ".", UID_INVALID, GID_INVALID, COPY_MERGE|COPY_REPLACE, NULL);
+ r = copy_tree_at(AT_FDCWD, skel, root_fd, ".", UID_INVALID, GID_INVALID, COPY_MERGE|COPY_REPLACE, NULL, NULL);
if (r == -ENOENT) {
log_info("Skeleton directory %s missing, ignoring.", skel);
return 0;
BTRFS_SNAPSHOT_FALLBACK_DIRECTORY|
BTRFS_SNAPSHOT_RECURSIVE);
else
- r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS, NULL);
+ r = copy_tree(i->final_path, t, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_HARDLINKS, NULL, NULL);
if (r < 0)
return log_error_errno(r, "Failed to create local image: %m");
* 0 or to the actual UID shift depending on the direction we copy. If no UID shift is set we'll copy
* the UID/GIDs as they are. */
if (copy_from)
- r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags, NULL);
+ r = copy_tree_at(containerfd, container_basename, hostfd, host_basename, uid_shift == 0 ? UID_INVALID : 0, uid_shift == 0 ? GID_INVALID : 0, copy_flags, NULL, NULL);
else
- r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags, NULL);
+ r = copy_tree_at(hostfd, host_basename, containerfd, container_basename, uid_shift == 0 ? UID_INVALID : uid_shift, uid_shift == 0 ? GID_INVALID : uid_shift, copy_flags, NULL, NULL);
hostfd = safe_close(hostfd);
containerfd = safe_close(containerfd);
pfd, fn,
UID_INVALID, GID_INVALID,
COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE,
- denylist);
+ denylist, NULL);
} else
r = copy_tree_at(
sfd, ".",
tfd, ".",
UID_INVALID, GID_INVALID,
COPY_REFLINK|COPY_HOLES|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS|COPY_ALL_XATTRS|COPY_GRACEFUL_WARN|COPY_TRUNCATE,
- denylist);
+ denylist, NULL);
if (r < 0)
return log_error_errno(r, "Failed to copy '%s%s' to '%s%s': %m",
strempty(arg_root), *source, strempty(root), *target);
gid_t override_gid,
CopyFlags copy_flags,
Hashmap *denylist,
+ Set *subvolumes,
HardlinkContext *hardlink_context,
const char *display_path,
copy_progress_path_t progress_path,
gid_t override_gid,
CopyFlags copy_flags,
Hashmap *denylist,
+ Set *subvolumes,
HardlinkContext *hardlink_context,
const char *display_path,
copy_progress_path_t progress_path,
fdt = xopenat_lock(dt, to,
O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW|(exists ? 0 : O_CREAT|O_EXCL),
- (copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0),
+ (copy_flags & COPY_MAC_CREATE ? XO_LABEL : 0)|(set_contains(subvolumes, st) ? XO_SUBVOLUME : 0),
st->st_mode & 07777,
copy_flags & COPY_LOCK_BSD ? LOCK_BSD : LOCK_NONE,
LOCK_EX);
q = fd_copy_tree_generic(dirfd(d), de->d_name, &buf, fdt, de->d_name, original_device,
depth_left-1, override_uid, override_gid, copy_flags & ~COPY_LOCK_BSD,
- denylist, hardlink_context, child_display_path, progress_path,
+ denylist, subvolumes, hardlink_context, child_display_path, progress_path,
progress_bytes, userdata);
if (q == -EINTR) /* Propagate SIGINT/SIGTERM up instantly */
gid_t override_gid,
CopyFlags copy_flags,
Hashmap *denylist,
+ Set *subvolumes,
HardlinkContext *hardlink_context,
const char *display_path,
copy_progress_path_t progress_path,
if (S_ISDIR(st->st_mode))
return fd_copy_directory(df, from, st, dt, to, original_device, depth_left-1, override_uid,
- override_gid, copy_flags, denylist, hardlink_context, display_path,
- progress_path, progress_bytes, userdata);
+ override_gid, copy_flags, denylist, subvolumes, hardlink_context,
+ display_path, progress_path, progress_bytes, userdata);
DenyType t = PTR_TO_INT(hashmap_get(denylist, st));
if (t == DENY_INODE) {
gid_t override_gid,
CopyFlags copy_flags,
Hashmap *denylist,
+ Set *subvolumes,
copy_progress_path_t progress_path,
copy_progress_bytes_t progress_bytes,
void *userdata) {
return -errno;
r = fd_copy_tree_generic(fdf, from, &st, fdt, to, st.st_dev, COPY_DEPTH_MAX, override_uid,
- override_gid, copy_flags, denylist, NULL, NULL, progress_path,
+ override_gid, copy_flags, denylist, subvolumes, NULL, NULL, progress_path,
progress_bytes, userdata);
if (r < 0)
return r;
COPY_DEPTH_MAX,
UID_INVALID, GID_INVALID,
copy_flags,
- NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL,
progress_path,
progress_bytes,
userdata);
return copy_file_atomic_full(from, to, mode, 0, 0, copy_flags, NULL, NULL);
}
-int copy_tree_at_full(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
-static inline int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist) {
- return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, denylist, NULL, NULL, NULL);
+int copy_tree_at_full(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist, Set *subvolumes, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
+static inline int copy_tree_at(int fdf, const char *from, int fdt, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist, Set *subvolumes) {
+ return copy_tree_at_full(fdf, from, fdt, to, override_uid, override_gid, copy_flags, denylist, subvolumes, NULL, NULL, NULL);
}
-static inline int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist) {
- return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, denylist, NULL, NULL, NULL);
+static inline int copy_tree(const char *from, const char *to, uid_t override_uid, gid_t override_gid, CopyFlags copy_flags, Hashmap *denylist, Set *subvolumes) {
+ return copy_tree_at_full(AT_FDCWD, from, AT_FDCWD, to, override_uid, override_gid, copy_flags, denylist, subvolumes, NULL, NULL, NULL);
}
int copy_directory_at_full(int dir_fdf, const char *from, int dir_fdt, const char *to, CopyFlags copy_flags, copy_progress_path_t progress_path, copy_progress_bytes_t progress_bytes, void *userdata);
/* The file exists- now overwrite original contents, and test the COPY_REPLACE flag. */
- assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK, NULL) == -EEXIST);
+ assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK, NULL, NULL) == -EEXIST);
assert_se(read_file_at_and_streq(AT_FDCWD, dst, "foo foo foo\n"));
- assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE, NULL) == 0);
+ assert_se(copy_tree(src, dst, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE, NULL, NULL) == 0);
assert_se(read_file_at_and_streq(AT_FDCWD, dst, "bar bar\n"));
}
assert_se(write_string_file_at(dst, "bar", "dest file 2", WRITE_STRING_FILE_CREATE) == 0);
/* Copying without COPY_REPLACE should fail because the destination file already exists. */
- assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK, NULL) == -EEXIST);
+ assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK, NULL, NULL) == -EEXIST);
assert_se(read_file_at_and_streq(src, "foo", "src file 1\n"));
assert_se(read_file_at_and_streq(src, "bar", "src file 2\n"));
assert_se(read_file_at_and_streq(dst, "foo", "dest file 1\n"));
assert_se(read_file_at_and_streq(dst, "bar", "dest file 2\n"));
- assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_MERGE, NULL) == 0);
+ assert_se(copy_tree_at(src, ".", dst, ".", UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_REPLACE|COPY_MERGE, NULL, NULL) == 0);
assert_se(read_file_at_and_streq(src, "foo", "src file 1\n"));
assert_se(read_file_at_and_streq(src, "bar", "src file 2\n"));
assert_se(hashmap_ensure_put(&denylist, &inode_hash_ops, cp, INT_TO_PTR(DENY_INODE)) >= 0);
TAKE_PTR(cp);
- assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS, denylist) == 0);
+ assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE|COPY_HARDLINKS, denylist, NULL) == 0);
STRV_FOREACH(p, files) {
_cleanup_free_ char *buf = NULL, *f = NULL, *c = NULL;
assert_se(stat(unixsockp, &st) >= 0);
assert_se(S_ISSOCK(st.st_mode));
- assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK, denylist) < 0);
- assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK, denylist) < 0);
+ assert_se(copy_tree(original_dir, copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK, denylist, NULL) < 0);
+ assert_se(copy_tree("/tmp/inexistent/foo/bar/fsdoi", copy_dir, UID_INVALID, GID_INVALID, COPY_REFLINK, denylist, NULL) < 0);
ignorep = strjoina(copy_dir, "ignore/file");
assert_se(RET_NERRNO(access(ignorep, F_OK)) == -ENOENT);
i->uid_set ? i->uid : UID_INVALID,
i->gid_set ? i->gid : GID_INVALID,
COPY_REFLINK | ((i->append_or_force) ? COPY_MERGE : COPY_MERGE_EMPTY) | COPY_MAC_CREATE | COPY_HARDLINKS,
- NULL);
+ NULL, NULL);
fd = openat(dfd, bn, O_NOFOLLOW|O_CLOEXEC|O_PATH);
if (fd < 0) {