diff --git a/src/partition/repart.c b/src/partition/repart.c index 3e88d38205..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); @@ -2846,10 +2847,23 @@ static int do_copy_files(Partition *p, const char *fs) { UID_INVALID, GID_INVALID, COPY_REFLINK|COPY_MERGE|COPY_REPLACE|COPY_SIGINT|COPY_HARDLINKS); if (r < 0) - return log_error_errno(r, "Failed to copy %s%s to %s: %m", strempty(arg_root), *source, *target); + 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"); @@ -2858,13 +2872,13 @@ static int do_copy_files(Partition *p, const char *fs) { if (pfd < 0) return log_error_errno(pfd, "Failed to open parent directory of target: %m"); - tfd = openat(pfd, basename(*target), O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700); + tfd = openat(pfd, fn, O_CREAT|O_EXCL|O_WRONLY|O_CLOEXEC, 0700); if (tfd < 0) return log_error_errno(errno, "Failed to create target file '%s': %m", *target); r = copy_bytes(sfd, tfd, UINT64_MAX, COPY_REFLINK|COPY_SIGINT); if (r < 0) - return log_error_errno(r, "Failed to copy '%s%s' to '%s': %m", strempty(arg_root), *source, *target); + return log_error_errno(r, "Failed to copy '%s' to '%s%s': %m", *source, strempty(arg_root), *target); (void) copy_xattr(sfd, tfd); (void) copy_access(sfd, tfd);