X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fimport%2Fimport-dkr.c;h=a3f390ca826da3abc094312eeba940b54186421c;hb=087682d103e08670963686d9b1bc1d35c412a63f;hp=205deb9cda62e6fd0bd9de80f1ce9a646ef6f9e6;hpb=6eeeb84c96d3f42c0e7726f8f45c06a0a886b4e4;p=elogind.git diff --git a/src/import/import-dkr.c b/src/import/import-dkr.c index 205deb9cd..a3f390ca8 100644 --- a/src/import/import-dkr.c +++ b/src/import/import-dkr.c @@ -76,7 +76,6 @@ struct DkrImportJob { struct DkrImportName { DkrImport *import; - char *index_url; char *name; char *tag; char *id; @@ -94,11 +93,16 @@ struct DkrImport { sd_event *event; CurlGlue *glue; + char *index_url; + char *image_root; + Hashmap *names; Hashmap *jobs; dkr_import_on_finished on_finished; void *userdata; + + bool finished; }; #define PROTOCOL_PREFIX "https://" @@ -163,7 +167,6 @@ static DkrImportName *dkr_import_name_unref(DkrImportName *name) { if (name->job_layer) set_remove(name->job_layer->needed_by, name); - free(name->index_url); free(name->name); free(name->id); free(name->tag); @@ -181,6 +184,11 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DkrImportName*, dkr_import_name_unref); static void dkr_import_finish(DkrImport *import, int error) { assert(import); + if (import->finished) + return; + + import->finished = true; + if (import->on_finished) import->on_finished(import, error, import->userdata); else @@ -399,22 +407,22 @@ static void dkr_import_name_maybe_finish(DkrImportName *name) { assert(name->id); - p = strappenda("/var/lib/container/", name->local); - q = strappenda("/var/lib/container/.dkr-", name->id); + p = strappenda(name->import->image_root, "/", name->local); + q = strappenda(name->import->image_root, "/.dkr-", name->id); if (name->force_local) { (void) btrfs_subvol_remove(p); - (void) rm_rf(p, false, true, false); + (void) rm_rf_dangerous(p, false, true, false); } r = btrfs_subvol_snapshot(q, p, false, false); if (r < 0) { - log_error_errno(r, "Failed to snapshot final image: %m"); + log_error_errno(r, "Failed to snapshot local image: %m"); dkr_import_finish(name->import, r); return; } - log_info("Created new image %s.", p); + log_info("Created new local image %s.", p); } dkr_import_finish(name->import, 0); @@ -527,7 +535,7 @@ static int dkr_import_name_pull_layer(DkrImportName *name) { return 0; } - path = strjoin("/var/lib/container/.dkr-", layer, NULL); + path = strjoin(name->import->image_root, "/.dkr-", layer, NULL); if (!path) return log_oom(); @@ -568,7 +576,7 @@ static int dkr_import_name_pull_layer(DkrImportName *name) { if (base) { const char *base_path; - base_path = strappend("/var/lib/container/.dkr-", base); + base_path = strappenda(name->import->image_root, "/.dkr-", base); r = btrfs_subvol_snapshot(base_path, temp, false, true); } else r = btrfs_subvol_make(temp); @@ -711,7 +719,7 @@ static void dkr_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, &job) != CURLE_OK) return; - if (!job) + if (!job || job->done) return; job->done = true; @@ -773,7 +781,7 @@ static void dkr_import_curl_on_finished(CurlGlue *g, CURL *curl, CURLcode result goto fail; } - r = btrfs_subvol_read_only(job->temp_path, true); + r = btrfs_subvol_set_read_only(job->temp_path, true); if (r < 0) { log_error_errno(r, "Failed to mark snapshot read-only: %m"); goto fail; @@ -810,12 +818,17 @@ static size_t dkr_import_job_write_callback(void *contents, size_t size, size_t assert(contents); assert(j); + if (j->done) { + r = -ESTALE; + goto fail; + } + if (j->tar_stream) { size_t l; l = fwrite(contents, size, nmemb, j->tar_stream); if (l != nmemb) { - r = -errno; + r = log_error_errno(errno, "Failed to write to tar: %m"); goto fail; } @@ -823,13 +836,14 @@ static size_t dkr_import_job_write_callback(void *contents, size_t size, size_t } if (j->payload_size + sz > PAYLOAD_MAX) { + log_error("Payload too large."); r = -EFBIG; goto fail; } p = realloc(j->payload, j->payload_size + sz); if (!p) { - r = -ENOMEM; + r = log_oom(); goto fail; } @@ -858,6 +872,11 @@ static size_t dkr_import_job_header_callback(void *contents, size_t size, size_t assert(contents); assert(j); + if (j->done) { + r = -ESTALE; + goto fail; + } + r = curl_header_strdup(contents, sz, HEADER_TOKEN, &token); if (r < 0) { log_oom(); @@ -998,16 +1017,26 @@ static int dkr_import_name_begin(DkrImportName *name) { assert(name); assert(!name->job_images); - url = strappenda(name->index_url, "/v1/repositories/", name->name, "/images"); + url = strappenda(name->import->index_url, "/v1/repositories/", name->name, "/images"); return dkr_import_name_add_job(name, DKR_IMPORT_JOB_IMAGES, url, &name->job_images); } -int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished on_finished, void *userdata) { +int dkr_import_new( + DkrImport **import, + sd_event *event, + const char *index_url, + const char *image_root, + dkr_import_on_finished on_finished, + void *userdata) { + _cleanup_(dkr_import_unrefp) DkrImport *i = NULL; + char *e; int r; assert(import); + assert(dkr_url_is_valid(index_url)); + assert(image_root); i = new0(DkrImport, 1); if (!i) @@ -1016,6 +1045,18 @@ int dkr_import_new(DkrImport **import, sd_event *event, dkr_import_on_finished o i->on_finished = on_finished; i->userdata = userdata; + i->index_url = strdup(index_url); + if (!i->index_url) + return -ENOMEM; + + i->image_root = strdup(image_root); + if (!i->image_root) + return -ENOMEM; + + e = endswith(i->index_url, "/"); + if (e) + *e = 0; + if (event) i->event = sd_event_ref(event); else { @@ -1055,6 +1096,8 @@ DkrImport* dkr_import_unref(DkrImport *import) { curl_glue_unref(import->glue); sd_event_unref(import->event); + free(import->index_url); + free(import->image_root); free(import); return NULL; @@ -1074,13 +1117,11 @@ int dkr_import_cancel(DkrImport *import, const char *name) { return 1; } -int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, const char *tag, const char *local, bool force_local) { +int dkr_import_pull(DkrImport *import, const char *name, const char *tag, const char *local, bool force_local) { _cleanup_(dkr_import_name_unrefp) DkrImportName *n = NULL; - char *e; int r; assert(import); - assert(dkr_url_is_valid(index_url)); assert(dkr_name_is_valid(name)); assert(dkr_tag_is_valid(tag)); assert(!local || machine_name_is_valid(local)); @@ -1098,13 +1139,6 @@ int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, n->import = import; - n->index_url = strdup(index_url); - if (!n->index_url) - return -ENOMEM; - e = endswith(n->index_url, "/"); - if (e) - *e = 0; - n->name = strdup(name); if (!n->name) return -ENOMEM; @@ -1120,7 +1154,7 @@ int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, n->force_local = force_local; } - r = hashmap_put(import->names, name, n); + r = hashmap_put(import->names, n->name, n); if (r < 0) return r; @@ -1132,7 +1166,6 @@ int dkr_import_pull(DkrImport *import, const char *index_url, const char *name, } n = NULL; - return 0; } @@ -1168,6 +1201,8 @@ bool dkr_id_is_valid(const char *id) { } bool dkr_url_is_valid(const char *url) { + if (isempty(url)) + return false; if (!startswith(url, "http://") && !startswith(url, "https://"))