]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/import/import.c
import: print friendly error messages on errors
[thirdparty/systemd.git] / src / import / import.c
CommitLineData
72648326
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2014 Lennart Poettering
7
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.
12
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.
17
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/>.
20***/
21
22#include <getopt.h>
23
24#include "sd-event.h"
25#include "event-util.h"
26#include "verbs.h"
27#include "build.h"
91f4347e 28#include "import-dkr.h"
72648326
LP
29
30static bool arg_force = false;
31
91f4347e
LP
32static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
33
34static void on_finished(DkrImport *import, int error, void *userdata) {
72648326
LP
35 sd_event *event = userdata;
36 assert(import);
37
38 if (error == 0)
39 log_info("Operation completed successfully.");
40 else
41 log_info_errno(error, "Operation failed: %m");
42
43 sd_event_exit(event, error);
44}
45
91f4347e
LP
46static int pull_dkr(int argc, char *argv[], void *userdata) {
47 _cleanup_(dkr_import_unrefp) DkrImport *import = NULL;
72648326
LP
48 _cleanup_event_unref_ sd_event *event = NULL;
49 const char *name, *tag, *local;
50 int r;
51
91f4347e
LP
52 if (!arg_dkr_index_url) {
53 log_error("Please specify an index URL with --dkr-index-url=");
54 return -EINVAL;
55 }
56
72648326
LP
57 tag = strchr(argv[1], ':');
58 if (tag) {
59 name = strndupa(argv[1], tag - argv[1]);
60 tag++;
61 } else {
62 name = argv[1];
63 tag = "latest";
64 }
65
66 if (argc >= 3)
67 local = argv[2];
68 else {
69 local = strchr(name, '/');
70 if (local)
71 local++;
72 else
73 local = name;
74 }
75
76 if (streq(local, "-") || isempty(local))
77 local = NULL;
78
91f4347e 79 if (!dkr_name_is_valid(name)) {
72648326
LP
80 log_error("Remote name '%s' is not valid.", name);
81 return -EINVAL;
82 }
83
91f4347e 84 if (!dkr_tag_is_valid(tag)) {
72648326
LP
85 log_error("Tag name '%s' is not valid.", tag);
86 return -EINVAL;
87 }
88
89 if (local) {
90 const char *p;
91
92 if (!machine_name_is_valid(tag)) {
93 log_error("Local image name '%s' is not valid.", local);
94 return -EINVAL;
95 }
96
97 p = strappenda("/var/lib/container/", local);
98 if (laccess(p, F_OK) >= 0) {
99 if (!arg_force) {
100 log_info("Image '%s' already exists.", local);
101 return 0;
102 }
103 } else if (errno != ENOENT)
104 return log_error_errno(errno, "Can't check if image '%s' already exists: %m", local);
105
106 log_info("Pulling '%s' with tag '%s', saving as '%s'.", name, tag, local);
107 } else
108 log_info("Pulling '%s' with tag '%s'.", name, tag);
109
110 r = sd_event_default(&event);
111 if (r < 0)
112 return log_error_errno(r, "Failed to allocate event loop: %m");
113
114 assert_se(sigprocmask_many(SIG_BLOCK, SIGTERM, SIGINT, -1) == 0);
115 sd_event_add_signal(event, NULL, SIGTERM, NULL, NULL);
116 sd_event_add_signal(event, NULL, SIGINT, NULL, NULL);
117
ea1ae8c3 118 r = dkr_import_new(&import, event, arg_dkr_index_url, on_dkr_finished, event);
72648326
LP
119 if (r < 0)
120 return log_error_errno(r, "Failed to allocate importer: %m");
121
ea1ae8c3 122 r = dkr_import_pull(import, name, tag, local, arg_force);
72648326
LP
123 if (r < 0)
124 return log_error_errno(r, "Failed to pull image: %m");
125
126 r = sd_event_loop(event);
127 if (r < 0)
128 return log_error_errno(r, "Failed to run event loop: %m");
129
130 log_info("Exiting.");
131
132 return 0;
133}
134
135static int help(int argc, char *argv[], void *userdata) {
136
137 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
138 "Import container or virtual machine image.\n\n"
139 " -h --help Show this help\n"
140 " --version Show package version\n"
91f4347e
LP
141 " --force Force creation of image\n"
142 " --dkr-index-url=URL Specify index URL to use for downloads\n\n"
72648326 143 "Commands:\n"
91f4347e 144 " pull-dkr REMOTE [NAME] Download an image\n",
72648326
LP
145 program_invocation_short_name);
146
147 return 0;
148}
149
150static int parse_argv(int argc, char *argv[]) {
151
152 enum {
153 ARG_VERSION = 0x100,
154 ARG_FORCE,
91f4347e 155 ARG_DKR_INDEX_URL,
72648326
LP
156 };
157
158 static const struct option options[] = {
159 { "help", no_argument, NULL, 'h' },
160 { "version", no_argument, NULL, ARG_VERSION },
161 { "force", no_argument, NULL, ARG_FORCE },
91f4347e 162 { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
72648326
LP
163 {}
164 };
165
166 int c;
167
168 assert(argc >= 0);
169 assert(argv);
170
171 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
172
173 switch (c) {
174
175 case 'h':
7eeeb28e 176 return help(0, NULL, NULL);
72648326
LP
177
178 case ARG_VERSION:
179 puts(PACKAGE_STRING);
180 puts(SYSTEMD_FEATURES);
181 return 0;
182
183 case ARG_FORCE:
184 arg_force = true;
185 break;
186
91f4347e
LP
187 case ARG_DKR_INDEX_URL:
188 if (!dkr_url_is_valid(optarg)) {
189 log_error("Index URL is not valid: %s", optarg);
190 return -EINVAL;
191 }
192
193 arg_dkr_index_url = optarg;
194 break;
195
72648326
LP
196 case '?':
197 return -EINVAL;
198
199 default:
200 assert_not_reached("Unhandled option");
201 }
202
203 return 1;
204}
205
206static int import_main(int argc, char *argv[]) {
207
7eeeb28e 208 static const Verb verbs[] = {
72648326 209 { "help", VERB_ANY, VERB_ANY, 0, help },
91f4347e 210 { "pull-dkr", 2, 3, 0, pull_dkr },
72648326
LP
211 {}
212 };
213
214 return dispatch_verb(argc, argv, verbs, NULL);
215}
216
217int main(int argc, char *argv[]) {
218 int r;
219
220 setlocale(LC_ALL, "");
221 log_parse_environment();
222 log_open();
223
224 r = parse_argv(argc, argv);
225 if (r <= 0)
226 goto finish;
227
228 r = import_main(argc, argv);
229
230finish:
231 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
232}