From 50dfca2eaf325835c2bd75565f65bfbe84d3cae5 Mon Sep 17 00:00:00 2001 From: Kevin Kuehler Date: Sun, 15 Mar 2020 13:46:27 -0700 Subject: [PATCH] import: Only keep RO copy if ETag header is set We fix the case when the webserver servers container images without setting the ETag header in the response. When an image is downloaded to image root, a read only copy is stored alongside it. The filename has the following form: .raw-.\x22\22.raw. This is so, if the same resource is fetched multiple times, importd can avoid extra downloads by creating the new image using the local read-only copy. The current code assumes the ETag header is set because, if the server does not set the ETag header, the file is stored without the ETag value in the filename. When importd fetches a duplicate image, it will run rename_noreplace and fail: Failed to rename raw file to /var/lib/machines/.raw-http:\x2f\x2flocalhost:8000\x2fwalkthroughd.raw: File exists This patch makes importd only store a read-only image if the webserver has set the ETag header. --- src/import/pull-raw.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/import/pull-raw.c b/src/import/pull-raw.c index 51c12444e00..0183c13f461 100644 --- a/src/import/pull-raw.c +++ b/src/import/pull-raw.c @@ -509,14 +509,17 @@ static void raw_pull_job_on_finished(PullJob *j) { raw_pull_report_progress(i, RAW_FINALIZING); - r = import_make_read_only_fd(i->raw_job->disk_fd); - if (r < 0) - goto finish; + if (i->raw_job->etag) { + /* Only make a read-only copy if ETag header is set. */ + r = import_make_read_only_fd(i->raw_job->disk_fd); + if (r < 0) + goto finish; - r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); - if (r < 0) { - log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path); - goto finish; + r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path); + if (r < 0) { + log_error_errno(r, "Failed to rename raw file to %s: %m", i->final_path); + goto finish; + } } i->temp_path = mfree(i->temp_path);