summaryrefslogtreecommitdiff
path: root/src/partition
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2021-04-21 23:23:07 +0200
committerLennart Poettering <lennart@poettering.net>2021-04-21 23:30:49 +0200
commitf21a3a82fb6532d0f858c4f59c235af263a4131b (patch)
treefa6fd168e5fe3d2098f8bd516e9f4e2a15710252 /src/partition
parente28190673ca83d62692dae6d791161bece820030 (diff)
downloadsystemd-f21a3a82fb6532d0f858c4f59c235af263a4131b.tar.gz
repart: don't try to extract directory of root dir when copying directories
It's OK to specify the root dir as target directory when copying directories. However, in that case path_extract_filename() is going to fail, because the root dir simply has not filename. Let's address that by moving the call further down into the loop, when we made sure that the target dir doesn't exist yet (the root dir always exists, hence this check is sufficient). Moreover, in the branch for copying regular files, also move the calls down, and generate friendly error messages in case people try to overwrite dirs with regular files (and the root dir is just a special case of a dir). Altogether this makes CopyFiles=/some/place:/ work, i.e. copying some dir on the host into the root dir of the newly created fs. Previously this would fail with an error about the inability to extract a filename from "/", needlessly.
Diffstat (limited to 'src/partition')
-rw-r--r--src/partition/repart.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/src/partition/repart.c b/src/partition/repart.c
index 7809641fc8..3b31109952 100644
--- a/src/partition/repart.c
+++ b/src/partition/repart.c
@@ -2801,15 +2801,6 @@ static int do_copy_files(Partition *p, const char *fs) {
STRV_FOREACH_PAIR(source, target, p->copy_files) {
_cleanup_close_ int sfd = -1, pfd = -1, tfd = -1;
- _cleanup_free_ char *dn = NULL, *fn = NULL;
-
- r = path_extract_directory(*target, &dn);
- if (r < 0)
- return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
-
- r = path_extract_filename(*target, &fn);
- if (r < 0)
- return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
sfd = chase_symlinks_and_open(*source, arg_root, CHASE_PREFIX_ROOT|CHASE_WARN, O_CLOEXEC|O_NOCTTY, NULL);
if (sfd < 0)
@@ -2823,9 +2814,19 @@ static int do_copy_files(Partition *p, const char *fs) {
/* We are looking at a directory */
tfd = chase_symlinks_and_open(*target, fs, CHASE_PREFIX_ROOT|CHASE_WARN, O_RDONLY|O_DIRECTORY|O_CLOEXEC, NULL);
if (tfd < 0) {
+ _cleanup_free_ char *dn = NULL, *fn = NULL;
+
if (tfd != -ENOENT)
return log_error_errno(tfd, "Failed to open target directory '%s': %m", *target);
+ r = path_extract_filename(*target, &fn);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
+
+ r = path_extract_directory(*target, &dn);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
+
r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create parent directory '%s': %m", dn);
@@ -2848,8 +2849,21 @@ static int do_copy_files(Partition *p, const char *fs) {
if (r < 0)
return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target);
} else {
+ _cleanup_free_ char *dn = NULL, *fn = NULL;
+
/* We are looking at a regular file */
+ r = path_extract_filename(*target, &fn);
+ if (r == -EADDRNOTAVAIL || r == O_DIRECTORY)
+ return log_error_errno(SYNTHETIC_ERRNO(EISDIR),
+ "Target path '%s' refers to a directory, but source path '%s' refers to regular file, can't copy.", *target, *source);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract filename from '%s': %m", *target);
+
+ r = path_extract_directory(*target, &dn);
+ if (r < 0)
+ return log_error_errno(r, "Failed to extract directory from '%s': %m", *target);
+
r = mkdir_p_root(fs, dn, UID_INVALID, GID_INVALID, 0755);
if (r < 0)
return log_error_errno(r, "Failed to create parent directory: %m");