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-gpt.h"
29 #include "import-dkr.h"
31 static bool arg_force = false;
33 static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
35 static void on_gpt_finished(GptImport *import, int error, void *userdata) {
36 sd_event *event = userdata;
40 log_info("Operation completed successfully.");
42 log_info_errno(error, "Operation failed: %m");
44 sd_event_exit(event, error);
47 static int pull_gpt(int argc, char *argv[], void *userdata) {
48 _cleanup_(gpt_import_unrefp) GptImport *import = NULL;
49 _cleanup_event_unref_ sd_event *event = NULL;
50 const char *url, *local, *suffix;
54 if (!gpt_url_is_valid(url)) {
55 log_error("URL '%s' is not valid.", url);
64 e = url + strlen(url);
65 while (e > url && e[-1] == '/')
69 while (p > url && p[-1] != '/')
72 local = strndupa(p, e - p);
75 if (isempty(local) || streq(local, "-"))
81 suffix = endswith(local, ".gpt");
83 local = strndupa(local, suffix - local);
85 if (!machine_name_is_valid(local)) {
86 log_error("Local image name '%s' is not valid.", local);
90 p = strappenda("/var/lib/container/", local, ".gpt");
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', saving as '%s'.", url, local);
101 log_info("Pulling '%s'.", url);
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 = gpt_import_new(&import, event, on_gpt_finished, event);
113 return log_error_errno(r, "Failed to allocate importer: %m");
115 r = gpt_import_pull(import, url, 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 void on_dkr_finished(DkrImport *import, int error, void *userdata) {
129 sd_event *event = userdata;
133 log_info("Operation completed successfully.");
135 log_info_errno(error, "Operation failed: %m");
137 sd_event_exit(event, error);
140 static int pull_dkr(int argc, char *argv[], void *userdata) {
141 _cleanup_(dkr_import_unrefp) DkrImport *import = NULL;
142 _cleanup_event_unref_ sd_event *event = NULL;
143 const char *name, *tag, *local;
146 if (!arg_dkr_index_url) {
147 log_error("Please specify an index URL with --dkr-index-url=");
151 tag = strchr(argv[1], ':');
153 name = strndupa(argv[1], tag - argv[1]);
160 if (!dkr_name_is_valid(name)) {
161 log_error("Remote name '%s' is not valid.", name);
165 if (!dkr_tag_is_valid(tag)) {
166 log_error("Tag name '%s' is not valid.", tag);
173 local = strchr(name, '/');
180 if (isempty(local) || streq(local, "-"))
186 if (!machine_name_is_valid(local)) {
187 log_error("Local image name '%s' is not valid.", local);
191 p = strappenda("/var/lib/container/", local);
192 if (laccess(p, F_OK) >= 0) {
194 log_info("Image '%s' already exists.", local);
197 } else if (errno != ENOENT)
198 return log_error_errno(errno, "Can't check if image '%s' already exists: %m", local);
200 log_info("Pulling '%s' with tag '%s', saving as '%s'.", name, tag, local);
202 log_info("Pulling '%s' with tag '%s'.", name, tag);
204 r = sd_event_default(&event);
206 return log_error_errno(r, "Failed to allocate event loop: %m");
208 assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
209 sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
210 sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
212 r = dkr_import_new(&import, event, arg_dkr_index_url, on_dkr_finished, event);
214 return log_error_errno(r, "Failed to allocate importer: %m");
216 r = dkr_import_pull(import, name, tag, local, arg_force);
218 return log_error_errno(r, "Failed to pull image: %m");
220 r = sd_event_loop(event);
222 return log_error_errno(r, "Failed to run event loop: %m");
224 log_info("Exiting.");
229 static int help(int argc, char *argv[], void *userdata) {
231 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
232 "Import container or virtual machine image.\n\n"
233 " -h --help Show this help\n"
234 " --version Show package version\n"
235 " --force Force creation of image\n"
236 " --dkr-index-url=URL Specify index URL to use for downloads\n\n"
238 " pull-dkr REMOTE [NAME] Download a DKR image\n"
239 " pull-gpt URL [NAME] Download a GPT image\n",
240 program_invocation_short_name);
245 static int parse_argv(int argc, char *argv[]) {
253 static const struct option options[] = {
254 { "help", no_argument, NULL, 'h' },
255 { "version", no_argument, NULL, ARG_VERSION },
256 { "force", no_argument, NULL, ARG_FORCE },
257 { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
266 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
271 return help(0, NULL, NULL);
274 puts(PACKAGE_STRING);
275 puts(SYSTEMD_FEATURES);
282 case ARG_DKR_INDEX_URL:
283 if (!dkr_url_is_valid(optarg)) {
284 log_error("Index URL is not valid: %s", optarg);
288 arg_dkr_index_url = optarg;
295 assert_not_reached("Unhandled option");
301 static int import_main(int argc, char *argv[]) {
303 static const Verb verbs[] = {
304 { "help", VERB_ANY, VERB_ANY, 0, help },
305 { "pull-dkr", 2, 3, 0, pull_dkr },
306 { "pull-gpt", 2, 3, 0, pull_gpt },
310 return dispatch_verb(argc, argv, verbs, NULL);
313 int main(int argc, char *argv[]) {
316 setlocale(LC_ALL, "");
317 log_parse_environment();
320 r = parse_argv(argc, argv);
324 r = import_main(argc, argv);
327 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;