summaryrefslogtreecommitdiff
path: root/src/import
diff options
context:
space:
mode:
Diffstat (limited to 'src/import')
-rw-r--r--src/import/aufs-util.c74
-rw-r--r--src/import/aufs-util.h24
-rw-r--r--src/import/curl-util.c27
-rw-r--r--src/import/curl-util.h7
-rw-r--r--src/import/export-raw.c18
-rw-r--r--src/import/export-raw.h5
-rw-r--r--src/import/export-tar.c25
-rw-r--r--src/import/export-tar.h5
-rw-r--r--src/import/export.c26
-rw-r--r--src/import/import-common.c26
-rw-r--r--src/import/import-common.h2
-rw-r--r--src/import/import-compress.c5
-rw-r--r--src/import/import-compress.h7
-rw-r--r--src/import/import-raw.c34
-rw-r--r--src/import/import-raw.h5
-rw-r--r--src/import/import-tar.c33
-rw-r--r--src/import/import-tar.h5
-rw-r--r--src/import/import.c32
-rw-r--r--src/import/importd.c170
-rw-r--r--src/import/org.freedesktop.import1.conf4
-rw-r--r--src/import/pull-common.c174
-rw-r--r--src/import/pull-common.h8
-rw-r--r--src/import/pull-dkr.c1335
-rw-r--r--src/import/pull-dkr.h37
-rw-r--r--src/import/pull-job.c11
-rw-r--r--src/import/pull-job.h15
-rw-r--r--src/import/pull-raw.c206
-rw-r--r--src/import/pull-raw.h7
-rw-r--r--src/import/pull-tar.c200
-rw-r--r--src/import/pull-tar.h7
-rw-r--r--src/import/pull.c180
-rw-r--r--src/import/qcow2-util.c9
-rw-r--r--src/import/qcow2-util.h2
-rw-r--r--src/import/test-qcow2.c6
34 files changed, 717 insertions, 2014 deletions
diff --git a/src/import/aufs-util.c b/src/import/aufs-util.c
deleted file mode 100644
index 18c42b8b6d..0000000000
--- a/src/import/aufs-util.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <ftw.h>
-
-#include "util.h"
-#include "rm-rf.h"
-#include "aufs-util.h"
-
-static int nftw_cb(
- const char *fpath,
- const struct stat *sb,
- int flag,
- struct FTW *ftwbuf) {
-
- const char *fn, *original;
- char *p;
- int r;
-
- fn = fpath + ftwbuf->base;
-
- /* We remove all whiteout files, and all whiteouts */
-
- original = startswith(fn, ".wh.");
- if (!original)
- return FTW_CONTINUE;
-
- log_debug("Removing whiteout indicator %s.", fpath);
- r = rm_rf(fpath, REMOVE_ROOT|REMOVE_PHYSICAL);
- if (r < 0)
- return FTW_STOP;
-
- if (!startswith(fn, ".wh..wh.")) {
-
- p = alloca(ftwbuf->base + strlen(original));
- strcpy(mempcpy(p, fpath, ftwbuf->base), original);
-
- log_debug("Removing deleted file %s.", p);
- r = rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL);
- if (r < 0)
- return FTW_STOP;
- }
-
- return FTW_CONTINUE;
-}
-
-int aufs_resolve(const char *path) {
- int r;
-
- errno = 0;
- r = nftw(path, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL);
- if (r == FTW_STOP)
- return errno ? -errno : -EIO;
-
- return 0;
-}
diff --git a/src/import/aufs-util.h b/src/import/aufs-util.h
deleted file mode 100644
index 712fb81cee..0000000000
--- a/src/import/aufs-util.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-#pragma once
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-int aufs_resolve(const char *path);
diff --git a/src/import/curl-util.c b/src/import/curl-util.c
index d390cfb1f3..6990c47f48 100644
--- a/src/import/curl-util.c
+++ b/src/import/curl-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,7 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "alloc-util.h"
#include "curl-util.h"
+#include "fd-util.h"
+#include "string-util.h"
static void curl_glue_check_finished(CurlGlue *g) {
CURLMsg *msg;
@@ -45,9 +46,7 @@ static int curl_glue_on_io(sd_event_source *s, int fd, uint32_t revents, void *u
assert(s);
assert(g);
- translated_fd = PTR_TO_INT(hashmap_get(g->translate_fds, INT_TO_PTR(fd+1)));
- assert(translated_fd > 0);
- translated_fd--;
+ translated_fd = PTR_TO_FD(hashmap_get(g->translate_fds, FD_TO_PTR(fd)));
if ((revents & (EPOLLIN|EPOLLOUT)) == (EPOLLIN|EPOLLOUT))
action = CURL_POLL_INOUT;
@@ -76,7 +75,7 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
assert(curl);
assert(g);
- io = hashmap_get(g->ios, INT_TO_PTR(s+1));
+ io = hashmap_get(g->ios, FD_TO_PTR(s));
if (action == CURL_POLL_REMOVE) {
if (io) {
@@ -88,8 +87,8 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
sd_event_source_set_enabled(io, SD_EVENT_OFF);
sd_event_source_unref(io);
- hashmap_remove(g->ios, INT_TO_PTR(s+1));
- hashmap_remove(g->translate_fds, INT_TO_PTR(fd+1));
+ hashmap_remove(g->ios, FD_TO_PTR(s));
+ hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
safe_close(fd);
}
@@ -138,19 +137,19 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v
if (sd_event_add_io(g->event, &io, fd, events, curl_glue_on_io, g) < 0)
return -1;
- sd_event_source_set_description(io, "curl-io");
+ (void) sd_event_source_set_description(io, "curl-io");
- r = hashmap_put(g->ios, INT_TO_PTR(s+1), io);
+ r = hashmap_put(g->ios, FD_TO_PTR(s), io);
if (r < 0) {
log_oom();
sd_event_source_unref(io);
return -1;
}
- r = hashmap_put(g->translate_fds, INT_TO_PTR(fd+1), INT_TO_PTR(s+1));
+ r = hashmap_put(g->translate_fds, FD_TO_PTR(fd), FD_TO_PTR(s));
if (r < 0) {
log_oom();
- hashmap_remove(g->ios, INT_TO_PTR(s+1));
+ hashmap_remove(g->ios, FD_TO_PTR(s));
sd_event_source_unref(io);
return -1;
}
@@ -205,7 +204,7 @@ static int curl_glue_timer_callback(CURLM *curl, long timeout_ms, void *userdata
if (sd_event_add_time(g->event, &g->timer, clock_boottime_or_monotonic(), usec, 0, curl_glue_on_timer, g) < 0)
return -1;
- sd_event_source_set_description(g->timer, "curl-timer");
+ (void) sd_event_source_set_description(g->timer, "curl-timer");
}
return 0;
@@ -226,7 +225,7 @@ CurlGlue *curl_glue_unref(CurlGlue *g) {
fd = sd_event_source_get_io_fd(io);
assert(fd >= 0);
- hashmap_remove(g->translate_fds, INT_TO_PTR(fd+1));
+ hashmap_remove(g->translate_fds, FD_TO_PTR(fd));
safe_close(fd);
sd_event_source_unref(io);
diff --git a/src/import/curl-util.h b/src/import/curl-util.h
index c249069ffa..a758cc5640 100644
--- a/src/import/curl-util.h
+++ b/src/import/curl-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -21,12 +19,13 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
#include <curl/curl.h>
+#include <sys/types.h>
-#include "hashmap.h"
#include "sd-event.h"
+#include "hashmap.h"
+
typedef struct CurlGlue CurlGlue;
struct CurlGlue {
diff --git a/src/import/export-raw.c b/src/import/export-raw.c
index 8f9c9bbc80..6136b677dd 100644
--- a/src/import/export-raw.c
+++ b/src/import/export-raw.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -20,16 +18,26 @@
***/
#include <sys/sendfile.h>
+
+/* When we include libgen.h because we need dirname() we immediately
+ * undefine basename() since libgen.h defines it as a macro to the POSIX
+ * version which is really broken. We prefer GNU basename(). */
#include <libgen.h>
#undef basename
#include "sd-daemon.h"
-#include "util.h"
-#include "ratelimit.h"
+
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "copy.h"
-#include "import-common.h"
#include "export-raw.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "import-common.h"
+#include "missing.h"
+#include "ratelimit.h"
+#include "string-util.h"
+#include "util.h"
#define COPY_BUFFER_SIZE (16*1024)
diff --git a/src/import/export-raw.h b/src/import/export-raw.h
index b71de6cb82..8e723d4908 100644
--- a/src/import/export-raw.h
+++ b/src/import/export-raw.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,8 +20,9 @@
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-compress.h"
+#include "macro.h"
typedef struct RawExport RawExport;
diff --git a/src/import/export-tar.c b/src/import/export-tar.c
index 5adc748c50..d79c27f2d0 100644
--- a/src/import/export-tar.c
+++ b/src/import/export-tar.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,15 +17,18 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/sendfile.h>
-
#include "sd-daemon.h"
-#include "util.h"
-#include "ratelimit.h"
+
+#include "alloc-util.h"
#include "btrfs-util.h"
-#include "import-common.h"
#include "export-tar.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "import-common.h"
#include "process-util.h"
+#include "ratelimit.h"
+#include "string-util.h"
+#include "util.h"
#define COPY_BUFFER_SIZE (16*1024)
@@ -78,7 +79,7 @@ TarExport *tar_export_unref(TarExport *e) {
}
if (e->temp_path) {
- (void) btrfs_subvol_remove(e->temp_path, false);
+ (void) btrfs_subvol_remove(e->temp_path, BTRFS_REMOVE_QUOTA);
free(e->temp_path);
}
@@ -283,12 +284,11 @@ int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType
if (e->st.st_ino == 256) { /* might be a btrfs subvolume? */
BtrfsQuotaInfo q;
- r = btrfs_subvol_get_quota_fd(sfd, &q);
+ r = btrfs_subvol_get_subtree_quota_fd(sfd, 0, &q);
if (r >= 0)
e->quota_referenced = q.referenced;
- free(e->temp_path);
- e->temp_path = NULL;
+ e->temp_path = mfree(e->temp_path);
r = tempfn_random(path, NULL, &e->temp_path);
if (r < 0)
@@ -298,8 +298,7 @@ int tar_export_start(TarExport *e, const char *path, int fd, ImportCompressType
r = btrfs_subvol_snapshot_fd(sfd, e->temp_path, BTRFS_SNAPSHOT_READ_ONLY|BTRFS_SNAPSHOT_RECURSIVE);
if (r < 0) {
log_debug_errno(r, "Couldn't create snapshot %s of %s, not exporting atomically: %m", e->temp_path, path);
- free(e->temp_path);
- e->temp_path = NULL;
+ e->temp_path = mfree(e->temp_path);
}
}
diff --git a/src/import/export-tar.h b/src/import/export-tar.h
index ce27a9fc1e..1e3c8bb80c 100644
--- a/src/import/export-tar.h
+++ b/src/import/export-tar.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,8 +20,9 @@
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-compress.h"
+#include "macro.h"
typedef struct TarExport TarExport;
diff --git a/src/import/export.c b/src/import/export.c
index ec7dbe210a..cc98c33ef6 100644
--- a/src/import/export.c
+++ b/src/import/export.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,14 +20,18 @@
#include <getopt.h>
#include "sd-event.h"
-#include "event-util.h"
+
+#include "alloc-util.h"
+#include "export-raw.h"
+#include "export-tar.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "hostname-util.h"
+#include "import-util.h"
+#include "machine-image.h"
#include "signal-util.h"
+#include "string-util.h"
#include "verbs.h"
-#include "build.h"
-#include "machine-image.h"
-#include "import-util.h"
-#include "export-tar.h"
-#include "export-raw.h"
static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN;
@@ -71,7 +73,7 @@ static void on_tar_finished(TarExport *export, int error, void *userdata) {
static int export_tar(int argc, char *argv[], void *userdata) {
_cleanup_(tar_export_unrefp) TarExport *export = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(image_unrefp) Image *image = NULL;
const char *path = NULL, *local = NULL;
_cleanup_close_ int open_fd = -1;
@@ -150,7 +152,7 @@ static void on_raw_finished(RawExport *export, int error, void *userdata) {
static int export_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_export_unrefp) RawExport *export = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
_cleanup_(image_unrefp) Image *image = NULL;
const char *path = NULL, *local = NULL;
_cleanup_close_ int open_fd = -1;
@@ -259,9 +261,7 @@ static int parse_argv(int argc, char *argv[]) {
return help(0, NULL, NULL);
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_FORMAT:
if (streq(optarg, "uncompressed"))
diff --git a/src/import/import-common.c b/src/import/import-common.c
index 950c7b4acd..81209cdaf6 100644
--- a/src/import/import-common.c
+++ b/src/import/import-common.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,15 +17,17 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include <sched.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <unistd.h>
-#include "util.h"
#include "btrfs-util.h"
-#include "capability.h"
-#include "signal-util.h"
+#include "capability-util.h"
+#include "fd-util.h"
#include "import-common.h"
+#include "signal-util.h"
+#include "util.h"
int import_make_read_only_fd(int fd) {
int r;
@@ -125,18 +125,16 @@ int import_fork_tar_x(const char *path, pid_t *ret) {
if (null_fd != STDOUT_FILENO)
null_fd = safe_close(null_fd);
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
+ stdio_unset_cloexec();
if (unshare(CLONE_NEWNET) < 0)
log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
- r = capability_bounding_set_drop(~retain, true);
+ r = capability_bounding_set_drop(retain, true);
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", NULL);
+ execlp("tar", "tar", "--numeric-owner", "-C", path, "-px", "--xattrs", "--xattrs-include=*", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
@@ -199,18 +197,16 @@ int import_fork_tar_c(const char *path, pid_t *ret) {
if (null_fd != STDIN_FILENO)
null_fd = safe_close(null_fd);
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
+ stdio_unset_cloexec();
if (unshare(CLONE_NEWNET) < 0)
log_error_errno(errno, "Failed to lock tar into network namespace, ignoring: %m");
- r = capability_bounding_set_drop(~retain, true);
+ r = capability_bounding_set_drop(retain, true);
if (r < 0)
log_error_errno(r, "Failed to drop capabilities, ignoring: %m");
- execlp("tar", "tar", "--sparse", "-C", path, "-c", ".", NULL);
+ execlp("tar", "tar", "-C", path, "-c", "--xattrs", "--xattrs-include=*", ".", NULL);
log_error_errno(errno, "Failed to execute tar: %m");
_exit(EXIT_FAILURE);
}
diff --git a/src/import/import-common.h b/src/import/import-common.h
index 7b60de80c2..07d3250e71 100644
--- a/src/import/import-common.h
+++ b/src/import/import-common.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/import/import-compress.c b/src/import/import-compress.c
index d6b8133036..f1766bbe3b 100644
--- a/src/import/import-compress.c
+++ b/src/import/import-compress.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,8 +17,9 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include "util.h"
#include "import-compress.h"
+#include "string-table.h"
+#include "util.h"
void import_compress_free(ImportCompress *c) {
assert(c);
diff --git a/src/import/import-compress.h b/src/import/import-compress.h
index 50d91f732c..6b59d0724b 100644
--- a/src/import/import-compress.h
+++ b/src/import/import-compress.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -21,11 +19,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/types.h>
-
+#include <bzlib.h>
#include <lzma.h>
+#include <sys/types.h>
#include <zlib.h>
-#include <bzlib.h>
#include "macro.h"
diff --git a/src/import/import-raw.c b/src/import/import-raw.c
index 43cd413042..fd6b9f7703 100644
--- a/src/import/import-raw.c
+++ b/src/import/import-raw.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -23,18 +21,27 @@
#include "sd-daemon.h"
#include "sd-event.h"
-#include "util.h"
-#include "path-util.h"
+
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "chattr-util.h"
#include "copy.h"
-#include "mkdir.h"
-#include "rm-rf.h"
-#include "ratelimit.h"
-#include "machine-pool.h"
-#include "qcow2-util.h"
-#include "import-compress.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "hostname-util.h"
#include "import-common.h"
+#include "import-compress.h"
#include "import-raw.h"
+#include "io-util.h"
+#include "machine-pool.h"
+#include "mkdir.h"
+#include "path-util.h"
+#include "qcow2-util.h"
+#include "ratelimit.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "util.h"
struct RawImport {
sd_event *event;
@@ -190,7 +197,7 @@ static int raw_import_maybe_convert_qcow2(RawImport *i) {
r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL);
if (r < 0)
- log_warning_errno(errno, "Failed to set file attributes on %s: %m", t);
+ log_warning_errno(r, "Failed to set file attributes on %s: %m", t);
log_info("Unpacking QCOW2 file.");
@@ -248,8 +255,7 @@ static int raw_import_finish(RawImport *i) {
if (r < 0)
return log_error_errno(r, "Failed to move image into place: %m");
- free(i->temp_path);
- i->temp_path = NULL;
+ i->temp_path = mfree(i->temp_path);
return 0;
}
@@ -279,7 +285,7 @@ static int raw_import_open_disk(RawImport *i) {
r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL);
if (r < 0)
- log_warning_errno(errno, "Failed to set file attributes on %s: %m", i->temp_path);
+ log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path);
return 0;
}
diff --git a/src/import/import-raw.h b/src/import/import-raw.h
index bf7c770340..4f543e0883 100644
--- a/src/import/import-raw.h
+++ b/src/import/import-raw.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,8 +20,9 @@
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct RawImport RawImport;
diff --git a/src/import/import-tar.c b/src/import/import-tar.c
index 2bf0b0680c..8b81324fde 100644
--- a/src/import/import-tar.c
+++ b/src/import/import-tar.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -23,19 +21,27 @@
#include "sd-daemon.h"
#include "sd-event.h"
-#include "util.h"
-#include "path-util.h"
+
+#include "alloc-util.h"
#include "btrfs-util.h"
#include "copy.h"
-#include "mkdir.h"
-#include "rm-rf.h"
-#include "ratelimit.h"
-#include "machine-pool.h"
-#include "qcow2-util.h"
-#include "import-compress.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "hostname-util.h"
#include "import-common.h"
+#include "import-compress.h"
#include "import-tar.h"
+#include "io-util.h"
+#include "machine-pool.h"
+#include "mkdir.h"
+#include "path-util.h"
#include "process-util.h"
+#include "qcow2-util.h"
+#include "ratelimit.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "util.h"
struct TarImport {
sd_event *event;
@@ -204,8 +210,7 @@ static int tar_import_finish(TarImport *i) {
if (r < 0)
return log_error_errno(r, "Failed to move image into place: %m");
- free(i->temp_path);
- i->temp_path = NULL;
+ i->temp_path = mfree(i->temp_path);
return 0;
}
@@ -234,7 +239,9 @@ static int tar_import_fork_tar(TarImport *i) {
if (mkdir(i->temp_path, 0755) < 0)
return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path);
} else if (r < 0)
- return log_error_errno(errno, "Failed to create subvolume %s: %m", i->temp_path);
+ return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path);
+ else
+ (void) import_assign_pool_quota_and_warn(i->temp_path);
i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
if (i->tar_fd < 0)
diff --git a/src/import/import-tar.h b/src/import/import-tar.h
index aaecb51398..24abe06c8f 100644
--- a/src/import/import-tar.h
+++ b/src/import/import-tar.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,8 +20,9 @@
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct TarImport TarImport;
diff --git a/src/import/import.c b/src/import/import.c
index b7772390e9..2b6ca24af8 100644
--- a/src/import/import.c
+++ b/src/import/import.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,14 +20,18 @@
#include <getopt.h>
#include "sd-event.h"
-#include "event-util.h"
-#include "verbs.h"
-#include "build.h"
-#include "signal-util.h"
-#include "machine-image.h"
-#include "import-util.h"
-#include "import-tar.h"
+
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "fs-util.h"
+#include "hostname-util.h"
#include "import-raw.h"
+#include "import-tar.h"
+#include "import-util.h"
+#include "machine-image.h"
+#include "signal-util.h"
+#include "string-util.h"
+#include "verbs.h"
static bool arg_force = false;
static bool arg_read_only = false;
@@ -53,7 +55,7 @@ static void on_tar_finished(TarImport *import, int error, void *userdata) {
static int import_tar(int argc, char *argv[], void *userdata) {
_cleanup_(tar_import_unrefp) TarImport *import = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
const char *path = NULL, *local = NULL;
_cleanup_free_ char *ll = NULL;
_cleanup_close_ int open_fd = -1;
@@ -88,7 +90,7 @@ static int import_tar(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
else if (r > 0) {
- log_error_errno(EEXIST, "Image '%s' already exists.", local);
+ log_error("Image '%s' already exists.", local);
return -EEXIST;
}
}
@@ -148,7 +150,7 @@ static void on_raw_finished(RawImport *import, int error, void *userdata) {
static int import_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_import_unrefp) RawImport *import = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
const char *path = NULL, *local = NULL;
_cleanup_free_ char *ll = NULL;
_cleanup_close_ int open_fd = -1;
@@ -183,7 +185,7 @@ static int import_raw(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
else if (r > 0) {
- log_error_errno(EEXIST, "Image '%s' already exists.", local);
+ log_error("Image '%s' already exists.", local);
return -EEXIST;
}
}
@@ -279,9 +281,7 @@ static int parse_argv(int argc, char *argv[]) {
return help(0, NULL, NULL);
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_FORCE:
arg_force = true;
diff --git a/src/import/importd.c b/src/import/importd.c
index dd314f5b00..28b4302cb3 100644
--- a/src/import/importd.c
+++ b/src/import/importd.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,19 +20,28 @@
#include <sys/prctl.h>
#include "sd-bus.h"
-#include "util.h"
-#include "strv.h"
-#include "bus-util.h"
+
+#include "alloc-util.h"
#include "bus-common-errors.h"
-#include "socket-util.h"
-#include "mkdir.h"
+#include "bus-util.h"
#include "def.h"
-#include "missing.h"
+#include "fd-util.h"
+#include "hostname-util.h"
+#include "import-util.h"
#include "machine-pool.h"
+#include "missing.h"
+#include "mkdir.h"
+#include "parse-util.h"
#include "path-util.h"
-#include "import-util.h"
#include "process-util.h"
#include "signal-util.h"
+#include "socket-util.h"
+#include "string-table.h"
+#include "strv.h"
+#include "syslog-util.h"
+#include "user-util.h"
+#include "util.h"
+#include "web-util.h"
typedef struct Transfer Transfer;
typedef struct Manager Manager;
@@ -46,7 +53,6 @@ typedef enum TransferType {
TRANSFER_EXPORT_RAW,
TRANSFER_PULL_TAR,
TRANSFER_PULL_RAW,
- TRANSFER_PULL_DKR,
_TRANSFER_TYPE_MAX,
_TRANSFER_TYPE_INVALID = -1,
} TransferType;
@@ -65,7 +71,6 @@ struct Transfer {
bool force_local;
bool read_only;
- char *dkr_index_url;
char *format;
pid_t pid;
@@ -108,7 +113,6 @@ static const char* const transfer_type_table[_TRANSFER_TYPE_MAX] = {
[TRANSFER_EXPORT_RAW] = "export-raw",
[TRANSFER_PULL_TAR] = "pull-tar",
[TRANSFER_PULL_RAW] = "pull-raw",
- [TRANSFER_PULL_DKR] = "pull-dkr",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(transfer_type, TransferType);
@@ -125,7 +129,6 @@ static Transfer *transfer_unref(Transfer *t) {
free(t->remote);
free(t->local);
- free(t->dkr_index_url);
free(t->format);
free(t->object_path);
@@ -166,6 +169,7 @@ static int transfer_new(Manager *m, Transfer **ret) {
t->type = _TRANSFER_TYPE_INVALID;
t->log_fd = -1;
t->stdin_fd = -1;
+ t->stdout_fd = -1;
t->verify = _IMPORT_VERIFY_INVALID;
id = m->current_transfer_id + 1;
@@ -373,12 +377,11 @@ static int transfer_start(Transfer *t) {
if (t->pid == 0) {
const char *cmd[] = {
NULL, /* systemd-import, systemd-export or systemd-pull */
- NULL, /* tar, raw, dkr */
+ NULL, /* tar, raw */
NULL, /* --verify= */
NULL, /* verify argument */
NULL, /* maybe --force */
NULL, /* maybe --read-only */
- NULL, /* maybe --dkr-index-url */
NULL, /* if so: the actual URL */
NULL, /* maybe --format= */
NULL, /* if so: the actual format */
@@ -445,9 +448,7 @@ static int transfer_start(Transfer *t) {
safe_close(null_fd);
}
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
+ stdio_unset_cloexec();
setenv("SYSTEMD_LOG_TARGET", "console-prefixed", 1);
setenv("NOTIFY_SOCKET", "/run/systemd/import/notify", 1);
@@ -461,10 +462,8 @@ static int transfer_start(Transfer *t) {
if (IN_SET(t->type, TRANSFER_IMPORT_TAR, TRANSFER_EXPORT_TAR, TRANSFER_PULL_TAR))
cmd[k++] = "tar";
- else if (IN_SET(t->type, TRANSFER_IMPORT_RAW, TRANSFER_EXPORT_RAW, TRANSFER_PULL_RAW))
- cmd[k++] = "raw";
else
- cmd[k++] = "dkr";
+ cmd[k++] = "raw";
if (t->verify != _IMPORT_VERIFY_INVALID) {
cmd[k++] = "--verify";
@@ -476,11 +475,6 @@ static int transfer_start(Transfer *t) {
if (t->read_only)
cmd[k++] = "--read-only";
- if (t->dkr_index_url) {
- cmd[k++] = "--dkr-index-url";
- cmd[k++] = t->dkr_index_url;
- }
-
if (t->format) {
cmd[k++] = "--format";
cmd[k++] = t->format;
@@ -598,14 +592,11 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
cmsg_close_all(&msghdr);
- CMSG_FOREACH(cmsg, &msghdr) {
+ CMSG_FOREACH(cmsg, &msghdr)
if (cmsg->cmsg_level == SOL_SOCKET &&
- cmsg->cmsg_type == SCM_CREDENTIALS &&
- cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
-
+ cmsg->cmsg_type == SCM_CREDENTIALS &&
+ cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
ucred = (struct ucred*) CMSG_DATA(cmsg);
- }
- }
if (msghdr.msg_flags & MSG_TRUNC) {
log_warning("Got overly long notification datagram, ignoring.");
@@ -684,7 +675,7 @@ static int manager_new(Manager **ret) {
(void) mkdir_parents_label(sa.un.sun_path, 0755);
(void) unlink(sa.un.sun_path);
- if (bind(m->notify_fd, &sa.sa, offsetof(union sockaddr_union, un.sun_path) + strlen(sa.un.sun_path)) < 0)
+ if (bind(m->notify_fd, &sa.sa, SOCKADDR_UN_LEN(sa.un)) < 0)
return -errno;
if (setsockopt(m->notify_fd, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
@@ -700,7 +691,7 @@ static int manager_new(Manager **ret) {
return 0;
}
-static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_index_url, const char *remote) {
+static Transfer *manager_find(Manager *m, TransferType type, const char *remote) {
Transfer *t;
Iterator i;
@@ -711,8 +702,7 @@ static Transfer *manager_find(Manager *m, TransferType type, const char *dkr_ind
HASHMAP_FOREACH(t, m->transfers, i) {
if (t->type == type &&
- streq_ptr(t->remote, remote) &&
- streq_ptr(t->dkr_index_url, dkr_index_url))
+ streq_ptr(t->remote, remote))
return t;
}
@@ -734,6 +724,7 @@ static int method_import_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
msg,
CAP_SYS_ADMIN,
"org.freedesktop.import1.import",
+ NULL,
false,
UID_INVALID,
&m->polkit_registry,
@@ -798,6 +789,7 @@ static int method_export_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_
msg,
CAP_SYS_ADMIN,
"org.freedesktop.import1.export",
+ NULL,
false,
UID_INVALID,
&m->polkit_registry,
@@ -863,6 +855,7 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
msg,
CAP_SYS_ADMIN,
"org.freedesktop.import1.pull",
+ NULL,
false,
UID_INVALID,
&m->polkit_registry,
@@ -897,7 +890,7 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
type = streq_ptr(sd_bus_message_get_member(msg), "PullTar") ? TRANSFER_PULL_TAR : TRANSFER_PULL_RAW;
- if (manager_find(m, type, NULL, remote))
+ if (manager_find(m, type, remote))
return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote);
r = transfer_new(m, &t);
@@ -929,106 +922,8 @@ static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_er
return sd_bus_reply_method_return(msg, "uo", id, object);
}
-static int method_pull_dkr(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
- _cleanup_(transfer_unrefp) Transfer *t = NULL;
- const char *index_url, *remote, *tag, *local, *verify, *object;
- Manager *m = userdata;
- ImportVerify v;
- int force, r;
- uint32_t id;
-
- assert(msg);
- assert(m);
-
- r = bus_verify_polkit_async(
- msg,
- CAP_SYS_ADMIN,
- "org.freedesktop.import1.pull",
- false,
- UID_INVALID,
- &m->polkit_registry,
- error);
- if (r < 0)
- return r;
- if (r == 0)
- return 1; /* Will call us back */
-
- r = sd_bus_message_read(msg, "sssssb", &index_url, &remote, &tag, &local, &verify, &force);
- if (r < 0)
- return r;
-
- if (isempty(index_url))
- index_url = DEFAULT_DKR_INDEX_URL;
- if (!index_url)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL must be specified.");
- if (!http_url_is_valid(index_url))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Index URL %s is invalid", index_url);
-
- if (!dkr_name_is_valid(remote))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Remote name %s is not valid", remote);
-
- if (isempty(tag))
- tag = "latest";
- else if (!dkr_tag_is_valid(tag))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Tag %s is not valid", tag);
-
- if (isempty(local))
- local = NULL;
- else if (!machine_name_is_valid(local))
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Local name %s is invalid", local);
-
- if (isempty(verify))
- v = IMPORT_VERIFY_SIGNATURE;
- else
- v = import_verify_from_string(verify);
- if (v < 0)
- return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown verification mode %s", verify);
-
- if (v != IMPORT_VERIFY_NO)
- return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "DKR does not support verification.");
-
- r = setup_machine_directory((uint64_t) -1, error);
- if (r < 0)
- return r;
-
- if (manager_find(m, TRANSFER_PULL_DKR, index_url, remote))
- return sd_bus_error_setf(error, BUS_ERROR_TRANSFER_IN_PROGRESS, "Transfer for %s already in progress.", remote);
-
- r = transfer_new(m, &t);
- if (r < 0)
- return r;
-
- t->type = TRANSFER_PULL_DKR;
- t->verify = v;
- t->force_local = force;
-
- t->dkr_index_url = strdup(index_url);
- if (!t->dkr_index_url)
- return -ENOMEM;
-
- t->remote = strjoin(remote, ":", tag, NULL);
- if (!t->remote)
- return -ENOMEM;
-
- if (local) {
- t->local = strdup(local);
- if (!t->local)
- return -ENOMEM;
- }
-
- r = transfer_start(t);
- if (r < 0)
- return r;
-
- object = t->object_path;
- id = t->id;
- t = NULL;
-
- return sd_bus_reply_method_return(msg, "uo", id, object);
-}
-
static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
- _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+ _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
Manager *m = userdata;
Transfer *t;
Iterator i;
@@ -1078,6 +973,7 @@ static int method_cancel(sd_bus_message *msg, void *userdata, sd_bus_error *erro
msg,
CAP_SYS_ADMIN,
"org.freedesktop.import1.pull",
+ NULL,
false,
UID_INVALID,
&t->manager->polkit_registry,
@@ -1107,6 +1003,7 @@ static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_er
msg,
CAP_SYS_ADMIN,
"org.freedesktop.import1.pull",
+ NULL,
false,
UID_INVALID,
&m->polkit_registry,
@@ -1175,7 +1072,6 @@ static const sd_bus_vtable manager_vtable[] = {
SD_BUS_METHOD("ExportRaw", "shs", "uo", method_export_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PullTar", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PullRaw", "sssb", "uo", method_pull_tar_or_raw, SD_BUS_VTABLE_UNPRIVILEGED),
- SD_BUS_METHOD("PullDkr", "sssssb", "uo", method_pull_dkr, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListTransfers", NULL, "a(usssdo)", method_list_transfers, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelTransfer", "u", NULL, method_cancel_transfer, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("TransferNew", "uo", 0),
diff --git a/src/import/org.freedesktop.import1.conf b/src/import/org.freedesktop.import1.conf
index ae36af422f..ed2539a03b 100644
--- a/src/import/org.freedesktop.import1.conf
+++ b/src/import/org.freedesktop.import1.conf
@@ -53,10 +53,6 @@
send_member="PullRaw"/>
<allow send_destination="org.freedesktop.import1"
- send_interface="org.freedesktop.import1.Manager"
- send_member="PullDkr"/>
-
- <allow send_destination="org.freedesktop.import1"
send_interface="org.freedesktop.import1.Transfer"
send_member="Cancel"/>
diff --git a/src/import/pull-common.c b/src/import/pull-common.c
index 652277e4be..2ae2a4174c 100644
--- a/src/import/pull-common.c
+++ b/src/import/pull-common.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,20 +19,37 @@
#include <sys/prctl.h>
-#include "util.h"
-#include "strv.h"
-#include "copy.h"
-#include "rm-rf.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
-#include "capability.h"
-#include "pull-job.h"
-#include "pull-common.h"
+#include "capability-util.h"
+#include "copy.h"
+#include "dirent-util.h"
+#include "escape.h"
+#include "fd-util.h"
+#include "io-util.h"
+#include "path-util.h"
#include "process-util.h"
+#include "pull-common.h"
+#include "pull-job.h"
+#include "rm-rf.h"
#include "signal-util.h"
+#include "siphash24.h"
+#include "string-util.h"
+#include "strv.h"
+#include "util.h"
+#include "web-util.h"
#define FILENAME_ESCAPE "/.#\"\'"
+#define HASH_URL_THRESHOLD_LENGTH (_POSIX_PATH_MAX - 16)
+
+int pull_find_old_etags(
+ const char *url,
+ const char *image_root,
+ int dt,
+ const char *prefix,
+ const char *suffix,
+ char ***etags) {
-int pull_find_old_etags(const char *url, const char *image_root, int dt, const char *prefix, const char *suffix, char ***etags) {
_cleanup_free_ char *escaped_url = NULL;
_cleanup_closedir_ DIR *d = NULL;
_cleanup_strv_free_ char **l = NULL;
@@ -129,7 +144,7 @@ int pull_make_local_copy(const char *final, const char *image_root, const char *
if (force_local)
(void) rm_rf(p, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
- r = btrfs_subvol_snapshot(final, p, 0);
+ r = btrfs_subvol_snapshot(final, p, BTRFS_SNAPSHOT_QUOTA);
if (r == -ENOTTY) {
r = copy_tree(final, p, false);
if (r < 0)
@@ -142,8 +157,21 @@ int pull_make_local_copy(const char *final, const char *image_root, const char *
return 0;
}
+static int hash_url(const char *url, char **ret) {
+ uint64_t h;
+ static const sd_id128_t k = SD_ID128_ARRAY(df,89,16,87,01,cc,42,30,98,ab,4a,19,a6,a5,63,4f);
+
+ assert(url);
+
+ h = siphash24(url, strlen(url), k.bytes);
+ if (asprintf(ret, "%"PRIx64, h) < 0)
+ return -ENOMEM;
+
+ return 0;
+}
+
int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret) {
- _cleanup_free_ char *escaped_url = NULL;
+ _cleanup_free_ char *escaped_url = NULL, *escaped_etag = NULL;
char *path;
assert(url);
@@ -157,22 +185,82 @@ int pull_make_path(const char *url, const char *etag, const char *image_root, co
return -ENOMEM;
if (etag) {
- _cleanup_free_ char *escaped_etag = NULL;
-
escaped_etag = xescape(etag, FILENAME_ESCAPE);
if (!escaped_etag)
return -ENOMEM;
+ }
- path = strjoin(image_root, "/", strempty(prefix), escaped_url, ".", escaped_etag, strempty(suffix), NULL);
- } else
- path = strjoin(image_root, "/", strempty(prefix), escaped_url, strempty(suffix), NULL);
+ path = strjoin(image_root, "/", strempty(prefix), escaped_url, escaped_etag ? "." : "",
+ strempty(escaped_etag), strempty(suffix), NULL);
if (!path)
return -ENOMEM;
+ /* URLs might make the path longer than the maximum allowed length for a file name.
+ * When that happens, a URL hash is used instead. Paths returned by this function
+ * can be later used with tempfn_random() which adds 16 bytes to the resulting name. */
+ if (strlen(path) >= HASH_URL_THRESHOLD_LENGTH) {
+ _cleanup_free_ char *hash = NULL;
+ int r;
+
+ free(path);
+
+ r = hash_url(url, &hash);
+ if (r < 0)
+ return r;
+
+ path = strjoin(image_root, "/", strempty(prefix), hash, escaped_etag ? "." : "",
+ strempty(escaped_etag), strempty(suffix), NULL);
+ if (!path)
+ return -ENOMEM;
+ }
+
*ret = path;
return 0;
}
+int pull_make_settings_job(
+ PullJob **ret,
+ const char *url,
+ CurlGlue *glue,
+ PullJobFinished on_finished,
+ void *userdata) {
+
+ _cleanup_free_ char *last_component = NULL, *ll = NULL, *settings_url = NULL;
+ _cleanup_(pull_job_unrefp) PullJob *job = NULL;
+ const char *q;
+ int r;
+
+ assert(ret);
+ assert(url);
+ assert(glue);
+
+ r = import_url_last_component(url, &last_component);
+ if (r < 0)
+ return r;
+
+ r = tar_strip_suffixes(last_component, &ll);
+ if (r < 0)
+ return r;
+
+ q = strjoina(ll, ".nspawn");
+
+ r = import_url_change_last_component(url, q, &settings_url);
+ if (r < 0)
+ return r;
+
+ r = pull_job_new(&job, settings_url, glue, userdata);
+ if (r < 0)
+ return r;
+
+ job->on_finished = on_finished;
+ job->compressed_max = job->uncompressed_max = 1ULL * 1024ULL * 1024ULL;
+
+ *ret = job;
+ job = NULL;
+
+ return 0;
+}
+
int pull_make_verification_jobs(
PullJob **ret_checksum_job,
PullJob **ret_signature_job,
@@ -232,8 +320,8 @@ int pull_make_verification_jobs(
return 0;
}
-int pull_verify(
- PullJob *main_job,
+int pull_verify(PullJob *main_job,
+ PullJob *settings_job,
PullJob *checksum_job,
PullJob *signature_job) {
@@ -242,7 +330,7 @@ int pull_verify(
_cleanup_close_ int sig_file = -1;
const char *p, *line;
char sig_file_path[] = "/tmp/sigXXXXXX", gpg_home[] = "/tmp/gpghomeXXXXXX";
- _cleanup_sigkill_wait_ pid_t pid = 0;
+ _cleanup_(sigkill_waitp) pid_t pid = 0;
bool gpg_home_created = false;
int r;
@@ -278,12 +366,48 @@ int pull_verify(
strlen(line));
if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) {
- log_error("Checksum did not check out, payload has been tempered with.");
+ log_error("DOWNLOAD INVALID: Checksum did not check out, payload has been tampered with.");
return -EBADMSG;
}
log_info("SHA256 checksum of %s is valid.", main_job->url);
+ assert(!settings_job || IN_SET(settings_job->state, PULL_JOB_DONE, PULL_JOB_FAILED));
+
+ if (settings_job &&
+ settings_job->state == PULL_JOB_DONE &&
+ settings_job->error == 0 &&
+ !settings_job->etag_exists) {
+
+ _cleanup_free_ char *settings_fn = NULL;
+
+ assert(settings_job->calc_checksum);
+ assert(settings_job->checksum);
+
+ r = import_url_last_component(settings_job->url, &settings_fn);
+ if (r < 0)
+ return log_oom();
+
+ if (!filename_is_valid(settings_fn)) {
+ log_error("Cannot verify checksum, could not determine server-side settings file name.");
+ return -EBADMSG;
+ }
+
+ line = strjoina(settings_job->checksum, " *", settings_fn, "\n");
+
+ p = memmem(checksum_job->payload,
+ checksum_job->payload_size,
+ line,
+ strlen(line));
+
+ if (!p || (p != (char*) checksum_job->payload && p[-1] != '\n')) {
+ log_error("DOWNLOAD INVALID: Checksum of settings file did not checkout, settings file has been tampered with.");
+ return -EBADMSG;
+ }
+
+ log_info("SHA256 checksum of %s is valid.", settings_job->url);
+ }
+
if (!signature_job)
return 0;
@@ -382,9 +506,7 @@ int pull_verify(
cmd[k++] = "-";
cmd[k++] = NULL;
- fd_cloexec(STDIN_FILENO, false);
- fd_cloexec(STDOUT_FILENO, false);
- fd_cloexec(STDERR_FILENO, false);
+ stdio_unset_cloexec();
execvp("gpg2", (char * const *) cmd);
execvp("gpg", (char * const *) cmd);
@@ -407,7 +529,7 @@ int pull_verify(
if (r < 0)
goto finish;
if (r > 0) {
- log_error("Signature verification failed.");
+ log_error("DOWNLOAD INVALID: Signature verification failed.");
r = -EBADMSG;
} else {
log_info("Signature verification succeeded.");
@@ -416,7 +538,7 @@ int pull_verify(
finish:
if (sig_file >= 0)
- unlink(sig_file_path);
+ (void) unlink(sig_file_path);
if (gpg_home_created)
(void) rm_rf(gpg_home, REMOVE_ROOT|REMOVE_PHYSICAL);
diff --git a/src/import/pull-common.h b/src/import/pull-common.h
index bb9cf3efc1..929a131c88 100644
--- a/src/import/pull-common.h
+++ b/src/import/pull-common.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -23,8 +21,8 @@
#include <stdbool.h>
-#include "pull-job.h"
#include "import-util.h"
+#include "pull-job.h"
int pull_make_local_copy(const char *final, const char *root, const char *local, bool force_local);
@@ -32,5 +30,7 @@ int pull_find_old_etags(const char *url, const char *root, int dt, const char *p
int pull_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret);
+int pull_make_settings_job(PullJob **ret, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata);
int pull_make_verification_jobs(PullJob **ret_checksum_job, PullJob **ret_signature_job, ImportVerify verify, const char *url, CurlGlue *glue, PullJobFinished on_finished, void *userdata);
-int pull_verify(PullJob *main_job, PullJob *checksum_job, PullJob *signature_job);
+
+int pull_verify(PullJob *main_job, PullJob *settings_job, PullJob *checksum_job, PullJob *signature_job);
diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c
deleted file mode 100644
index 78e3184c42..0000000000
--- a/src/import/pull-dkr.c
+++ /dev/null
@@ -1,1335 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#include <curl/curl.h>
-#include <sys/prctl.h>
-
-#include "sd-daemon.h"
-#include "json.h"
-#include "strv.h"
-#include "btrfs-util.h"
-#include "utf8.h"
-#include "mkdir.h"
-#include "rm-rf.h"
-#include "path-util.h"
-#include "import-util.h"
-#include "curl-util.h"
-#include "aufs-util.h"
-#include "pull-job.h"
-#include "pull-common.h"
-#include "import-common.h"
-#include "pull-dkr.h"
-#include "process-util.h"
-#include "hostname-util.h"
-
-typedef enum DkrProgress {
- DKR_SEARCHING,
- DKR_RESOLVING,
- DKR_METADATA,
- DKR_DOWNLOADING,
- DKR_COPYING,
-} DkrProgress;
-
-struct DkrPull {
- sd_event *event;
- CurlGlue *glue;
-
- char *index_protocol;
- char *index_address;
-
- char *index_url;
- char *image_root;
-
- PullJob *images_job;
- PullJob *tags_job;
- PullJob *ancestry_job;
- PullJob *json_job;
- PullJob *layer_job;
-
- char *name;
- char *reference;
- char *id;
-
- char *response_digest;
- char *response_token;
- char **response_registries;
-
- char **ancestry;
- unsigned n_ancestry;
- unsigned current_ancestry;
-
- DkrPullFinished on_finished;
- void *userdata;
-
- char *local;
- bool force_local;
- bool grow_machine_directory;
-
- char *temp_path;
- char *final_path;
-
- pid_t tar_pid;
-};
-
-#define PROTOCOL_PREFIX "https://"
-
-#define HEADER_TOKEN "X-Do" /* the HTTP header for the auth token */ "cker-Token:"
-#define HEADER_REGISTRY "X-Do" /* the HTTP header for the registry */ "cker-Endpoints:"
-#define HEADER_DIGEST "Do" /* the HTTP header for the manifest digest */ "cker-Content-Digest:"
-#define LAYERS_MAX 127
-
-static void dkr_pull_job_on_finished(PullJob *j);
-
-DkrPull* dkr_pull_unref(DkrPull *i) {
- if (!i)
- return NULL;
-
- if (i->tar_pid > 1) {
- (void) kill_and_sigcont(i->tar_pid, SIGKILL);
- (void) wait_for_terminate(i->tar_pid, NULL);
- }
-
- pull_job_unref(i->images_job);
- pull_job_unref(i->tags_job);
- pull_job_unref(i->ancestry_job);
- pull_job_unref(i->json_job);
- pull_job_unref(i->layer_job);
-
- curl_glue_unref(i->glue);
- sd_event_unref(i->event);
-
- if (i->temp_path) {
- (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
- free(i->temp_path);
- }
-
- free(i->name);
- free(i->reference);
- free(i->id);
- free(i->response_token);
- strv_free(i->ancestry);
- free(i->final_path);
- free(i->index_address);
- free(i->index_protocol);
- free(i->index_url);
- free(i->image_root);
- free(i->local);
- free(i);
-
- return NULL;
-}
-
-int dkr_pull_new(
- DkrPull **ret,
- sd_event *event,
- const char *index_url,
- const char *image_root,
- DkrPullFinished on_finished,
- void *userdata) {
-
- _cleanup_(dkr_pull_unrefp) DkrPull *i = NULL;
- char *e;
- int r;
-
- assert(ret);
- assert(index_url);
-
- if (!http_url_is_valid(index_url))
- return -EINVAL;
-
- i = new0(DkrPull, 1);
- if (!i)
- return -ENOMEM;
-
- i->on_finished = on_finished;
- i->userdata = userdata;
-
- i->image_root = strdup(image_root ?: "/var/lib/machines");
- if (!i->image_root)
- return -ENOMEM;
-
- i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
-
- i->index_url = strdup(index_url);
- if (!i->index_url)
- return -ENOMEM;
-
- e = endswith(i->index_url, "/");
- if (e)
- *e = 0;
-
- if (event)
- i->event = sd_event_ref(event);
- else {
- r = sd_event_default(&i->event);
- if (r < 0)
- return r;
- }
-
- r = curl_glue_new(&i->glue, i->event);
- if (r < 0)
- return r;
-
- i->glue->on_finished = pull_job_curl_on_finished;
- i->glue->userdata = i;
-
- *ret = i;
- i = NULL;
-
- return 0;
-}
-
-static void dkr_pull_report_progress(DkrPull *i, DkrProgress p) {
- unsigned percent;
-
- assert(i);
-
- switch (p) {
-
- case DKR_SEARCHING:
- percent = 0;
- if (i->images_job)
- percent += i->images_job->progress_percent * 5 / 100;
- break;
-
- case DKR_RESOLVING:
- percent = 5;
- if (i->tags_job)
- percent += i->tags_job->progress_percent * 5 / 100;
- break;
-
- case DKR_METADATA:
- percent = 10;
- if (i->ancestry_job)
- percent += i->ancestry_job->progress_percent * 5 / 100;
- if (i->json_job)
- percent += i->json_job->progress_percent * 5 / 100;
- break;
-
- case DKR_DOWNLOADING:
- percent = 20;
- percent += 75 * i->current_ancestry / MAX(1U, i->n_ancestry);
- if (i->layer_job)
- percent += i->layer_job->progress_percent * 75 / MAX(1U, i->n_ancestry) / 100;
-
- break;
-
- case DKR_COPYING:
- percent = 95;
- break;
-
- default:
- assert_not_reached("Unknown progress state");
- }
-
- sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
- log_debug("Combined progress %u%%", percent);
-}
-
-static int parse_id(const void *payload, size_t size, char **ret) {
- _cleanup_free_ char *buf = NULL, *id = NULL, *other = NULL;
- union json_value v = {};
- void *json_state = NULL;
- const char *p;
- int t;
-
- assert(payload);
- assert(ret);
-
- if (size <= 0)
- return -EBADMSG;
-
- if (memchr(payload, 0, size))
- return -EBADMSG;
-
- buf = strndup(payload, size);
- if (!buf)
- return -ENOMEM;
-
- p = buf;
- t = json_tokenize(&p, &id, &v, &json_state, NULL);
- if (t < 0)
- return t;
- if (t != JSON_STRING)
- return -EBADMSG;
-
- t = json_tokenize(&p, &other, &v, &json_state, NULL);
- if (t < 0)
- return t;
- if (t != JSON_END)
- return -EBADMSG;
-
- if (!dkr_id_is_valid(id))
- return -EBADMSG;
-
- *ret = id;
- id = NULL;
-
- return 0;
-}
-
-static int parse_ancestry(const void *payload, size_t size, char ***ret) {
- _cleanup_free_ char *buf = NULL;
- void *json_state = NULL;
- const char *p;
- enum {
- STATE_BEGIN,
- STATE_ITEM,
- STATE_COMMA,
- STATE_END,
- } state = STATE_BEGIN;
- _cleanup_strv_free_ char **l = NULL;
- size_t n = 0, allocated = 0;
-
- if (size <= 0)
- return -EBADMSG;
-
- if (memchr(payload, 0, size))
- return -EBADMSG;
-
- buf = strndup(payload, size);
- if (!buf)
- return -ENOMEM;
-
- p = buf;
- for (;;) {
- _cleanup_free_ char *str;
- union json_value v = {};
- int t;
-
- t = json_tokenize(&p, &str, &v, &json_state, NULL);
- if (t < 0)
- return t;
-
- switch (state) {
-
- case STATE_BEGIN:
- if (t == JSON_ARRAY_OPEN)
- state = STATE_ITEM;
- else
- return -EBADMSG;
-
- break;
-
- case STATE_ITEM:
- if (t == JSON_STRING) {
- if (!dkr_id_is_valid(str))
- return -EBADMSG;
-
- if (n+1 > LAYERS_MAX)
- return -EFBIG;
-
- if (!GREEDY_REALLOC(l, allocated, n + 2))
- return -ENOMEM;
-
- l[n++] = str;
- str = NULL;
- l[n] = NULL;
-
- state = STATE_COMMA;
-
- } else if (t == JSON_ARRAY_CLOSE)
- state = STATE_END;
- else
- return -EBADMSG;
-
- break;
-
- case STATE_COMMA:
- if (t == JSON_COMMA)
- state = STATE_ITEM;
- else if (t == JSON_ARRAY_CLOSE)
- state = STATE_END;
- else
- return -EBADMSG;
- break;
-
- case STATE_END:
- if (t == JSON_END) {
-
- if (strv_isempty(l))
- return -EBADMSG;
-
- if (!strv_is_uniq(l))
- return -EBADMSG;
-
- l = strv_reverse(l);
-
- *ret = l;
- l = NULL;
- return 0;
- } else
- return -EBADMSG;
- }
-
- }
-}
-
-static const char *dkr_pull_current_layer(DkrPull *i) {
- assert(i);
-
- if (strv_isempty(i->ancestry))
- return NULL;
-
- return i->ancestry[i->current_ancestry];
-}
-
-static const char *dkr_pull_current_base_layer(DkrPull *i) {
- assert(i);
-
- if (strv_isempty(i->ancestry))
- return NULL;
-
- if (i->current_ancestry <= 0)
- return NULL;
-
- return i->ancestry[i->current_ancestry-1];
-}
-
-static int dkr_pull_add_token(DkrPull *i, PullJob *j) {
- const char *t;
-
- assert(i);
- assert(j);
-
- if (i->response_token)
- t = strjoina("Authorization: Token ", i->response_token);
- else
- t = HEADER_TOKEN " true";
-
- j->request_header = curl_slist_new("Accept: application/json", t, NULL);
- if (!j->request_header)
- return -ENOMEM;
-
- return 0;
-}
-
-static int dkr_pull_add_bearer_token(DkrPull *i, PullJob *j) {
- const char *t = NULL;
-
- assert(i);
- assert(j);
-
- if (i->response_token)
- t = strjoina("Authorization: Bearer ", i->response_token);
- else
- return -EINVAL;
-
- j->request_header = curl_slist_new("Accept: application/json", t, NULL);
- if (!j->request_header)
- return -ENOMEM;
-
- return 0;
-}
-
-static bool dkr_pull_is_done(DkrPull *i) {
- assert(i);
- assert(i->images_job);
- if (i->images_job->state != PULL_JOB_DONE)
- return false;
-
- if (!i->tags_job || i->tags_job->state != PULL_JOB_DONE)
- return false;
-
- if (!i->ancestry_job || i->ancestry_job->state != PULL_JOB_DONE)
- return false;
-
- if (i->json_job && i->json_job->state != PULL_JOB_DONE)
- return false;
-
- if (i->layer_job && i->layer_job->state != PULL_JOB_DONE)
- return false;
-
- if (dkr_pull_current_layer(i))
- return false;
-
- return true;
-}
-
-static int dkr_pull_make_local_copy(DkrPull *i, DkrPullVersion version) {
- int r;
- _cleanup_free_ char *p = NULL;
-
- assert(i);
-
- if (!i->local)
- return 0;
-
- if (!i->final_path) {
- i->final_path = strjoin(i->image_root, "/.dkr-", i->id, NULL);
- if (!i->final_path)
- return log_oom();
- }
-
- if (version == DKR_PULL_V2) {
- r = path_get_parent(i->image_root, &p);
- if (r < 0)
- return r;
- }
-
- r = pull_make_local_copy(i->final_path, p ?: i->image_root, i->local, i->force_local);
- if (r < 0)
- return r;
-
- if (version == DKR_PULL_V2) {
- char **k = NULL;
- STRV_FOREACH(k, i->ancestry) {
- _cleanup_free_ char *d = strjoin(i->image_root, "/.dkr-", *k, NULL);
- r = btrfs_subvol_remove(d, false);
- if (r < 0)
- return r;
- }
-
- r = rmdir(i->image_root);
- if (r < 0)
- return r;
- }
-
- return 0;
-}
-
-static int dkr_pull_job_on_open_disk(PullJob *j) {
- const char *base;
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- assert(i->layer_job == j);
- assert(i->final_path);
- assert(!i->temp_path);
- assert(i->tar_pid <= 0);
-
- r = tempfn_random(i->final_path, NULL, &i->temp_path);
- if (r < 0)
- return log_oom();
-
- mkdir_parents_label(i->temp_path, 0700);
-
- base = dkr_pull_current_base_layer(i);
- if (base) {
- const char *base_path;
-
- base_path = strjoina(i->image_root, "/.dkr-", base);
- r = btrfs_subvol_snapshot(base_path, i->temp_path, BTRFS_SNAPSHOT_FALLBACK_COPY);
- } else
- r = btrfs_subvol_make(i->temp_path);
- if (r < 0)
- return log_error_errno(r, "Failed to make btrfs subvolume %s: %m", i->temp_path);
-
- j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
- if (j->disk_fd < 0)
- return j->disk_fd;
-
- return 0;
-}
-
-static void dkr_pull_job_on_progress(PullJob *j) {
- DkrPull *i;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
-
- dkr_pull_report_progress(
- i,
- j == i->images_job ? DKR_SEARCHING :
- j == i->tags_job ? DKR_RESOLVING :
- j == i->ancestry_job || j == i->json_job ? DKR_METADATA :
- DKR_DOWNLOADING);
-}
-
-static void dkr_pull_job_on_finished_v2(PullJob *j);
-
-static int dkr_pull_pull_layer_v2(DkrPull *i) {
- _cleanup_free_ char *path = NULL;
- const char *url, *layer = NULL;
- int r;
-
- assert(i);
- assert(!i->layer_job);
- assert(!i->temp_path);
- assert(!i->final_path);
-
- for (;;) {
- layer = dkr_pull_current_layer(i);
- if (!layer)
- return 0; /* no more layers */
-
- path = strjoin(i->image_root, "/.dkr-", layer, NULL);
- if (!path)
- return log_oom();
-
- if (laccess(path, F_OK) < 0) {
- if (errno == ENOENT)
- break;
-
- return log_error_errno(errno, "Failed to check for container: %m");
- }
-
- log_info("Layer %s already exists, skipping.", layer);
-
- i->current_ancestry++;
-
- free(path);
- path = NULL;
- }
-
- log_info("Pulling layer %s...", layer);
-
- i->final_path = path;
- path = NULL;
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/blobs/", layer);
- r = pull_job_new(&i->layer_job, url, i->glue, i);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate layer job: %m");
-
- r = dkr_pull_add_bearer_token(i, i->layer_job);
- if (r < 0)
- return log_oom();
-
- i->layer_job->on_finished = dkr_pull_job_on_finished_v2;
- i->layer_job->on_open_disk = dkr_pull_job_on_open_disk;
- i->layer_job->on_progress = dkr_pull_job_on_progress;
- i->layer_job->grow_machine_directory = i->grow_machine_directory;
-
- r = pull_job_begin(i->layer_job);
- if (r < 0)
- return log_error_errno(r, "Failed to start layer job: %m");
-
- return 0;
-}
-
-static int dkr_pull_pull_layer(DkrPull *i) {
- _cleanup_free_ char *path = NULL;
- const char *url, *layer = NULL;
- int r;
-
- assert(i);
- assert(!i->layer_job);
- assert(!i->temp_path);
- assert(!i->final_path);
-
- for (;;) {
- layer = dkr_pull_current_layer(i);
- if (!layer)
- return 0; /* no more layers */
-
- path = strjoin(i->image_root, "/.dkr-", layer, NULL);
- if (!path)
- return log_oom();
-
- if (laccess(path, F_OK) < 0) {
- if (errno == ENOENT)
- break;
-
- return log_error_errno(errno, "Failed to check for container: %m");
- }
-
- log_info("Layer %s already exists, skipping.", layer);
-
- i->current_ancestry++;
-
- free(path);
- path = NULL;
- }
-
- log_info("Pulling layer %s...", layer);
-
- i->final_path = path;
- path = NULL;
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", layer, "/layer");
- r = pull_job_new(&i->layer_job, url, i->glue, i);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate layer job: %m");
-
- r = dkr_pull_add_token(i, i->layer_job);
- if (r < 0)
- return log_oom();
-
- i->layer_job->on_finished = dkr_pull_job_on_finished;
- i->layer_job->on_open_disk = dkr_pull_job_on_open_disk;
- i->layer_job->on_progress = dkr_pull_job_on_progress;
- i->layer_job->grow_machine_directory = i->grow_machine_directory;
-
- r = pull_job_begin(i->layer_job);
- if (r < 0)
- return log_error_errno(r, "Failed to start layer job: %m");
-
- return 0;
-}
-
-static int dkr_pull_job_on_header(PullJob *j, const char *header, size_t sz) {
- _cleanup_free_ char *registry = NULL;
- char *token, *digest;
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- r = curl_header_strdup(header, sz, HEADER_TOKEN, &token);
- if (r < 0)
- return log_oom();
- if (r > 0) {
- free(i->response_token);
- i->response_token = token;
- return 0;
- }
-
- r = curl_header_strdup(header, sz, HEADER_DIGEST, &digest);
- if (r < 0)
- return log_oom();
- if (r > 0) {
- free(i->response_digest);
- i->response_digest = digest;
- return 0;
- }
-
- r = curl_header_strdup(header, sz, HEADER_REGISTRY, &registry);
- if (r < 0)
- return log_oom();
- if (r > 0) {
- char **l, **k;
-
- l = strv_split(registry, ",");
- if (!l)
- return log_oom();
-
- STRV_FOREACH(k, l) {
- if (!hostname_is_valid(*k)) {
- log_error("Registry hostname is not valid.");
- strv_free(l);
- return -EBADMSG;
- }
- }
-
- strv_free(i->response_registries);
- i->response_registries = l;
- }
-
- return 0;
-}
-
-static void dkr_pull_job_on_finished_v2(PullJob *j) {
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- if (j->error != 0) {
- if (j == i->images_job)
- log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
- else if (j == i->ancestry_job)
- log_error_errno(j->error, "Failed to retrieve manifest.");
- else if (j == i->json_job)
- log_error_errno(j->error, "Failed to retrieve json data.");
- else
- log_error_errno(j->error, "Failed to retrieve layer data.");
-
- r = j->error;
- goto finish;
- }
-
- if (i->images_job == j) {
- const char *url;
-
- assert(!i->tags_job);
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- if (strv_isempty(i->response_registries)) {
- r = -EBADMSG;
- log_error("Didn't get registry information.");
- goto finish;
- }
-
- log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
- dkr_pull_report_progress(i, DKR_RESOLVING);
-
- url = strjoina(i->index_protocol, "auth.", i->index_address, "/v2/token/?scope=repository:",
- i->name, ":pull&service=registry.", i->index_address);
- r = pull_job_new(&i->tags_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate tags job: %m");
- goto finish;
- }
-
- i->tags_job->on_finished = dkr_pull_job_on_finished_v2;
- i->tags_job->on_progress = dkr_pull_job_on_progress;
-
- r = pull_job_begin(i->tags_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start tags job: %m");
- goto finish;
- }
-
- } else if (i->tags_job == j) {
- const char *url;
- _cleanup_free_ const char *buf;
- _cleanup_json_variant_unref_ JsonVariant *doc = NULL;
- JsonVariant *e = NULL;
-
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- buf = strndup((const char *)j->payload, j->payload_size);
- if (!buf) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
-
- r = json_parse(buf, &doc);
- if (r < 0) {
- log_error("Unable to parse bearer token\n%s", j->payload);
- goto finish;
- }
-
- e = json_variant_value(doc, "token");
- if (!e || e->type != JSON_VARIANT_STRING) {
- r = -EBADMSG;
- log_error("Invalid JSON format for Bearer token");
- goto finish;
- }
-
- r = free_and_strdup(&i->response_token, json_variant_string(e));
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v2/", i->name, "/manifests/", i->reference);
- r = pull_job_new(&i->ancestry_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate ancestry job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_bearer_token(i, i->ancestry_job);
- if (r < 0)
- goto finish;
-
- i->ancestry_job->on_finished = dkr_pull_job_on_finished_v2;
- i->ancestry_job->on_progress = dkr_pull_job_on_progress;
- i->ancestry_job->on_header = dkr_pull_job_on_header;
-
-
- r = pull_job_begin(i->ancestry_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start ancestry job: %m");
- goto finish;
- }
-
- } else if (i->ancestry_job == j) {
-
- _cleanup_json_variant_unref_ JsonVariant *doc = NULL, *compat = NULL;
- JsonVariant *e = NULL;
- _cleanup_strv_free_ char **ancestry = NULL;
- size_t allocated = 0, size = 0;
- char *path = NULL, **k = NULL;
-
- r = json_parse((const char *)j->payload, &doc);
- if (r < 0) {
- log_error("Invalid JSON Manifest");
- goto finish;
- }
-
- e = json_variant_value(doc, "fsLayers");
- if (!e || e->type != JSON_VARIANT_ARRAY || e->size == 0) {
- r = -EBADMSG;
- goto finish;
- }
-
- log_info("JSON manifest with schema v%"PRIi64" for %s parsed!",
- json_variant_integer(json_variant_value(doc, "schemaVersion")),
- json_variant_string(json_variant_value(doc, "name")));
-
- for (unsigned z = 0; z < e->size; z++) {
- JsonVariant *f = json_variant_element(e, z), *g = NULL;
- const char *layer;
- if (f->type != JSON_VARIANT_OBJECT) {
- r = -EBADMSG;
- goto finish;
- }
-
- g = json_variant_value(f, "blobSum");
-
- layer = json_variant_string(g);
- if (!dkr_digest_is_valid(layer)) {
- r = -EBADMSG;
- goto finish;
- }
-
- if (!GREEDY_REALLOC(ancestry, allocated, size + 2)) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
-
- ancestry[size] = strdup(layer);
- if (!ancestry[size]) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
-
- ancestry[size+1] = NULL;
- size += 1;
- }
-
- e = json_variant_value(doc, "history");
- if (!e || e->type != JSON_VARIANT_ARRAY) {
- r = -EBADMSG;
- goto finish;
- }
-
- e = json_variant_element(e, 0);
- e = json_variant_value(e, "v1Compatibility");
- r = json_parse(json_variant_string(e), &compat);
- if (r < 0) {
- log_error("Invalid v1Compatibility JSON");
- goto finish;
- }
-
- e = json_variant_value(compat, "id");
-
- strv_free(i->ancestry);
- i->ancestry = strv_reverse(strv_uniq(ancestry));
- i->n_ancestry = strv_length(i->ancestry);
- i->current_ancestry = 0;
- i->id = strdup(i->ancestry[i->n_ancestry - 1]);
- if (!i->id) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
- path = strjoin(i->image_root, "/.dkr-", json_variant_string(e), NULL);
- if (!path) {
- r = -ENOMEM;
- log_oom();
- goto finish;
- }
- free(i->image_root);
- i->image_root = path;
- ancestry = NULL;
-
- log_info("Required layers:\n");
- STRV_FOREACH(k, i->ancestry)
- log_info("\t%s", *k);
- log_info("\nProvenance:\n\tImageID: %s\n\tDigest: %s", json_variant_string(e), i->response_digest);
-
- dkr_pull_report_progress(i, DKR_DOWNLOADING);
-
- r = dkr_pull_pull_layer_v2(i);
- if (r < 0)
- goto finish;
-
- } else if (i->layer_job == j) {
- assert(i->temp_path);
- assert(i->final_path);
-
- j->disk_fd = safe_close(j->disk_fd);
-
- if (i->tar_pid > 0) {
- r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
- i->tar_pid = 0;
- if (r < 0)
- goto finish;
- }
-
- r = aufs_resolve(i->temp_path);
- if (r < 0) {
- log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
- goto finish;
- }
-
- r = btrfs_subvol_set_read_only(i->temp_path, true);
- if (r < 0) {
- log_error_errno(r, "Failed to mark snapshot read-only: %m");
- goto finish;
- }
-
- if (rename(i->temp_path, i->final_path) < 0) {
- log_error_errno(errno, "Failed to rename snaphsot: %m");
- goto finish;
- }
-
- log_info("Completed writing to layer %s.", i->final_path);
-
- i->layer_job = pull_job_unref(i->layer_job);
- free(i->temp_path);
- i->temp_path = NULL;
- free(i->final_path);
- i->final_path = NULL;
-
- i->current_ancestry ++;
- r = dkr_pull_pull_layer_v2(i);
- if (r < 0)
- goto finish;
-
- } else if (i->json_job != j)
- assert_not_reached("Got finished event for unknown curl object");
-
- if (!dkr_pull_is_done(i))
- return;
-
- dkr_pull_report_progress(i, DKR_COPYING);
-
- r = dkr_pull_make_local_copy(i, DKR_PULL_V2);
- if (r < 0)
- goto finish;
-
- r = 0;
-
-finish:
- if (i->on_finished)
- i->on_finished(i, r, i->userdata);
- else
- sd_event_exit(i->event, r);
-
-}
-
-static void dkr_pull_job_on_finished(PullJob *j) {
- DkrPull *i;
- int r;
-
- assert(j);
- assert(j->userdata);
-
- i = j->userdata;
- if (j->error != 0) {
- if (j == i->images_job)
- log_error_errno(j->error, "Failed to retrieve images list. (Wrong index URL?)");
- else if (j == i->tags_job)
- log_error_errno(j->error, "Failed to retrieve tags list.");
- else if (j == i->ancestry_job)
- log_error_errno(j->error, "Failed to retrieve ancestry list.");
- else if (j == i->json_job)
- log_error_errno(j->error, "Failed to retrieve json data.");
- else
- log_error_errno(j->error, "Failed to retrieve layer data.");
-
- r = j->error;
- goto finish;
- }
-
- if (i->images_job == j) {
- const char *url;
-
- assert(!i->tags_job);
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- if (strv_isempty(i->response_registries)) {
- r = -EBADMSG;
- log_error("Didn't get registry information.");
- goto finish;
- }
-
- log_info("Index lookup succeeded, directed to registry %s.", i->response_registries[0]);
- dkr_pull_report_progress(i, DKR_RESOLVING);
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/repositories/", i->name, "/tags/", i->reference);
- r = pull_job_new(&i->tags_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate tags job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_token(i, i->tags_job);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- i->tags_job->on_finished = dkr_pull_job_on_finished;
- i->tags_job->on_progress = dkr_pull_job_on_progress;
-
- r = pull_job_begin(i->tags_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start tags job: %m");
- goto finish;
- }
-
- } else if (i->tags_job == j) {
- const char *url;
- char *id = NULL;
-
- assert(!i->ancestry_job);
- assert(!i->json_job);
- assert(!i->layer_job);
-
- r = parse_id(j->payload, j->payload_size, &id);
- if (r < 0) {
- log_error_errno(r, "Failed to parse JSON id.");
- goto finish;
- }
-
- free(i->id);
- i->id = id;
-
- log_info("Tag lookup succeeded, resolved to layer %s.", i->id);
- dkr_pull_report_progress(i, DKR_METADATA);
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/ancestry");
- r = pull_job_new(&i->ancestry_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate ancestry job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_token(i, i->ancestry_job);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- i->ancestry_job->on_finished = dkr_pull_job_on_finished;
- i->ancestry_job->on_progress = dkr_pull_job_on_progress;
-
- url = strjoina(PROTOCOL_PREFIX, i->response_registries[0], "/v1/images/", i->id, "/json");
- r = pull_job_new(&i->json_job, url, i->glue, i);
- if (r < 0) {
- log_error_errno(r, "Failed to allocate json job: %m");
- goto finish;
- }
-
- r = dkr_pull_add_token(i, i->json_job);
- if (r < 0) {
- log_oom();
- goto finish;
- }
-
- i->json_job->on_finished = dkr_pull_job_on_finished;
- i->json_job->on_progress = dkr_pull_job_on_progress;
-
- r = pull_job_begin(i->ancestry_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start ancestry job: %m");
- goto finish;
- }
-
- r = pull_job_begin(i->json_job);
- if (r < 0) {
- log_error_errno(r, "Failed to start json job: %m");
- goto finish;
- }
-
- } else if (i->ancestry_job == j) {
- char **ancestry = NULL, **k;
- unsigned n;
-
- assert(!i->layer_job);
-
- r = parse_ancestry(j->payload, j->payload_size, &ancestry);
- if (r < 0) {
- log_error_errno(r, "Failed to parse JSON id.");
- goto finish;
- }
-
- n = strv_length(ancestry);
- if (n <= 0 || !streq(ancestry[n-1], i->id)) {
- log_error("Ancestry doesn't end in main layer.");
- strv_free(ancestry);
- r = -EBADMSG;
- goto finish;
- }
-
- log_info("Ancestor lookup succeeded, requires layers:\n");
- STRV_FOREACH(k, ancestry)
- log_info("\t%s", *k);
-
- strv_free(i->ancestry);
- i->ancestry = ancestry;
- i->n_ancestry = n;
- i->current_ancestry = 0;
-
- dkr_pull_report_progress(i, DKR_DOWNLOADING);
-
- r = dkr_pull_pull_layer(i);
- if (r < 0)
- goto finish;
-
- } else if (i->layer_job == j) {
- assert(i->temp_path);
- assert(i->final_path);
-
- j->disk_fd = safe_close(j->disk_fd);
-
- if (i->tar_pid > 0) {
- r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
- i->tar_pid = 0;
- if (r < 0)
- goto finish;
- }
-
- r = aufs_resolve(i->temp_path);
- if (r < 0) {
- log_error_errno(r, "Failed to resolve aufs whiteouts: %m");
- goto finish;
- }
-
- r = btrfs_subvol_set_read_only(i->temp_path, true);
- if (r < 0) {
- log_error_errno(r, "Failed to mark snapshot read-only: %m");
- goto finish;
- }
-
- if (rename(i->temp_path, i->final_path) < 0) {
- log_error_errno(errno, "Failed to rename snaphsot: %m");
- goto finish;
- }
-
- log_info("Completed writing to layer %s.", i->final_path);
-
- i->layer_job = pull_job_unref(i->layer_job);
- free(i->temp_path);
- i->temp_path = NULL;
- free(i->final_path);
- i->final_path = NULL;
-
- i->current_ancestry ++;
- r = dkr_pull_pull_layer(i);
- if (r < 0)
- goto finish;
-
- } else if (i->json_job != j)
- assert_not_reached("Got finished event for unknown curl object");
-
- if (!dkr_pull_is_done(i))
- return;
-
- dkr_pull_report_progress(i, DKR_COPYING);
-
- r = dkr_pull_make_local_copy(i, DKR_PULL_V1);
- if (r < 0)
- goto finish;
-
- r = 0;
-finish:
- if (i->on_finished)
- i->on_finished(i, r, i->userdata);
- else
- sd_event_exit(i->event, r);
-}
-
-static int get_protocol_address(char **protocol, char **address, const char *url) {
- const char *sep, *dot;
- _cleanup_free_ char *a = NULL, *p = NULL;
-
- sep = strstr(url, "://");
- if (!sep)
- return -EINVAL;
-
- dot = strrchr(url, '.');
- if (!dot)
- return -EINVAL;
- dot--;
-
- p = strndup(url, (sep - url) + 3);
- if (!p)
- return log_oom();
-
- while (dot > (sep + 3) && *dot != '.')
- dot--;
-
- a = strdup(dot + 1);
- if (!a)
- return log_oom();
-
- *address = a;
- *protocol = p;
- a = p = NULL;
-
- return 0;
-}
-
-int dkr_pull_start(DkrPull *i, const char *name, const char *reference, const char *local, bool force_local, DkrPullVersion version) {
- const char *url;
- int r;
-
- assert(i);
-
- if (!dkr_name_is_valid(name))
- return -EINVAL;
-
- if (reference && !dkr_ref_is_valid(reference))
- return -EINVAL;
-
- if (local && !machine_name_is_valid(local))
- return -EINVAL;
-
- if (i->images_job)
- return -EBUSY;
-
- if (!reference)
- reference = "latest";
-
- free(i->index_protocol);
- free(i->index_address);
- r = get_protocol_address(&i->index_protocol, &i->index_address, i->index_url);
- if (r < 0)
- return r;
-
- r = free_and_strdup(&i->local, local);
- if (r < 0)
- return r;
- i->force_local = force_local;
-
- r = free_and_strdup(&i->name, name);
- if (r < 0)
- return r;
- r = free_and_strdup(&i->reference, reference);
- if (r < 0)
- return r;
-
- url = strjoina(i->index_url, "/v1/repositories/", name, "/images");
-
- r = pull_job_new(&i->images_job, url, i->glue, i);
- if (r < 0)
- return r;
-
- r = dkr_pull_add_token(i, i->images_job);
- if (r < 0)
- return r;
-
- if (version == DKR_PULL_V1)
- i->images_job->on_finished = dkr_pull_job_on_finished;
- else
- i->images_job->on_finished = dkr_pull_job_on_finished_v2;
-
- i->images_job->on_header = dkr_pull_job_on_header;
- i->images_job->on_progress = dkr_pull_job_on_progress;
-
- return pull_job_begin(i->images_job);
-}
diff --git a/src/import/pull-dkr.h b/src/import/pull-dkr.h
deleted file mode 100644
index 33d18cb394..0000000000
--- a/src/import/pull-dkr.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
-/***
- This file is part of systemd.
-
- Copyright 2014 Lennart Poettering
-
- systemd is free software; you can redistribute it and/or modify it
- under the terms of the GNU Lesser General Public License as published by
- the Free Software Foundation; either version 2.1 of the License, or
- (at your option) any later version.
-
- systemd is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public License
- along with systemd; If not, see <http://www.gnu.org/licenses/>.
-***/
-
-#pragma once
-
-#include "sd-event.h"
-#include "util.h"
-
-typedef enum { DKR_PULL_V1, DKR_PULL_V2 } DkrPullVersion;
-typedef struct DkrPull DkrPull;
-
-typedef void (*DkrPullFinished)(DkrPull *pull, int error, void *userdata);
-
-int dkr_pull_new(DkrPull **pull, sd_event *event, const char *index_url, const char *image_root, DkrPullFinished on_finished, void *userdata);
-DkrPull* dkr_pull_unref(DkrPull *pull);
-
-DEFINE_TRIVIAL_CLEANUP_FUNC(DkrPull*, dkr_pull_unref);
-
-int dkr_pull_start(DkrPull *pull, const char *name, const char *tag, const char *local, bool force_local, DkrPullVersion version);
diff --git a/src/import/pull-job.c b/src/import/pull-job.c
index 42939f2104..6bcf35ef4e 100644
--- a/src/import/pull-job.c
+++ b/src/import/pull-job.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,9 +19,16 @@
#include <sys/xattr.h>
-#include "strv.h"
+#include "alloc-util.h"
+#include "fd-util.h"
+#include "hexdecoct.h"
+#include "io-util.h"
#include "machine-pool.h"
+#include "parse-util.h"
#include "pull-job.h"
+#include "string-util.h"
+#include "strv.h"
+#include "xattr-util.h"
PullJob* pull_job_unref(PullJob *j) {
if (!j)
diff --git a/src/import/pull-job.h b/src/import/pull-job.h
index 3239aeac20..3a152a50e3 100644
--- a/src/import/pull-job.h
+++ b/src/import/pull-job.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -23,9 +21,9 @@
#include <gcrypt.h>
-#include "macro.h"
#include "curl-util.h"
#include "import-compress.h"
+#include "macro.h"
typedef struct PullJob PullJob;
@@ -44,16 +42,7 @@ typedef enum PullJobState {
_PULL_JOB_STATE_INVALID = -1,
} PullJobState;
-#define PULL_JOB_STATE_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED))
-
-typedef enum PullJobCompression {
- PULL_JOB_UNCOMPRESSED,
- PULL_JOB_XZ,
- PULL_JOB_GZIP,
- PULL_JOB_BZIP2,
- _PULL_JOB_COMPRESSION_MAX,
- _PULL_JOB_COMPRESSION_INVALID = -1,
-} PullJobCompression;
+#define PULL_JOB_IS_COMPLETE(j) (IN_SET((j)->state, PULL_JOB_DONE, PULL_JOB_FAILED))
struct PullJob {
PullJobState state;
diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c
index 5bfaf012c0..8993402821 100644
--- a/src/import/pull-raw.c
+++ b/src/import/pull-raw.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,27 +17,36 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/xattr.h>
-#include <linux/fs.h>
#include <curl/curl.h>
+#include <linux/fs.h>
+#include <sys/xattr.h>
#include "sd-daemon.h"
-#include "utf8.h"
-#include "strv.h"
-#include "copy.h"
+
+#include "alloc-util.h"
#include "btrfs-util.h"
-#include "util.h"
+#include "chattr-util.h"
+#include "copy.h"
+#include "curl-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "hostname-util.h"
+#include "import-common.h"
+#include "import-util.h"
#include "macro.h"
#include "mkdir.h"
-#include "rm-rf.h"
#include "path-util.h"
-#include "import-util.h"
-#include "import-common.h"
-#include "curl-util.h"
-#include "qcow2-util.h"
-#include "pull-job.h"
#include "pull-common.h"
+#include "pull-job.h"
#include "pull-raw.h"
+#include "qcow2-util.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "utf8.h"
+#include "util.h"
+#include "web-util.h"
typedef enum RawProgress {
RAW_DOWNLOADING,
@@ -56,6 +63,7 @@ struct RawPull {
char *image_root;
PullJob *raw_job;
+ PullJob *settings_job;
PullJob *checksum_job;
PullJob *signature_job;
@@ -65,9 +73,13 @@ struct RawPull {
char *local;
bool force_local;
bool grow_machine_directory;
+ bool settings;
- char *temp_path;
char *final_path;
+ char *temp_path;
+
+ char *settings_path;
+ char *settings_temp_path;
ImportVerify verify;
};
@@ -77,6 +89,7 @@ RawPull* raw_pull_unref(RawPull *i) {
return NULL;
pull_job_unref(i->raw_job);
+ pull_job_unref(i->settings_job);
pull_job_unref(i->checksum_job);
pull_job_unref(i->signature_job);
@@ -88,7 +101,13 @@ RawPull* raw_pull_unref(RawPull *i) {
free(i->temp_path);
}
+ if (i->settings_temp_path) {
+ (void) unlink(i->settings_temp_path);
+ free(i->settings_temp_path);
+ }
+
free(i->final_path);
+ free(i->settings_path);
free(i->image_root);
free(i->local);
free(i);
@@ -154,6 +173,11 @@ static void raw_pull_report_progress(RawPull *i, RawProgress p) {
percent = 0;
+ if (i->settings_job) {
+ percent += i->settings_job->progress_percent * 5 / 100;
+ remain -= 5;
+ }
+
if (i->checksum_job) {
percent += i->checksum_job->progress_percent * 5 / 100;
remain -= 5;
@@ -218,7 +242,7 @@ static int raw_pull_maybe_convert_qcow2(RawPull *i) {
r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL);
if (r < 0)
- log_warning_errno(errno, "Failed to set file attributes on %s: %m", t);
+ log_warning_errno(r, "Failed to set file attributes on %s: %m", t);
log_info("Unpacking QCOW2 file.");
@@ -252,17 +276,17 @@ static int raw_pull_make_local_copy(RawPull *i) {
if (!i->local)
return 0;
+ if (!i->final_path) {
+ r = pull_make_path(i->raw_job->url, i->raw_job->etag, i->image_root, ".raw-", ".raw", &i->final_path);
+ if (r < 0)
+ return log_oom();
+ }
+
if (i->raw_job->etag_exists) {
/* We have downloaded this one previously, reopen it */
assert(i->raw_job->disk_fd < 0);
- if (!i->final_path) {
- r = pull_make_path(i->raw_job->url, i->raw_job->etag, i->image_root, ".raw-", ".raw", &i->final_path);
- if (r < 0)
- return log_oom();
- }
-
i->raw_job->disk_fd = open(i->final_path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (i->raw_job->disk_fd < 0)
return log_error_errno(errno, "Failed to open vendor image: %m");
@@ -294,9 +318,9 @@ static int raw_pull_make_local_copy(RawPull *i) {
* writes. */
r = chattr_fd(dfd, FS_NOCOW_FL, FS_NOCOW_FL);
if (r < 0)
- log_warning_errno(errno, "Failed to set file attributes on %s: %m", tp);
+ log_warning_errno(r, "Failed to set file attributes on %s: %m", tp);
- r = copy_bytes(i->raw_job->disk_fd, dfd, (off_t) -1, true);
+ r = copy_bytes(i->raw_job->disk_fd, dfd, (uint64_t) -1, true);
if (r < 0) {
unlink(tp);
return log_error_errno(r, "Failed to make writable copy of image: %m");
@@ -309,11 +333,36 @@ static int raw_pull_make_local_copy(RawPull *i) {
r = rename(tp, p);
if (r < 0) {
+ r = log_error_errno(errno, "Failed to move writable image into place: %m");
unlink(tp);
- return log_error_errno(errno, "Failed to move writable image into place: %m");
+ return r;
}
log_info("Created new local image '%s'.", i->local);
+
+ if (i->settings) {
+ const char *local_settings;
+ assert(i->settings_job);
+
+ if (!i->settings_path) {
+ r = pull_make_path(i->settings_job->url, i->settings_job->etag, i->image_root, ".settings-", NULL, &i->settings_path);
+ if (r < 0)
+ return log_oom();
+ }
+
+ local_settings = strjoina(i->image_root, "/", i->local, ".nspawn");
+
+ r = copy_file_atomic(i->settings_path, local_settings, 0644, i->force_local, 0);
+ if (r == -EEXIST)
+ log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
+ else if (r == -ENOENT)
+ log_debug_errno(r, "Skipping creation of settings file, since none was found.");
+ else if (r < 0)
+ log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings);
+ else
+ log_info("Created new settings file %s.", local_settings);
+ }
+
return 0;
}
@@ -321,11 +370,13 @@ static bool raw_pull_is_done(RawPull *i) {
assert(i);
assert(i->raw_job);
- if (i->raw_job->state != PULL_JOB_DONE)
+ if (!PULL_JOB_IS_COMPLETE(i->raw_job))
+ return false;
+ if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
return false;
- if (i->checksum_job && i->checksum_job->state != PULL_JOB_DONE)
+ if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
return false;
- if (i->signature_job && i->signature_job->state != PULL_JOB_DONE)
+ if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
return false;
return true;
@@ -339,7 +390,10 @@ static void raw_pull_job_on_finished(PullJob *j) {
assert(j->userdata);
i = j->userdata;
- if (j->error != 0) {
+ if (j == i->settings_job) {
+ if (j->error != 0)
+ log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
+ } else if (j->error != 0) {
if (j == i->checksum_job)
log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
else if (j == i->signature_job)
@@ -361,13 +415,16 @@ static void raw_pull_job_on_finished(PullJob *j) {
if (!raw_pull_is_done(i))
return;
+ if (i->settings_job)
+ i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
+
if (!i->raw_job->etag_exists) {
/* This is a new download, verify it, and move it into place */
assert(i->raw_job->disk_fd >= 0);
raw_pull_report_progress(i, RAW_VERIFYING);
- r = pull_verify(i->raw_job, i->checksum_job, i->signature_job);
+ r = pull_verify(i->raw_job, i->settings_job, i->checksum_job, i->signature_job);
if (r < 0)
goto finish;
@@ -389,8 +446,27 @@ static void raw_pull_job_on_finished(PullJob *j) {
goto finish;
}
- free(i->temp_path);
- i->temp_path = NULL;
+ i->temp_path = mfree(i->temp_path);
+
+ if (i->settings_job &&
+ i->settings_job->error == 0 &&
+ !i->settings_job->etag_exists) {
+
+ assert(i->settings_temp_path);
+ assert(i->settings_path);
+
+ r = import_make_read_only(i->settings_temp_path);
+ if (r < 0)
+ goto finish;
+
+ r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path);
+ if (r < 0) {
+ log_error_errno(r, "Failed to rename settings file: %m");
+ goto finish;
+ }
+
+ i->settings_temp_path = mfree(i->settings_temp_path);
+ }
}
raw_pull_report_progress(i, RAW_COPYING);
@@ -408,7 +484,7 @@ finish:
sd_event_exit(i->event, r);
}
-static int raw_pull_job_on_open_disk(PullJob *j) {
+static int raw_pull_job_on_open_disk_raw(PullJob *j) {
RawPull *i;
int r;
@@ -436,7 +512,36 @@ static int raw_pull_job_on_open_disk(PullJob *j) {
r = chattr_fd(j->disk_fd, FS_NOCOW_FL, FS_NOCOW_FL);
if (r < 0)
- log_warning_errno(errno, "Failed to set file attributes on %s: %m", i->temp_path);
+ log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path);
+
+ return 0;
+}
+
+static int raw_pull_job_on_open_disk_settings(PullJob *j) {
+ RawPull *i;
+ int r;
+
+ assert(j);
+ assert(j->userdata);
+
+ i = j->userdata;
+ assert(i->settings_job == j);
+ assert(!i->settings_path);
+ assert(!i->settings_temp_path);
+
+ r = pull_make_path(j->url, j->etag, i->image_root, ".settings-", NULL, &i->settings_path);
+ if (r < 0)
+ return log_oom();
+
+ r = tempfn_random(i->settings_path, NULL, &i->settings_temp_path);
+ if (r < 0)
+ return log_oom();
+
+ mkdir_parents_label(i->settings_temp_path, 0700);
+
+ j->disk_fd = open(i->settings_temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
+ if (j->disk_fd < 0)
+ return log_error_errno(errno, "Failed to create %s: %m", i->settings_temp_path);
return 0;
}
@@ -452,7 +557,14 @@ static void raw_pull_job_on_progress(PullJob *j) {
raw_pull_report_progress(i, RAW_DOWNLOADING);
}
-int raw_pull_start(RawPull *i, const char *url, const char *local, bool force_local, ImportVerify verify) {
+int raw_pull_start(
+ RawPull *i,
+ const char *url,
+ const char *local,
+ bool force_local,
+ ImportVerify verify,
+ bool settings) {
+
int r;
assert(i);
@@ -471,8 +583,10 @@ int raw_pull_start(RawPull *i, const char *url, const char *local, bool force_lo
r = free_and_strdup(&i->local, local);
if (r < 0)
return r;
+
i->force_local = force_local;
i->verify = verify;
+ i->settings = settings;
/* Queue job for the image itself */
r = pull_job_new(&i->raw_job, url, i->glue, i);
@@ -480,7 +594,7 @@ int raw_pull_start(RawPull *i, const char *url, const char *local, bool force_lo
return r;
i->raw_job->on_finished = raw_pull_job_on_finished;
- i->raw_job->on_open_disk = raw_pull_job_on_open_disk;
+ i->raw_job->on_open_disk = raw_pull_job_on_open_disk_raw;
i->raw_job->on_progress = raw_pull_job_on_progress;
i->raw_job->calc_checksum = verify != IMPORT_VERIFY_NO;
i->raw_job->grow_machine_directory = i->grow_machine_directory;
@@ -489,6 +603,20 @@ int raw_pull_start(RawPull *i, const char *url, const char *local, bool force_lo
if (r < 0)
return r;
+ if (settings) {
+ r = pull_make_settings_job(&i->settings_job, url, i->glue, raw_pull_job_on_finished, i);
+ if (r < 0)
+ return r;
+
+ i->settings_job->on_open_disk = raw_pull_job_on_open_disk_settings;
+ i->settings_job->on_progress = raw_pull_job_on_progress;
+ i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+
+ r = pull_find_old_etags(i->settings_job->url, i->image_root, DT_REG, ".settings-", NULL, &i->settings_job->old_etags);
+ if (r < 0)
+ return r;
+ }
+
r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, raw_pull_job_on_finished, i);
if (r < 0)
return r;
@@ -497,6 +625,12 @@ int raw_pull_start(RawPull *i, const char *url, const char *local, bool force_lo
if (r < 0)
return r;
+ if (i->settings_job) {
+ r = pull_job_begin(i->settings_job);
+ if (r < 0)
+ return r;
+ }
+
if (i->checksum_job) {
i->checksum_job->on_progress = raw_pull_job_on_progress;
diff --git a/src/import/pull-raw.h b/src/import/pull-raw.h
index 808f7be818..8f6d16eb3a 100644
--- a/src/import/pull-raw.h
+++ b/src/import/pull-raw.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,8 +20,9 @@
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct RawPull RawPull;
@@ -34,4 +33,4 @@ RawPull* raw_pull_unref(RawPull *pull);
DEFINE_TRIVIAL_CLEANUP_FUNC(RawPull*, raw_pull_unref);
-int raw_pull_start(RawPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify);
+int raw_pull_start(RawPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings);
diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c
index a6605d248f..8c61c46f73 100644
--- a/src/import/pull-tar.c
+++ b/src/import/pull-tar.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,26 +17,34 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
-#include <sys/prctl.h>
#include <curl/curl.h>
+#include <sys/prctl.h>
#include "sd-daemon.h"
-#include "utf8.h"
-#include "strv.h"
-#include "copy.h"
+
+#include "alloc-util.h"
#include "btrfs-util.h"
-#include "util.h"
+#include "copy.h"
+#include "curl-util.h"
+#include "fd-util.h"
+#include "fileio.h"
+#include "fs-util.h"
+#include "hostname-util.h"
+#include "import-common.h"
+#include "import-util.h"
#include "macro.h"
#include "mkdir.h"
-#include "rm-rf.h"
#include "path-util.h"
-#include "import-util.h"
-#include "import-common.h"
-#include "curl-util.h"
-#include "pull-job.h"
+#include "process-util.h"
#include "pull-common.h"
+#include "pull-job.h"
#include "pull-tar.h"
-#include "process-util.h"
+#include "rm-rf.h"
+#include "string-util.h"
+#include "strv.h"
+#include "utf8.h"
+#include "util.h"
+#include "web-util.h"
typedef enum TarProgress {
TAR_DOWNLOADING,
@@ -54,6 +60,7 @@ struct TarPull {
char *image_root;
PullJob *tar_job;
+ PullJob *settings_job;
PullJob *checksum_job;
PullJob *signature_job;
@@ -63,11 +70,15 @@ struct TarPull {
char *local;
bool force_local;
bool grow_machine_directory;
+ bool settings;
pid_t tar_pid;
- char *temp_path;
char *final_path;
+ char *temp_path;
+
+ char *settings_path;
+ char *settings_temp_path;
ImportVerify verify;
};
@@ -82,6 +93,7 @@ TarPull* tar_pull_unref(TarPull *i) {
}
pull_job_unref(i->tar_job);
+ pull_job_unref(i->settings_job);
pull_job_unref(i->checksum_job);
pull_job_unref(i->signature_job);
@@ -93,7 +105,13 @@ TarPull* tar_pull_unref(TarPull *i) {
free(i->temp_path);
}
+ if (i->settings_temp_path) {
+ (void) unlink(i->settings_temp_path);
+ free(i->settings_temp_path);
+ }
+
free(i->final_path);
+ free(i->settings_path);
free(i->image_root);
free(i->local);
free(i);
@@ -112,7 +130,6 @@ int tar_pull_new(
int r;
assert(ret);
- assert(event);
i = new0(TarPull, 1);
if (!i)
@@ -160,6 +177,11 @@ static void tar_pull_report_progress(TarPull *i, TarProgress p) {
percent = 0;
+ if (i->settings_job) {
+ percent += i->settings_job->progress_percent * 5 / 100;
+ remain -= 5;
+ }
+
if (i->checksum_job) {
percent += i->checksum_job->progress_percent * 5 / 100;
remain -= 5;
@@ -214,6 +236,29 @@ static int tar_pull_make_local_copy(TarPull *i) {
if (r < 0)
return r;
+ if (i->settings) {
+ const char *local_settings;
+ assert(i->settings_job);
+
+ if (!i->settings_path) {
+ r = pull_make_path(i->settings_job->url, i->settings_job->etag, i->image_root, ".settings-", NULL, &i->settings_path);
+ if (r < 0)
+ return log_oom();
+ }
+
+ local_settings = strjoina(i->image_root, "/", i->local, ".nspawn");
+
+ r = copy_file_atomic(i->settings_path, local_settings, 0664, i->force_local, 0);
+ if (r == -EEXIST)
+ log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings);
+ else if (r == -ENOENT)
+ log_debug_errno(r, "Skipping creation of settings file, since none was found.");
+ else if (r < 0)
+ log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings);
+ else
+ log_info("Created new settings file %s.", local_settings);
+ }
+
return 0;
}
@@ -221,11 +266,13 @@ static bool tar_pull_is_done(TarPull *i) {
assert(i);
assert(i->tar_job);
- if (i->tar_job->state != PULL_JOB_DONE)
+ if (!PULL_JOB_IS_COMPLETE(i->tar_job))
+ return false;
+ if (i->settings_job && !PULL_JOB_IS_COMPLETE(i->settings_job))
return false;
- if (i->checksum_job && i->checksum_job->state != PULL_JOB_DONE)
+ if (i->checksum_job && !PULL_JOB_IS_COMPLETE(i->checksum_job))
return false;
- if (i->signature_job && i->signature_job->state != PULL_JOB_DONE)
+ if (i->signature_job && !PULL_JOB_IS_COMPLETE(i->signature_job))
return false;
return true;
@@ -239,7 +286,11 @@ static void tar_pull_job_on_finished(PullJob *j) {
assert(j->userdata);
i = j->userdata;
- if (j->error != 0) {
+
+ if (j == i->settings_job) {
+ if (j->error != 0)
+ log_info_errno(j->error, "Settings file could not be retrieved, proceeding without.");
+ } else if (j->error != 0) {
if (j == i->checksum_job)
log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)");
else if (j == i->signature_job)
@@ -258,13 +309,19 @@ static void tar_pull_job_on_finished(PullJob *j) {
if (!tar_pull_is_done(i))
return;
- j->disk_fd = safe_close(i->tar_job->disk_fd);
+ i->tar_job->disk_fd = safe_close(i->tar_job->disk_fd);
+ if (i->settings_job)
+ i->settings_job->disk_fd = safe_close(i->settings_job->disk_fd);
if (i->tar_pid > 0) {
r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
i->tar_pid = 0;
if (r < 0)
goto finish;
+ if (r > 0) {
+ r = -EIO;
+ goto finish;
+ }
}
if (!i->tar_job->etag_exists) {
@@ -272,7 +329,7 @@ static void tar_pull_job_on_finished(PullJob *j) {
tar_pull_report_progress(i, TAR_VERIFYING);
- r = pull_verify(i->tar_job, i->checksum_job, i->signature_job);
+ r = pull_verify(i->tar_job, i->settings_job, i->checksum_job, i->signature_job);
if (r < 0)
goto finish;
@@ -288,8 +345,32 @@ static void tar_pull_job_on_finished(PullJob *j) {
goto finish;
}
- free(i->temp_path);
- i->temp_path = NULL;
+ i->temp_path = mfree(i->temp_path);
+
+ if (i->settings_job &&
+ i->settings_job->error == 0 &&
+ !i->settings_job->etag_exists) {
+
+ assert(i->settings_temp_path);
+ assert(i->settings_path);
+
+ /* Also move the settings file into place, if
+ * it exist. Note that we do so only if we
+ * also moved the tar file in place, to keep
+ * things strictly in sync. */
+
+ r = import_make_read_only(i->settings_temp_path);
+ if (r < 0)
+ goto finish;
+
+ r = rename_noreplace(AT_FDCWD, i->settings_temp_path, AT_FDCWD, i->settings_path);
+ if (r < 0) {
+ log_error_errno(r, "Failed to rename settings file: %m");
+ goto finish;
+ }
+
+ i->settings_temp_path = mfree(i->settings_temp_path);
+ }
}
tar_pull_report_progress(i, TAR_COPYING);
@@ -307,7 +388,7 @@ finish:
sd_event_exit(i->event, r);
}
-static int tar_pull_job_on_open_disk(PullJob *j) {
+static int tar_pull_job_on_open_disk_tar(PullJob *j) {
TarPull *i;
int r;
@@ -335,7 +416,9 @@ static int tar_pull_job_on_open_disk(PullJob *j) {
if (mkdir(i->temp_path, 0755) < 0)
return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path);
} else if (r < 0)
- return log_error_errno(errno, "Failed to create subvolume %s: %m", i->temp_path);
+ return log_error_errno(r, "Failed to create subvolume %s: %m", i->temp_path);
+ else
+ (void) import_assign_pool_quota_and_warn(i->temp_path);
j->disk_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
if (j->disk_fd < 0)
@@ -344,6 +427,35 @@ static int tar_pull_job_on_open_disk(PullJob *j) {
return 0;
}
+static int tar_pull_job_on_open_disk_settings(PullJob *j) {
+ TarPull *i;
+ int r;
+
+ assert(j);
+ assert(j->userdata);
+
+ i = j->userdata;
+ assert(i->settings_job == j);
+ assert(!i->settings_path);
+ assert(!i->settings_temp_path);
+
+ r = pull_make_path(j->url, j->etag, i->image_root, ".settings-", NULL, &i->settings_path);
+ if (r < 0)
+ return log_oom();
+
+ r = tempfn_random(i->settings_path, NULL, &i->settings_temp_path);
+ if (r < 0)
+ return log_oom();
+
+ mkdir_parents_label(i->settings_temp_path, 0700);
+
+ j->disk_fd = open(i->settings_temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
+ if (j->disk_fd < 0)
+ return log_error_errno(errno, "Failed to create %s: %m", i->settings_temp_path);
+
+ return 0;
+}
+
static void tar_pull_job_on_progress(PullJob *j) {
TarPull *i;
@@ -355,10 +467,19 @@ static void tar_pull_job_on_progress(PullJob *j) {
tar_pull_report_progress(i, TAR_DOWNLOADING);
}
-int tar_pull_start(TarPull *i, const char *url, const char *local, bool force_local, ImportVerify verify) {
+int tar_pull_start(
+ TarPull *i,
+ const char *url,
+ const char *local,
+ bool force_local,
+ ImportVerify verify,
+ bool settings) {
+
int r;
assert(i);
+ assert(verify < _IMPORT_VERIFY_MAX);
+ assert(verify >= 0);
if (!http_url_is_valid(url))
return -EINVAL;
@@ -372,15 +493,18 @@ int tar_pull_start(TarPull *i, const char *url, const char *local, bool force_lo
r = free_and_strdup(&i->local, local);
if (r < 0)
return r;
+
i->force_local = force_local;
i->verify = verify;
+ i->settings = settings;
+ /* Set up download job for TAR file */
r = pull_job_new(&i->tar_job, url, i->glue, i);
if (r < 0)
return r;
i->tar_job->on_finished = tar_pull_job_on_finished;
- i->tar_job->on_open_disk = tar_pull_job_on_open_disk;
+ i->tar_job->on_open_disk = tar_pull_job_on_open_disk_tar;
i->tar_job->on_progress = tar_pull_job_on_progress;
i->tar_job->calc_checksum = verify != IMPORT_VERIFY_NO;
i->tar_job->grow_machine_directory = i->grow_machine_directory;
@@ -389,6 +513,22 @@ int tar_pull_start(TarPull *i, const char *url, const char *local, bool force_lo
if (r < 0)
return r;
+ /* Set up download job for the settings file (.nspawn) */
+ if (settings) {
+ r = pull_make_settings_job(&i->settings_job, url, i->glue, tar_pull_job_on_finished, i);
+ if (r < 0)
+ return r;
+
+ i->settings_job->on_open_disk = tar_pull_job_on_open_disk_settings;
+ i->settings_job->on_progress = tar_pull_job_on_progress;
+ i->settings_job->calc_checksum = verify != IMPORT_VERIFY_NO;
+
+ r = pull_find_old_etags(i->settings_job->url, i->image_root, DT_REG, ".settings-", NULL, &i->settings_job->old_etags);
+ if (r < 0)
+ return r;
+ }
+
+ /* Set up download of checksum/signature files */
r = pull_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, tar_pull_job_on_finished, i);
if (r < 0)
return r;
@@ -397,6 +537,12 @@ int tar_pull_start(TarPull *i, const char *url, const char *local, bool force_lo
if (r < 0)
return r;
+ if (i->settings_job) {
+ r = pull_job_begin(i->settings_job);
+ if (r < 0)
+ return r;
+ }
+
if (i->checksum_job) {
i->checksum_job->on_progress = tar_pull_job_on_progress;
diff --git a/src/import/pull-tar.h b/src/import/pull-tar.h
index 0ed507748c..7e63e496d8 100644
--- a/src/import/pull-tar.h
+++ b/src/import/pull-tar.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
@@ -22,8 +20,9 @@
***/
#include "sd-event.h"
-#include "macro.h"
+
#include "import-util.h"
+#include "macro.h"
typedef struct TarPull TarPull;
@@ -34,4 +33,4 @@ TarPull* tar_pull_unref(TarPull *pull);
DEFINE_TRIVIAL_CLEANUP_FUNC(TarPull*, tar_pull_unref);
-int tar_pull_start(TarPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify);
+int tar_pull_start(TarPull *pull, const char *url, const char *local, bool force_local, ImportVerify verify, bool settings);
diff --git a/src/import/pull.c b/src/import/pull.c
index ca7be6be85..53b1211965 100644
--- a/src/import/pull.c
+++ b/src/import/pull.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -22,20 +20,23 @@
#include <getopt.h>
#include "sd-event.h"
-#include "event-util.h"
-#include "verbs.h"
-#include "build.h"
-#include "signal-util.h"
-#include "machine-image.h"
+
+#include "alloc-util.h"
+#include "hostname-util.h"
#include "import-util.h"
-#include "pull-tar.h"
+#include "machine-image.h"
+#include "parse-util.h"
#include "pull-raw.h"
-#include "pull-dkr.h"
+#include "pull-tar.h"
+#include "signal-util.h"
+#include "string-util.h"
+#include "verbs.h"
+#include "web-util.h"
static bool arg_force = false;
static const char *arg_image_root = "/var/lib/machines";
static ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
-static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
+static bool arg_settings = true;
static int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
log_notice("Transfer aborted.");
@@ -55,7 +56,7 @@ static void on_tar_finished(TarPull *pull, int error, void *userdata) {
static int pull_tar(int argc, char *argv[], void *userdata) {
_cleanup_(tar_pull_unrefp) TarPull *pull = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
const char *url, *local;
_cleanup_free_ char *l = NULL, *ll = NULL;
int r;
@@ -96,7 +97,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
else if (r > 0) {
- log_error_errno(EEXIST, "Image '%s' already exists.", local);
+ log_error("Image '%s' already exists.", local);
return -EEXIST;
}
}
@@ -117,7 +118,7 @@ static int pull_tar(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to allocate puller: %m");
- r = tar_pull_start(pull, url, local, arg_force, arg_verify);
+ r = tar_pull_start(pull, url, local, arg_force, arg_verify, arg_settings);
if (r < 0)
return log_error_errno(r, "Failed to pull image: %m");
@@ -141,7 +142,7 @@ static void on_raw_finished(RawPull *pull, int error, void *userdata) {
static int pull_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_pull_unrefp) RawPull *pull = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
const char *url, *local;
_cleanup_free_ char *l = NULL, *ll = NULL;
int r;
@@ -182,7 +183,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
else if (r > 0) {
- log_error_errno(EEXIST, "Image '%s' already exists.", local);
+ log_error("Image '%s' already exists.", local);
return -EEXIST;
}
}
@@ -203,115 +204,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
if (r < 0)
return log_error_errno(r, "Failed to allocate puller: %m");
- r = raw_pull_start(pull, url, local, arg_force, arg_verify);
- if (r < 0)
- return log_error_errno(r, "Failed to pull image: %m");
-
- r = sd_event_loop(event);
- if (r < 0)
- return log_error_errno(r, "Failed to run event loop: %m");
-
- log_info("Exiting.");
- return -r;
-}
-
-static void on_dkr_finished(DkrPull *pull, int error, void *userdata) {
- sd_event *event = userdata;
- assert(pull);
-
- if (error == 0)
- log_info("Operation completed successfully.");
-
- sd_event_exit(event, abs(error));
-}
-
-static int pull_dkr(int argc, char *argv[], void *userdata) {
- _cleanup_(dkr_pull_unrefp) DkrPull *pull = NULL;
- _cleanup_event_unref_ sd_event *event = NULL;
- const char *name, *reference, *local, *digest;
- int r;
-
- if (!arg_dkr_index_url) {
- log_error("Please specify an index URL with --dkr-index-url=");
- return -EINVAL;
- }
-
- if (arg_verify != IMPORT_VERIFY_NO) {
- log_error("Pulls from dkr do not support image verification, please pass --verify=no.");
- return -EINVAL;
- }
-
- digest = strchr(argv[1], '@');
- if (digest) {
- reference = digest + 1;
- name = strndupa(argv[1], digest - argv[1]);
- } else {
- reference = strchr(argv[1], ':');
- if (reference) {
- name = strndupa(argv[1], reference - argv[1]);
- reference++;
- } else {
- name = argv[1];
- reference = "latest";
- }
- }
-
- if (!dkr_name_is_valid(name)) {
- log_error("Remote name '%s' is not valid.", name);
- return -EINVAL;
- }
-
- if (!dkr_ref_is_valid(reference)) {
- log_error("Tag name '%s' is not valid.", reference);
- return -EINVAL;
- }
-
- if (argc >= 3)
- local = argv[2];
- else {
- local = strchr(name, '/');
- if (local)
- local++;
- else
- local = name;
- }
-
- if (isempty(local) || streq(local, "-"))
- local = NULL;
-
- if (local) {
- if (!machine_name_is_valid(local)) {
- log_error("Local image name '%s' is not valid.", local);
- return -EINVAL;
- }
-
- if (!arg_force) {
- r = image_find(local, NULL);
- if (r < 0)
- return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
- else if (r > 0) {
- log_error_errno(EEXIST, "Image '%s' already exists.", local);
- return -EEXIST;
- }
- }
-
- log_info("Pulling '%s' with reference '%s', saving as '%s'.", name, reference, local);
- } else
- log_info("Pulling '%s' with reference '%s'.", name, reference);
-
- r = sd_event_default(&event);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate event loop: %m");
-
- assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
- (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL);
- (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
-
- r = dkr_pull_new(&pull, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event);
- if (r < 0)
- return log_error_errno(r, "Failed to allocate puller: %m");
-
- r = dkr_pull_start(pull, name, reference, local, arg_force, DKR_PULL_V2);
+ r = raw_pull_start(pull, url, local, arg_force, arg_verify, arg_settings);
if (r < 0)
return log_error_errno(r, "Failed to pull image: %m");
@@ -330,14 +223,13 @@ static int help(int argc, char *argv[], void *userdata) {
" -h --help Show this help\n"
" --version Show package version\n"
" --force Force creation of image\n"
- " --verify= Verify downloaded image, one of: 'no',\n"
- " 'checksum', 'signature'.\n"
- " --image-root=PATH Image root directory\n"
- " --dkr-index-url=URL Specify index URL to use for downloads\n\n"
+ " --verify=MODE Verify downloaded image, one of: 'no',\n"
+ " 'checksum', 'signature'\n"
+ " --settings=BOOL Download settings file with image\n"
+ " --image-root=PATH Image root directory\n\n"
"Commands:\n"
" tar URL [NAME] Download a TAR image\n"
- " raw URL [NAME] Download a RAW image\n"
- " dkr REMOTE [NAME] Download a DKR image\n",
+ " raw URL [NAME] Download a RAW image\n",
program_invocation_short_name);
return 0;
@@ -348,22 +240,22 @@ static int parse_argv(int argc, char *argv[]) {
enum {
ARG_VERSION = 0x100,
ARG_FORCE,
- ARG_DKR_INDEX_URL,
ARG_IMAGE_ROOT,
ARG_VERIFY,
+ ARG_SETTINGS,
};
static const struct option options[] = {
{ "help", no_argument, NULL, 'h' },
{ "version", no_argument, NULL, ARG_VERSION },
{ "force", no_argument, NULL, ARG_FORCE },
- { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
{ "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
{ "verify", required_argument, NULL, ARG_VERIFY },
+ { "settings", required_argument, NULL, ARG_SETTINGS },
{}
};
- int c;
+ int c, r;
assert(argc >= 0);
assert(argv);
@@ -376,23 +268,12 @@ static int parse_argv(int argc, char *argv[]) {
return help(0, NULL, NULL);
case ARG_VERSION:
- puts(PACKAGE_STRING);
- puts(SYSTEMD_FEATURES);
- return 0;
+ return version();
case ARG_FORCE:
arg_force = true;
break;
- case ARG_DKR_INDEX_URL:
- if (!http_url_is_valid(optarg)) {
- log_error("Index URL is not valid: %s", optarg);
- return -EINVAL;
- }
-
- arg_dkr_index_url = optarg;
- break;
-
case ARG_IMAGE_ROOT:
arg_image_root = optarg;
break;
@@ -406,6 +287,14 @@ static int parse_argv(int argc, char *argv[]) {
break;
+ case ARG_SETTINGS:
+ r = parse_boolean(optarg);
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse --settings= parameter '%s'", optarg);
+
+ arg_settings = r;
+ break;
+
case '?':
return -EINVAL;
@@ -422,7 +311,6 @@ static int pull_main(int argc, char *argv[]) {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "tar", 2, 3, 0, pull_tar },
{ "raw", 2, 3, 0, pull_raw },
- { "dkr", 2, 3, 0, pull_dkr },
{}
};
diff --git a/src/import/qcow2-util.c b/src/import/qcow2-util.c
index fd3cf1b0e3..ee2121cc36 100644
--- a/src/import/qcow2-util.c
+++ b/src/import/qcow2-util.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -21,10 +19,11 @@
#include <zlib.h>
-#include "util.h"
-#include "sparse-endian.h"
-#include "qcow2-util.h"
+#include "alloc-util.h"
#include "btrfs-util.h"
+#include "qcow2-util.h"
+#include "sparse-endian.h"
+#include "util.h"
#define QCOW2_MAGIC 0x514649fb
diff --git a/src/import/qcow2-util.h b/src/import/qcow2-util.h
index be7fd1d0c9..6dddac8cdf 100644
--- a/src/import/qcow2-util.h
+++ b/src/import/qcow2-util.h
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
#pragma once
/***
diff --git a/src/import/test-qcow2.c b/src/import/test-qcow2.c
index 9a6c3e8b35..b820253d71 100644
--- a/src/import/test-qcow2.c
+++ b/src/import/test-qcow2.c
@@ -1,5 +1,3 @@
-/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
-
/***
This file is part of systemd.
@@ -19,10 +17,10 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#include "fd-util.h"
#include "log.h"
-#include "util.h"
-
#include "qcow2-util.h"
+#include "util.h"
int main(int argc, char *argv[]) {
_cleanup_close_ int sfd = -1, dfd = -1;