chiark / gitweb /
import: minor improvements to dkr importer
[elogind.git] / src / import / import-dkr.c
index e2910f940fa1a69702e24739d029bfca0c3b5ab3..16580538102d8465026a5ce79ec94787defc2334 100644 (file)
@@ -76,7 +76,6 @@ struct DkrImportJob {
 struct DkrImportName {
         DkrImport *import;
 
-        char *index_url;
         char *name;
         char *tag;
         char *id;
@@ -94,11 +93,15 @@ struct DkrImport {
         sd_event *event;
         CurlGlue *glue;
 
+        char *index_url;
+
         Hashmap *names;
         Hashmap *jobs;
 
         dkr_import_on_finished on_finished;
         void *userdata;
+
+        bool finished;
 };
 
 #define PROTOCOL_PREFIX "https://"
@@ -163,7 +166,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 +183,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
@@ -414,7 +421,7 @@ static void dkr_import_name_maybe_finish(DkrImportName *name) {
                         return;
                 }
 
-                log_info("Created new image %s.", p);
+                log_info("Created new local image %s.", p);
         }
 
         dkr_import_finish(name->import, 0);
@@ -711,7 +718,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 +780,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 +817,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 +835,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 +871,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 +1016,18 @@ 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, 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));
 
         i = new0(DkrImport, 1);
         if (!i)
@@ -1016,6 +1036,14 @@ 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;
+
+        e = endswith(i->index_url, "/");
+        if (e)
+                *e = 0;
+
         if (event)
                 i->event = sd_event_ref(event);
         else {
@@ -1055,6 +1083,8 @@ DkrImport* dkr_import_unref(DkrImport *import) {
         curl_glue_unref(import->glue);
         sd_event_unref(import->event);
 
+        free(import->index_url);
+
         free(import);
 
         return NULL;
@@ -1074,13 +1104,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 +1126,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 = NULL;
-
         n->name = strdup(name);
         if (!n->name)
                 return -ENOMEM;
@@ -1120,7 +1141,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 +1153,6 @@ int dkr_import_pull(DkrImport *import, const char *index_url, const char *name,
         }
 
         n = NULL;
-
         return 0;
 }
 
@@ -1168,6 +1188,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://"))