diff options
Diffstat (limited to 'src/import')
31 files changed, 292 insertions, 1783 deletions
diff --git a/src/import/aufs-util.c b/src/import/aufs-util.c index 18c42b8b6d..b44dbb14ea 100644 --- a/src/import/aufs-util.c +++ b/src/import/aufs-util.c @@ -21,9 +21,10 @@ #include <ftw.h> -#include "util.h" -#include "rm-rf.h" #include "aufs-util.h" +#include "rm-rf.h" +#include "string-util.h" +#include "util.h" static int nftw_cb( const char *fpath, @@ -68,7 +69,7 @@ int aufs_resolve(const char *path) { errno = 0; r = nftw(path, nftw_cb, 64, FTW_MOUNT|FTW_PHYS|FTW_ACTIONRETVAL); if (r == FTW_STOP) - return errno ? -errno : -EIO; + return errno > 0 ? -errno : -EIO; return 0; } diff --git a/src/import/curl-util.c b/src/import/curl-util.c index d390cfb1f3..8e531a64fa 100644 --- a/src/import/curl-util.c +++ b/src/import/curl-util.c @@ -19,7 +19,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 +48,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 +77,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 +89,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); } @@ -140,17 +141,17 @@ static int curl_glue_socket_callback(CURLM *curl, curl_socket_t s, int action, v 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; } @@ -226,7 +227,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..eec53c9266 100644 --- a/src/import/curl-util.h +++ b/src/import/curl-util.h @@ -21,12 +21,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..28c87594d6 100644 --- a/src/import/export-raw.c +++ b/src/import/export-raw.c @@ -20,16 +20,25 @@ ***/ #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 "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..e5e298f6ab 100644 --- a/src/import/export-raw.h +++ b/src/import/export-raw.h @@ -22,8 +22,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 43fa9d1b03..2bbec661e6 100644 --- a/src/import/export-tar.c +++ b/src/import/export-tar.c @@ -19,15 +19,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 +81,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,7 +286,7 @@ 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; diff --git a/src/import/export-tar.h b/src/import/export-tar.h index ce27a9fc1e..9061e7515d 100644 --- a/src/import/export-tar.h +++ b/src/import/export-tar.h @@ -22,8 +22,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 b88d71fec6..27efc3b099 100644 --- a/src/import/export.c +++ b/src/import/export.c @@ -22,15 +22,18 @@ #include <getopt.h> #include "sd-event.h" -#include "event-util.h" -#include "signal-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 "verbs.h" -#include "build.h" -#include "machine-image.h" #include "import-util.h" -#include "export-tar.h" -#include "export-raw.h" +#include "machine-image.h" +#include "signal-util.h" +#include "string-util.h" +#include "verbs.h" static ImportCompressType arg_compress = IMPORT_COMPRESS_UNKNOWN; @@ -72,7 +75,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; @@ -151,7 +154,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; @@ -260,9 +263,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 d8a3bbc249..8a48bd7bf9 100644 --- a/src/import/import-common.c +++ b/src/import/import-common.c @@ -19,15 +19,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; @@ -132,7 +134,7 @@ int import_fork_tar_x(const char *path, pid_t *ret) { 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"); @@ -206,7 +208,7 @@ int import_fork_tar_c(const char *path, pid_t *ret) { 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"); diff --git a/src/import/import-compress.c b/src/import/import-compress.c index d6b8133036..d4ff178f60 100644 --- a/src/import/import-compress.c +++ b/src/import/import-compress.c @@ -19,8 +19,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..0a13232554 100644 --- a/src/import/import-compress.h +++ b/src/import/import-compress.h @@ -21,11 +21,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 5f7d25d063..7593f064fc 100644 --- a/src/import/import-raw.c +++ b/src/import/import-raw.c @@ -23,19 +23,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 "hostname-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; @@ -191,7 +199,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."); @@ -279,7 +287,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..626d965cf8 100644 --- a/src/import/import-raw.h +++ b/src/import/import-raw.h @@ -22,8 +22,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 d2bfb30238..c7983c04be 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -23,20 +23,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 "hostname-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; @@ -234,7 +241,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..d12391572d 100644 --- a/src/import/import-tar.h +++ b/src/import/import-tar.h @@ -22,8 +22,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 929a840298..15505de924 100644 --- a/src/import/import.c +++ b/src/import/import.c @@ -22,15 +22,18 @@ #include <getopt.h> #include "sd-event.h" -#include "event-util.h" -#include "verbs.h" -#include "build.h" -#include "signal-util.h" + +#include "alloc-util.h" +#include "fd-util.h" +#include "fs-util.h" #include "hostname-util.h" -#include "machine-image.h" -#include "import-util.h" -#include "import-tar.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; @@ -54,7 +57,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; @@ -149,7 +152,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; @@ -280,9 +283,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 c90ada5da4..1b777c32b6 100644 --- a/src/import/importd.c +++ b/src/import/importd.c @@ -22,20 +22,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 "hostname-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; @@ -47,7 +55,6 @@ typedef enum TransferType { TRANSFER_EXPORT_RAW, TRANSFER_PULL_TAR, TRANSFER_PULL_RAW, - TRANSFER_PULL_DKR, _TRANSFER_TYPE_MAX, _TRANSFER_TYPE_INVALID = -1, } TransferType; @@ -66,7 +73,6 @@ struct Transfer { bool force_local; bool read_only; - char *dkr_index_url; char *format; pid_t pid; @@ -109,7 +115,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); @@ -126,7 +131,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); @@ -375,12 +379,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 */ @@ -463,10 +466,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"; @@ -478,11 +479,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; @@ -600,11 +596,11 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void cmsg_close_all(&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_FOREACH(cmsg, &msghdr) + if (cmsg->cmsg_level == SOL_SOCKET && + 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."); @@ -699,7 +695,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; @@ -710,8 +706,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; } @@ -899,7 +894,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); @@ -931,107 +926,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", - NULL, - 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; @@ -1180,7 +1076,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 38201e46e1..a83cffffa0 100644 --- a/src/import/pull-common.c +++ b/src/import/pull-common.c @@ -21,18 +21,28 @@ #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, @@ -136,7 +146,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) @@ -149,8 +159,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); @@ -164,18 +187,35 @@ 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; } @@ -334,9 +374,10 @@ int pull_verify(PullJob *main_job, log_info("SHA256 checksum of %s is valid.", main_job->url); - assert(!settings_job || settings_job->state == PULL_JOB_DONE); + 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) { diff --git a/src/import/pull-common.h b/src/import/pull-common.h index 7e6db1862c..ea228bb5c8 100644 --- a/src/import/pull-common.h +++ b/src/import/pull-common.h @@ -23,8 +23,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); diff --git a/src/import/pull-dkr.c b/src/import/pull-dkr.c deleted file mode 100644 index 0dab184af1..0000000000 --- a/src/import/pull-dkr.c +++ /dev/null @@ -1,1331 +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++; - - path = mfree(path); - } - - 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++; - - path = mfree(path); - } - - 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, ®istry); - 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, false)) { - 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_ 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); - i->temp_path = mfree(i->temp_path); - i->final_path = mfree(i->final_path); - - 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..824fa246ec 100644 --- a/src/import/pull-job.c +++ b/src/import/pull-job.c @@ -21,9 +21,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 1777bf1c33..56a74a34ef 100644 --- a/src/import/pull-job.h +++ b/src/import/pull-job.h @@ -23,9 +23,9 @@ #include <gcrypt.h> -#include "macro.h" #include "curl-util.h" #include "import-compress.h" +#include "macro.h" typedef struct PullJob PullJob; diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 0e77197e34..03bfb51756 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -19,28 +19,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 "hostname-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, @@ -236,7 +244,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."); @@ -312,7 +320,7 @@ 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, (uint64_t) -1, true); if (r < 0) { @@ -327,8 +335,9 @@ 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); @@ -349,9 +358,9 @@ static int raw_pull_make_local_copy(RawPull *i) { if (r == -EEXIST) log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings); else if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to copy settings files %s: %m", local_settings); - - log_info("Create new settings file '%s.nspawn'", i->local); + log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings); + else + log_info("Created new settings file '%s.nspawn'", i->local); } return 0; @@ -503,7 +512,7 @@ static int raw_pull_job_on_open_disk_raw(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; } diff --git a/src/import/pull-raw.h b/src/import/pull-raw.h index b03b4f5c92..0e4e1daf0e 100644 --- a/src/import/pull-raw.h +++ b/src/import/pull-raw.h @@ -22,8 +22,9 @@ ***/ #include "sd-event.h" -#include "macro.h" + #include "import-util.h" +#include "macro.h" typedef struct RawPull RawPull; diff --git a/src/import/pull-tar.c b/src/import/pull-tar.c index 563765d83d..2e48167c54 100644 --- a/src/import/pull-tar.c +++ b/src/import/pull-tar.c @@ -19,27 +19,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 "process-util.h" -#include "hostname-util.h" -#include "import-util.h" -#include "import-common.h" -#include "curl-util.h" -#include "pull-job.h" #include "pull-common.h" +#include "pull-job.h" #include "pull-tar.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, @@ -247,9 +254,9 @@ static int tar_pull_make_local_copy(TarPull *i) { if (r == -EEXIST) log_warning_errno(r, "Settings file %s already exists, not replacing.", local_settings); else if (r < 0 && r != -ENOENT) - log_warning_errno(r, "Failed to copy settings files %s: %m", local_settings); - - log_info("Create new settings file '%s.nspawn'", i->local); + log_warning_errno(r, "Failed to copy settings files %s, ignoring: %m", local_settings); + else + log_info("Created new settings file '%s.nspawn'", i->local); } return 0; @@ -409,7 +416,9 @@ static int tar_pull_job_on_open_disk_tar(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) diff --git a/src/import/pull-tar.h b/src/import/pull-tar.h index 420845ae50..9f02f1ec71 100644 --- a/src/import/pull-tar.h +++ b/src/import/pull-tar.h @@ -22,8 +22,9 @@ ***/ #include "sd-event.h" -#include "macro.h" + #include "import-util.h" +#include "macro.h" typedef struct TarPull TarPull; diff --git a/src/import/pull.c b/src/import/pull.c index 98c22aeec9..e0631bdeaf 100644 --- a/src/import/pull.c +++ b/src/import/pull.c @@ -22,21 +22,22 @@ #include <getopt.h> #include "sd-event.h" -#include "event-util.h" -#include "verbs.h" -#include "build.h" -#include "signal-util.h" + +#include "alloc-util.h" #include "hostname-util.h" -#include "machine-image.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) { @@ -57,7 +58,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; @@ -143,7 +144,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; @@ -217,114 +218,6 @@ static int pull_raw(int argc, char *argv[], void *userdata) { 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); - 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 int help(int argc, char *argv[], void *userdata) { printf("%s [OPTIONS...] {COMMAND} ...\n\n" @@ -335,12 +228,10 @@ static int help(int argc, char *argv[], void *userdata) { " --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" - " --dkr-index-url=URL Specify index URL to use for downloads\n\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; @@ -351,7 +242,6 @@ 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, @@ -361,7 +251,6 @@ static int parse_argv(int argc, char *argv[]) { { "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 }, @@ -381,23 +270,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; @@ -435,7 +313,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..47dabaa86e 100644 --- a/src/import/qcow2-util.c +++ b/src/import/qcow2-util.c @@ -21,10 +21,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/test-qcow2.c b/src/import/test-qcow2.c index 9a6c3e8b35..4b60079619 100644 --- a/src/import/test-qcow2.c +++ b/src/import/test-qcow2.c @@ -19,10 +19,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; |