]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/import/import.c
import: three minor fixes
[thirdparty/systemd.git] / src / import / import.c
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"
28 #include "import-dkr.h"
29
30 static bool arg_force = false;
31
32 static const char* arg_dkr_index_url = DEFAULT_DKR_INDEX_URL;
33
34 static void on_finished(DkrImport *import, int error, void *userdata) {
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
46 static int pull_dkr(int argc, char *argv[], void *userdata) {
47 _cleanup_(dkr_import_unrefp) DkrImport *import = NULL;
48 _cleanup_event_unref_ sd_event *event = NULL;
49 const char *name, *tag, *local;
50 int r;
51
52 if (!arg_dkr_index_url) {
53 log_error("Please specify an index URL with --dkr-index-url=");
54 return -EINVAL;
55 }
56
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 (isempty(local) || streq(local, "-"))
77 local = NULL;
78
79 if (!dkr_name_is_valid(name)) {
80 log_error("Remote name '%s' is not valid.", name);
81 return -EINVAL;
82 }
83
84 if (!dkr_tag_is_valid(tag)) {
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(local)) {
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
118 r = dkr_import_new(&import, event, arg_dkr_index_url, on_dkr_finished, event);
119 if (r < 0)
120 return log_error_errno(r, "Failed to allocate importer: %m");
121
122 r = dkr_import_pull(import, name, tag, local, arg_force);
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
135 static 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"
141 " --force Force creation of image\n"
142 " --dkr-index-url=URL Specify index URL to use for downloads\n\n"
143 "Commands:\n"
144 " pull-dkr REMOTE [NAME] Download an image\n",
145 program_invocation_short_name);
146
147 return 0;
148 }
149
150 static int parse_argv(int argc, char *argv[]) {
151
152 enum {
153 ARG_VERSION = 0x100,
154 ARG_FORCE,
155 ARG_DKR_INDEX_URL,
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 },
162 { "dkr-index-url", required_argument, NULL, ARG_DKR_INDEX_URL },
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':
176 return help(0, NULL, NULL);
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
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
196 case '?':
197 return -EINVAL;
198
199 default:
200 assert_not_reached("Unhandled option");
201 }
202
203 return 1;
204 }
205
206 static int import_main(int argc, char *argv[]) {
207
208 static const Verb verbs[] = {
209 { "help", VERB_ANY, VERB_ANY, 0, help },
210 { "pull-dkr", 2, 3, 0, pull_dkr },
211 {}
212 };
213
214 return dispatch_verb(argc, argv, verbs, NULL);
215 }
216
217 int 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
230 finish:
231 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
232 }