import.c revision 8f6950587ab7b4d6fe1b51241759cc3a4682b96d
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek This file is part of systemd.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek Copyright 2014 Lennart Poettering
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek systemd is free software; you can redistribute it and/or modify it
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek under the terms of the GNU Lesser General Public License as published by
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek the Free Software Foundation; either version 2.1 of the License, or
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek (at your option) any later version.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek systemd is distributed in the hope that it will be useful, but
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek WITHOUT ANY WARRANTY; without even the implied warranty of
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek Lesser General Public License for more details.
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek You should have received a copy of the GNU Lesser General Public License
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek along with systemd; If not, see <http://www.gnu.org/licenses/>.
a5c32cff1f56afe6f0c6c70d91a88a7a8238b2d7Harald Hoyerstatic bool arg_force = false;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic const char *arg_image_root = "/var/lib/machines";
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic ImportVerify arg_verify = IMPORT_VERIFY_SIGNATURE;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic void on_tar_finished(TarImport *import, int error, void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_info("Operation completed successfully.");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error_errno(error, "Operation failed: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int strip_tar_suffixes(const char *name, char **ret) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int pull_tar(int argc, char *argv[], void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_(tar_import_unrefp) TarImport *import = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_event_unref_ sd_event *event = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_free_ char *l = NULL, *ll = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("URL '%s' is not valid.", url);
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek r = import_url_last_component(url, &l);
7fd1b19bc9e9f5574f2877936b8ac267c7706947Harald Hoyer return log_error_errno(r, "Failed get final component of URL: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = strip_tar_suffixes(local, &ll);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!machine_name_is_valid(local)) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Local image name '%s' is not valid.", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (r > 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error_errno(EEXIST, "Image '%s' already exists.", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_info("Pulling '%s', saving as '%s'.", url, local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to allocate event loop: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
db91ea32aa223d1b087d99811226a9c59a1bb281Zbigniew Jędrzejewski-Szmek sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = tar_import_new(&import, event, arg_image_root, on_tar_finished, event);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to allocate importer: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = tar_import_pull(import, url, local, arg_force);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to pull image: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to run event loop: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic void on_raw_finished(RawImport *import, int error, void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_info("Operation completed successfully.");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error_errno(error, "Operation failed: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int strip_raw_suffixes(const char *p, char **ret) {
670b110c3b59dfa335ac43065b2038400d1d04a9Zbigniew Jędrzejewski-Szmek static const char suffixes[] =
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int pull_raw(int argc, char *argv[], void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_(raw_import_unrefp) RawImport *import = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_event_unref_ sd_event *event = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_free_ char *l = NULL, *ll = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("URL '%s' is not valid.", url);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = import_url_last_component(url, &l);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed get final component of URL: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (isempty(local) || streq(local, "-"))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = strip_raw_suffixes(local, &ll);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!machine_name_is_valid(local)) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Local image name '%s' is not valid.", local);
23ad4dd8844c582929115a11ed2830a1371568d6Jan Alexander Steffens (heftig) return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek else if (r > 0) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error_errno(EEXIST, "Image '%s' already exists.", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_info("Pulling '%s', saving as '%s'.", url, local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to allocate event loop: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = raw_import_new(&import, event, arg_image_root, on_raw_finished, event);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to allocate importer: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek r = raw_import_pull(import, url, local, arg_force, arg_verify);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to pull image: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to run event loop: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic void on_dkr_finished(DkrImport *import, int error, void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_info("Operation completed successfully.");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error_errno(error, "Operation failed: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int pull_dkr(int argc, char *argv[], void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_(dkr_import_unrefp) DkrImport *import = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek _cleanup_event_unref_ sd_event *event = NULL;
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Please specify an index URL with --dkr-index-url=");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (arg_verify != IMPORT_VERIFY_NO) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Imports from dkr do not support image verification, please pass --verify=no.");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek name = strndupa(argv[1], tag - argv[1]);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Remote name '%s' is not valid.", name);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Tag name '%s' is not valid.", tag);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (isempty(local) || streq(local, "-"))
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!machine_name_is_valid(local)) {
7d73c1343be02a59b17de0cd34375deeb815d89cLennart Poettering log_error("Local image name '%s' is not valid.", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek p = strappenda(arg_image_root, "/", local);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_info("Image '%s' already exists.", local);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return log_error_errno(errno, "Can't check if image '%s' already exists: %m", local);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk log_info("Pulling '%s' with tag '%s', saving as '%s'.", name, tag, local);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk log_info("Pulling '%s' with tag '%s'.", name, tag);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return log_error_errno(r, "Failed to allocate event loop: %m");
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk r = dkr_import_new(&import, event, arg_dkr_index_url, arg_image_root, on_dkr_finished, event);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return log_error_errno(r, "Failed to allocate importer: %m");
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk r = dkr_import_pull(import, name, tag, local, arg_force);
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return log_error_errno(r, "Failed to pull image: %m");
26687bf8a907009dedcff79346860ed41511405eOleksii Shevchuk return log_error_errno(r, "Failed to run event loop: %m");
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int help(int argc, char *argv[], void *userdata) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek printf("%s [OPTIONS...] {COMMAND} ...\n\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek "Import container or virtual machine image.\n\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " -h --help Show this help\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " --version Show package version\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " --force Force creation of image\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " --verify= Verify downloaded image, one of: 'no', 'sum'\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " 'signature'.\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " --image-root= Image root directory\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " --dkr-index-url=URL Specify index URL to use for downloads\n\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " pull-tar URL [NAME] Download a TAR image\n"
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek " pull-raw URL [NAME] Download a RAW image\n"
ed375bebf46c1251f4baa170b39ee93761dbdb19Zbigniew Jędrzejewski-Szmek " pull-dkr REMOTE [NAME] Download a DKR image\n",
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekstatic int parse_argv(int argc, char *argv[]) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek static const struct option options[] = {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "help", no_argument, NULL, 'h' },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "version", no_argument, NULL, ARG_VERSION },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "force", no_argument, NULL, ARG_FORCE },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "verify", required_argument, NULL, ARG_VERIFY },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek if (!dkr_url_is_valid(optarg)) {
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Index URL is not valid: %s", optarg);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek arg_verify = import_verify_from_string(optarg);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek log_error("Invalid verification setting '%s'", optarg);
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmekstatic int import_main(int argc, char *argv[]) {
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek { "help", VERB_ANY, VERB_ANY, 0, help },
e40ec7aec5e64cd0cfa5fc556d6a9747229b5794Zbigniew Jędrzejewski-Szmek { "pull-tar", 2, 3, 0, pull_tar },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "pull-raw", 2, 3, 0, pull_raw },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek { "pull-dkr", 2, 3, 0, pull_dkr },
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmek return dispatch_verb(argc, argv, verbs, NULL);
d025f1e4dca8fc1436aff76f9e6185fe3e728daaZbigniew Jędrzejewski-Szmekint main(int argc, char *argv[]) {