struct DkrImportName {
DkrImport *import;
- char *index_url;
char *name;
char *tag;
char *id;
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://"
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);
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
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);
if (null_fd != STDOUT_FILENO)
safe_close(null_fd);
- execlp("tar", "tar", "-C", job->temp_path, gzip ? "-xz" : "-x", NULL);
+ execlp("tar", "tar", "-C", job->temp_path, gzip ? "-xpz" : "-px", "--numeric-owner", NULL);
_exit(EXIT_FAILURE);
}
return 0;
}
- path = strjoin("/var/lib/container/.dkr-", layer, NULL);
+ path = strjoin(name->import->image_root, "/.dkr-", layer, NULL);
if (!path)
return log_oom();
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);
if (curl_easy_getinfo(curl, CURLINFO_PRIVATE, &job) != CURLE_OK)
return;
- if (!job)
+ if (!job || job->done)
return;
job->done = true;
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;
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;
}
}
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;
}
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();
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)
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 {
curl_glue_unref(import->glue);
sd_event_unref(import->event);
+ free(import->index_url);
+ free(import->image_root);
free(import);
return NULL;
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));
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;
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;
}
n = NULL;
-
return 0;
}
}
bool dkr_url_is_valid(const char *url) {
+ if (isempty(url))
+ return false;
if (!startswith(url, "http://") &&
!startswith(url, "https://"))