summaryrefslogtreecommitdiff
path: root/src/import/import-tar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/import/import-tar.c')
-rw-r--r--src/import/import-tar.c91
1 files changed, 55 insertions, 36 deletions
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 7c4e5127a9..bb67862d62 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -15,6 +15,7 @@
#include "import-common.h"
#include "import-compress.h"
#include "import-tar.h"
+#include "install-file.h"
#include "io-util.h"
#include "machine-pool.h"
#include "mkdir.h"
@@ -54,7 +55,7 @@ struct TarImport {
uint64_t written_compressed;
uint64_t written_uncompressed;
- struct stat st;
+ struct stat input_stat;
pid_t tar_pid;
@@ -136,13 +137,13 @@ static void tar_import_report_progress(TarImport *i) {
assert(i);
/* We have no size information, unless the source is a regular file */
- if (!S_ISREG(i->st.st_mode))
+ if (!S_ISREG(i->input_stat.st_mode))
return;
- if (i->written_compressed >= (uint64_t) i->st.st_size)
+ if (i->written_compressed >= (uint64_t) i->input_stat.st_size)
percent = 100;
else
- percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size);
+ percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->input_stat.st_size);
if (percent == i->last_percent)
return;
@@ -157,12 +158,11 @@ static void tar_import_report_progress(TarImport *i) {
}
static int tar_import_finish(TarImport *i) {
+ const char *d;
int r;
assert(i);
assert(i->tar_fd >= 0);
- assert(i->temp_path);
- assert(i->final_path);
i->tar_fd = safe_close(i->tar_fd);
@@ -175,22 +175,20 @@ static int tar_import_finish(TarImport *i) {
return -EPROTO;
}
- r = import_mangle_os_tree(i->temp_path);
+ assert_se(d = i->temp_path ?: i->local);
+
+ r = import_mangle_os_tree(d);
if (r < 0)
return r;
- if (i->flags & IMPORT_READ_ONLY) {
- r = import_make_read_only(i->temp_path);
- if (r < 0)
- return r;
- }
-
- if (i->flags & IMPORT_FORCE)
- (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
-
- r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
+ r = install_file(
+ AT_FDCWD, d,
+ AT_FDCWD, i->final_path,
+ (i->flags & IMPORT_FORCE ? INSTALL_REPLACE : 0) |
+ (i->flags & IMPORT_READ_ONLY ? INSTALL_READ_ONLY : 0) |
+ (i->flags & IMPORT_SYNC ? INSTALL_SYNCFS : 0));
if (r < 0)
- return log_error_errno(r, "Failed to move image into place: %m");
+ return log_error_errno(r, "Failed to move '%s' into place: %m", i->final_path ?: i->local);
i->temp_path = mfree(i->temp_path);
@@ -198,33 +196,54 @@ static int tar_import_finish(TarImport *i) {
}
static int tar_import_fork_tar(TarImport *i) {
+ const char *d, *root;
int r;
assert(i);
-
+ assert(i->local);
assert(!i->final_path);
assert(!i->temp_path);
assert(i->tar_fd < 0);
- i->final_path = path_join(i->image_root, i->local);
- if (!i->final_path)
- return log_oom();
+ if (i->flags & IMPORT_DIRECT) {
+ d = i->local;
+ root = NULL;
+ } else {
+ i->final_path = path_join(i->image_root, i->local);
+ if (!i->final_path)
+ return log_oom();
- r = tempfn_random(i->final_path, NULL, &i->temp_path);
- if (r < 0)
- return log_oom();
+ r = tempfn_random(i->final_path, NULL, &i->temp_path);
+ if (r < 0)
+ return log_oom();
+
+ d = i->temp_path;
+ root = i->image_root;
+ }
+
+ assert(d);
- (void) mkdir_parents_label(i->temp_path, 0700);
+ (void) mkdir_parents_label(d, 0700);
- r = btrfs_subvol_make_fallback(i->temp_path, 0755);
+ if (FLAGS_SET(i->flags, IMPORT_DIRECT|IMPORT_FORCE))
+ (void) rm_rf(d, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
+
+ if (i->flags & IMPORT_BTRFS_SUBVOL)
+ r = btrfs_subvol_make_fallback(d, 0755);
+ else
+ r = mkdir(d, 0755) < 0 ? -errno : 0;
+ if (r == -EEXIST && (i->flags & IMPORT_DIRECT)) /* EEXIST is OK if in direct mode, but not otherwise,
+ * because in that case our temporary path collided */
+ r = 0;
if (r < 0)
- return log_error_errno(r, "Failed to create directory/subvolume %s: %m", i->temp_path);
- if (r > 0) { /* actually btrfs subvol */
- (void) import_assign_pool_quota_and_warn(i->image_root);
- (void) import_assign_pool_quota_and_warn(i->temp_path);
+ return log_error_errno(r, "Failed to create directory/subvolume %s: %m", d);
+ if (r > 0 && (i->flags & IMPORT_BTRFS_QUOTA)) { /* actually btrfs subvol */
+ if (!(i->flags & IMPORT_DIRECT))
+ (void) import_assign_pool_quota_and_warn(root);
+ (void) import_assign_pool_quota_and_warn(d);
}
- i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
+ i->tar_fd = import_fork_tar_x(d, &i->tar_pid);
if (i->tar_fd < 0)
return i->tar_fd;
@@ -327,9 +346,9 @@ int tar_import_start(TarImport *i, int fd, const char *local, ImportFlags flags)
assert(i);
assert(fd >= 0);
assert(local);
- assert(!(flags & ~IMPORT_FLAGS_MASK));
+ assert(!(flags & ~IMPORT_FLAGS_MASK_TAR));
- if (!hostname_is_valid(local, 0))
+ if (!import_validate_local(local, flags))
return -EINVAL;
if (i->input_fd >= 0)
@@ -345,7 +364,7 @@ int tar_import_start(TarImport *i, int fd, const char *local, ImportFlags flags)
i->flags = flags;
- if (fstat(fd, &i->st) < 0)
+ if (fstat(fd, &i->input_stat) < 0)
return -errno;
r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, tar_import_on_input, i);
@@ -361,5 +380,5 @@ int tar_import_start(TarImport *i, int fd, const char *local, ImportFlags flags)
return r;
i->input_fd = fd;
- return r;
+ return 0;
}