1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2014 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include "event-util.h"
28 #include "import-dck.h"
30 static bool arg_force = false;
32 static void on_finished(DckImport *import, int error, void *userdata) {
33 sd_event *event = userdata;
37 log_info("Operation completed successfully.");
39 log_info_errno(error, "Operation failed: %m");
41 sd_event_exit(event, error);
44 static int pull_dck(int argc, char *argv[], void *userdata) {
45 _cleanup_(dck_import_unrefp) DckImport *import = NULL;
46 _cleanup_event_unref_ sd_event *event = NULL;
47 const char *name, *tag, *local;
50 tag = strchr(argv[1], ':');
52 name = strndupa(argv[1], tag - argv[1]);
62 local = strchr(name, '/');
69 if (streq(local, "-") || isempty(local))
72 if (!dck_name_is_valid(name)) {
73 log_error("Remote name '%s' is not valid.", name);
77 if (!dck_tag_is_valid(tag)) {
78 log_error("Tag name '%s' is not valid.", tag);
85 if (!machine_name_is_valid(tag)) {
86 log_error("Local image name '%s' is not valid.", local);
90 p = strappenda("/var/lib/container/", local);
91 if (laccess(p, F_OK) >= 0) {
93 log_info("Image '%s' already exists.", local);
96 } else if (errno != ENOENT)
97 return log_error_errno(errno, "Can't check if image '%s' already exists: %m", local);
99 log_info("Pulling '%s' with tag '%s', saving as '%s'.", name, tag, local);
101 log_info("Pulling '%s' with tag '%s'.", name, tag);
103 r = sd_event_default(&event);
105 return log_error_errno(r, "Failed to allocate event loop: %m");
107 assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
108 sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
109 sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
111 r = dck_import_new(&import, event, on_finished, event);
113 return log_error_errno(r, "Failed to allocate importer: %m");
115 r = dck_import_pull(import, name, tag, local, arg_force);
117 return log_error_errno(r, "Failed to pull image: %m");
119 r = sd_event_loop(event);
121 return log_error_errno(r, "Failed to run event loop: %m");
123 log_info("Exiting.");
128 static int help(int argc, char *argv[], void *userdata) {
130 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
131 "Import container or virtual machine image.\n\n"
132 " -h --help Show this help\n"
133 " --version Show package version\n"
134 " --force Force creation of image\n\n"
136 " pull-dck REMOTE [NAME] Download an image\n",
137 program_invocation_short_name);
142 static int parse_argv(int argc, char *argv[]) {
149 static const struct option options[] = {
150 { "help", no_argument, NULL, 'h' },
151 { "version", no_argument, NULL, ARG_VERSION },
152 { "force", no_argument, NULL, ARG_FORCE },
161 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
166 return help(argc, argv, NULL);
169 puts(PACKAGE_STRING);
170 puts(SYSTEMD_FEATURES);
181 assert_not_reached("Unhandled option");
187 static int import_main(int argc, char *argv[]) {
189 const Verb verbs[] = {
190 { "help", VERB_ANY, VERB_ANY, 0, help },
191 { "pull-dck", 2, 3, 0, pull_dck },
195 return dispatch_verb(argc, argv, verbs, NULL);
198 int main(int argc, char *argv[]) {
201 setlocale(LC_ALL, "");
202 log_parse_environment();
205 r = parse_argv(argc, argv);
209 r = import_main(argc, argv);
212 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;