diff --git a/src/basic/mountpoint-util.c b/src/basic/mountpoint-util.c index 7c043bb54a..72d2a01af5 100644 --- a/src/basic/mountpoint-util.c +++ b/src/basic/mountpoint-util.c @@ -485,6 +485,22 @@ bool fstype_can_fmask_dmask(const char *fstype) { return streq(fstype, "vfat") || (mount_option_supported(fstype, "fmask", "0177") > 0 && mount_option_supported(fstype, "dmask", "0077") > 0); } +bool fstype_can_ownership(const char *fstype) { + /* File systems which are not known to not support uid/gid ownership. + * For some types, this can be a bit murky. So just exclude the ones that for sure + * don't support with the current implementations in Linux. */ + + return !STR_IN_SET(ASSERT_PTR(fstype), + "adfs", + "exfat", + "fat", + "hfs", + "hpfs", + "msdos", + "ntfs", + "vfat"); +} + bool fstype_can_uid_gid(const char *fstype) { /* All file systems that have a uid=/gid= mount option that fixates the owners of all files and * directories, current and future. Note that this does *not* ask the kernel via diff --git a/src/basic/mountpoint-util.h b/src/basic/mountpoint-util.h index 8cc966751c..dd27f36c2c 100644 --- a/src/basic/mountpoint-util.h +++ b/src/basic/mountpoint-util.h @@ -66,6 +66,7 @@ bool fstype_is_api_vfs(const char *fstype); bool fstype_is_blockdev_backed(const char *fstype); bool fstype_is_ro(const char *fsype); bool fstype_can_discard(const char *fstype); +bool fstype_can_ownership(const char *fstype); bool fstype_can_uid_gid(const char *fstype); bool fstype_can_fmask_dmask(const char *fstype); diff --git a/src/repart/repart.c b/src/repart/repart.c index 6b0422dd6c..879a90e183 100644 --- a/src/repart/repart.c +++ b/src/repart/repart.c @@ -6712,6 +6712,8 @@ static int do_copy_files(Context *context, Partition *p, const char *root) { return log_oom(); } + bool copy_ownership = fstype_can_ownership(p->format); + /* copy_tree_at() automatically copies the permissions of source directories to target directories if * it created them. However, the root directory is created by us, so we have to manually take care * that it is initialized. We use the first source directory targeting "/" as the metadata source for @@ -6733,12 +6735,16 @@ static int do_copy_files(Context *context, Partition *p, const char *root) { return log_error_errno(sfd, "Failed to open source file '%s%s': %m", strempty(arg_copy_source), line->source); (void) copy_xattr(sfd, NULL, rfd, NULL, COPY_ALL_XATTRS); - (void) copy_access(sfd, rfd); + if (copy_ownership) + (void) copy_access(sfd, rfd); (void) copy_times(sfd, rfd, 0); break; } + uid_t uid = copy_ownership ? UID_INVALID : getuid(); + gid_t gid = copy_ownership ? GID_INVALID : getgid(); + FOREACH_ARRAY(line, copy_files, n_copy_files) { _cleanup_hashmap_free_ Hashmap *denylist = NULL; _cleanup_hashmap_free_ Hashmap *subvolumes_by_source_inode = NULL; @@ -6795,14 +6801,14 @@ static int do_copy_files(Context *context, Partition *p, const char *root) { r = copy_tree_at( sfd, ".", pfd, fn, - UID_INVALID, GID_INVALID, + uid, gid, line->flags, denylist, subvolumes_by_source_inode); } else r = copy_tree_at( sfd, ".", tfd, ".", - UID_INVALID, GID_INVALID, + uid, gid, line->flags, denylist, subvolumes_by_source_inode); if (r < 0) @@ -6849,7 +6855,8 @@ static int do_copy_files(Context *context, Partition *p, const char *root) { return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", line->source, strempty(arg_copy_source), line->target); (void) copy_xattr(sfd, NULL, tfd, NULL, COPY_ALL_XATTRS); - (void) copy_access(sfd, tfd); + if (copy_ownership) + (void) copy_access(sfd, tfd); (void) copy_times(sfd, tfd, 0); if (ts != USEC_INFINITY) {