X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fimport%2Fimport-tar.c;h=80ae83971efb93dd03164584bda76dff2c4d1797;hp=08839caae76a281fec8af7fb5f893f9ffc32f9ab;hb=2c140ded48fc31e3c80a92a1f755a2b1ab6e1a30;hpb=0d6e763b48cabe8899a20823b015c9a988e38659;ds=sidebyside diff --git a/src/import/import-tar.c b/src/import/import-tar.c index 08839caae..80ae83971 100644 --- a/src/import/import-tar.c +++ b/src/import/import-tar.c @@ -29,9 +29,10 @@ #include "util.h" #include "macro.h" #include "mkdir.h" +#include "import-util.h" #include "curl-util.h" #include "import-job.h" -#include "import-util.h" +#include "import-common.h" #include "import-tar.h" struct TarImport { @@ -41,6 +42,8 @@ struct TarImport { char *image_root; ImportJob *tar_job; + ImportJob *checksum_job; + ImportJob *signature_job; TarImportFinished on_finished; void *userdata; @@ -52,18 +55,22 @@ struct TarImport { char *temp_path; char *final_path; + + ImportVerify verify; }; TarImport* tar_import_unref(TarImport *i) { if (!i) return NULL; - if (i->tar_pid > 0) { - kill(i->tar_pid, SIGKILL); - wait_for_terminate(i->tar_pid, NULL); + if (i->tar_pid > 1) { + (void) kill_and_sigcont(i->tar_pid, SIGKILL); + (void) wait_for_terminate(i->tar_pid, NULL); } import_job_unref(i->tar_job); + import_job_unref(i->checksum_job); + import_job_unref(i->signature_job); curl_glue_unref(i->glue); sd_event_unref(i->event); @@ -77,13 +84,18 @@ TarImport* tar_import_unref(TarImport *i) { free(i->final_path); free(i->image_root); free(i->local); - free(i); return NULL; } -int tar_import_new(TarImport **ret, sd_event *event, const char *image_root, TarImportFinished on_finished, void *userdata) { +int tar_import_new( + TarImport **ret, + sd_event *event, + const char *image_root, + TarImportFinished on_finished, + void *userdata) { + _cleanup_(tar_import_unrefp) TarImport *i = NULL; int r; @@ -135,15 +147,29 @@ static int tar_import_make_local_copy(TarImport *i) { r = import_make_path(i->tar_job->url, i->tar_job->etag, i->image_root, ".tar-", NULL, &i->final_path); if (r < 0) return log_oom(); - - r = import_make_local_copy(i->final_path, i->image_root, i->local, i->force_local); - if (r < 0) - return r; } + r = import_make_local_copy(i->final_path, i->image_root, i->local, i->force_local); + if (r < 0) + return r; + return 0; } +static bool tar_import_is_done(TarImport *i) { + assert(i); + assert(i->tar_job); + + if (i->tar_job->state != IMPORT_JOB_DONE) + return false; + if (i->checksum_job && i->checksum_job->state != IMPORT_JOB_DONE) + return false; + if (i->signature_job && i->signature_job->state != IMPORT_JOB_DONE) + return false; + + return true; +} + static void tar_import_job_on_finished(ImportJob *j) { TarImport *i; int r; @@ -153,6 +179,13 @@ static void tar_import_job_on_finished(ImportJob *j) { i = j->userdata; if (j->error != 0) { + if (j == i->checksum_job) + log_error_errno(j->error, "Failed to retrieve SHA256 checksum, cannot verify. (Try --verify=no?)"); + else if (j == i->signature_job) + log_error_errno(j->error, "Failed to retrieve signature file, cannot verify. (Try --verify=no?)"); + else + log_error_errno(j->error, "Failed to retrieve image file. (Wrong URL?)"); + r = j->error; goto finish; } @@ -161,7 +194,10 @@ static void tar_import_job_on_finished(ImportJob *j) { * successfully, or the download was skipped because we * already have the etag. */ - j->disk_fd = safe_close(j->disk_fd); + if (!tar_import_is_done(i)) + return; + + j->disk_fd = safe_close(i->tar_job->disk_fd); if (i->tar_pid > 0) { r = wait_for_terminate_and_warn("tar", i->tar_pid, true); @@ -170,7 +206,13 @@ static void tar_import_job_on_finished(ImportJob *j) { goto finish; } - if (i->temp_path) { + if (!i->tar_job->etag_exists) { + /* This is a new download, verify it, and move it into place */ + + r = import_verify(i->tar_job, i->checksum_job, i->signature_job); + if (r < 0) + goto finish; + r = import_make_read_only(i->temp_path); if (r < 0) goto finish; @@ -206,6 +248,10 @@ static int tar_import_job_on_open_disk(ImportJob *j) { assert(j->userdata); i = j->userdata; + assert(i->tar_job == j); + assert(!i->final_path); + assert(!i->temp_path); + assert(i->tar_pid <= 0); r = import_make_path(j->url, j->etag, i->image_root, ".tar-", NULL, &i->final_path); if (r < 0) @@ -224,74 +270,32 @@ static int tar_import_job_on_open_disk(ImportJob *j) { } else if (r < 0) return log_error_errno(errno, "Failed to create subvolume %s: %m", i->temp_path); - if (pipe2(pipefd, O_CLOEXEC) < 0) - return log_error_errno(errno, "Failed to create pipe for tar: %m"); - - i->tar_pid = fork(); - if (i->tar_pid < 0) - return log_error_errno(errno, "Failed to fork off tar: %m"); - if (i->tar_pid == 0) { - int null_fd; - - reset_all_signal_handlers(); - reset_signal_mask(); - assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0); - - pipefd[1] = safe_close(pipefd[1]); - - if (dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (pipefd[0] != STDIN_FILENO) - safe_close(pipefd[0]); - - null_fd = open("/dev/null", O_WRONLY|O_NOCTTY); - if (null_fd < 0) { - log_error_errno(errno, "Failed to open /dev/null: %m"); - _exit(EXIT_FAILURE); - } - - if (dup2(null_fd, STDOUT_FILENO) != STDOUT_FILENO) { - log_error_errno(errno, "Failed to dup2() fd: %m"); - _exit(EXIT_FAILURE); - } - - if (null_fd != STDOUT_FILENO) - safe_close(null_fd); - - execlp("tar", "tar", "--numeric-owner", "-C", i->temp_path, "-px", NULL); - _exit(EXIT_FAILURE); - } - - pipefd[0] = safe_close(pipefd[0]); - - j->disk_fd = pipefd[1]; - pipefd[1] = -1; + j->disk_fd = import_fork_tar(i->temp_path, &i->tar_pid); + if (j->disk_fd < 0) + return j->disk_fd; return 0; } -int tar_import_pull(TarImport *i, const char *url, const char *local, bool force_local) { +int tar_import_pull(TarImport *i, const char *url, const char *local, bool force_local, ImportVerify verify) { int r; assert(i); - if (i->tar_job) - return -EBUSY; - if (!http_url_is_valid(url)) return -EINVAL; if (local && !machine_name_is_valid(local)) return -EINVAL; + if (i->tar_job) + return -EBUSY; + r = free_and_strdup(&i->local, local); if (r < 0) return r; - i->force_local = force_local; + i->verify = verify; r = import_job_new(&i->tar_job, url, i->glue, i); if (r < 0) @@ -299,10 +303,31 @@ int tar_import_pull(TarImport *i, const char *url, const char *local, bool force i->tar_job->on_finished = tar_import_job_on_finished; i->tar_job->on_open_disk = tar_import_job_on_open_disk; + i->tar_job->calc_checksum = verify != IMPORT_VERIFY_NO; r = import_find_old_etags(url, i->image_root, DT_DIR, ".tar-", NULL, &i->tar_job->old_etags); if (r < 0) return r; - return import_job_begin(i->tar_job); + r = import_make_verification_jobs(&i->checksum_job, &i->signature_job, verify, url, i->glue, tar_import_job_on_finished, i); + if (r < 0) + return r; + + r = import_job_begin(i->tar_job); + if (r < 0) + return r; + + if (i->checksum_job) { + r = import_job_begin(i->checksum_job); + if (r < 0) + return r; + } + + if (i->signature_job) { + r = import_job_begin(i->signature_job); + if (r < 0) + return r; + } + + return 0; }