2 This file is part of systemd.
4 Copyright 2015 Lennart Poettering
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
24 #include "alloc-util.h"
27 #include "hostname-util.h"
28 #include "import-raw.h"
29 #include "import-tar.h"
30 #include "import-util.h"
31 #include "machine-image.h"
32 #include "signal-util.h"
33 #include "string-util.h"
36 static bool arg_force
= false;
37 static bool arg_read_only
= false;
38 static const char *arg_image_root
= "/var/lib/machines";
40 static int interrupt_signal_handler(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
41 log_notice("Transfer aborted.");
42 sd_event_exit(sd_event_source_get_event(s
), EINTR
);
46 static void on_tar_finished(TarImport
*import
, int error
, void *userdata
) {
47 sd_event
*event
= userdata
;
51 log_info("Operation completed successfully.");
53 sd_event_exit(event
, abs(error
));
56 static int import_tar(int argc
, char *argv
[], void *userdata
) {
57 _cleanup_(tar_import_unrefp
) TarImport
*import
= NULL
;
58 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
59 const char *path
= NULL
, *local
= NULL
;
60 _cleanup_free_
char *ll
= NULL
;
61 _cleanup_close_
int open_fd
= -1;
66 if (isempty(path
) || streq(path
, "-"))
72 local
= basename(path
);
73 if (isempty(local
) || streq(local
, "-"))
77 r
= tar_strip_suffixes(local
, &ll
);
83 if (!machine_name_is_valid(local
)) {
84 log_error("Local image name '%s' is not valid.", local
);
89 r
= image_find(local
, NULL
);
91 return log_error_errno(r
, "Failed to check whether image '%s' exists: %m", local
);
93 log_error("Image '%s' already exists.", local
);
101 open_fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
103 return log_error_errno(errno
, "Failed to open tar image to import: %m");
107 log_info("Importing '%s', saving as '%s'.", path
, local
);
109 _cleanup_free_
char *pretty
= NULL
;
113 (void) readlink_malloc("/proc/self/fd/0", &pretty
);
114 log_info("Importing '%s', saving as '%s'.", strna(pretty
), local
);
117 r
= sd_event_default(&event
);
119 return log_error_errno(r
, "Failed to allocate event loop: %m");
121 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
122 (void) sd_event_add_signal(event
, NULL
, SIGTERM
, interrupt_signal_handler
, NULL
);
123 (void) sd_event_add_signal(event
, NULL
, SIGINT
, interrupt_signal_handler
, NULL
);
125 r
= tar_import_new(&import
, event
, arg_image_root
, on_tar_finished
, event
);
127 return log_error_errno(r
, "Failed to allocate importer: %m");
129 r
= tar_import_start(import
, fd
, local
, arg_force
, arg_read_only
);
131 return log_error_errno(r
, "Failed to import image: %m");
133 r
= sd_event_loop(event
);
135 return log_error_errno(r
, "Failed to run event loop: %m");
137 log_info("Exiting.");
141 static void on_raw_finished(RawImport
*import
, int error
, void *userdata
) {
142 sd_event
*event
= userdata
;
146 log_info("Operation completed successfully.");
148 sd_event_exit(event
, abs(error
));
151 static int import_raw(int argc
, char *argv
[], void *userdata
) {
152 _cleanup_(raw_import_unrefp
) RawImport
*import
= NULL
;
153 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
154 const char *path
= NULL
, *local
= NULL
;
155 _cleanup_free_
char *ll
= NULL
;
156 _cleanup_close_
int open_fd
= -1;
161 if (isempty(path
) || streq(path
, "-"))
167 local
= basename(path
);
168 if (isempty(local
) || streq(local
, "-"))
172 r
= raw_strip_suffixes(local
, &ll
);
178 if (!machine_name_is_valid(local
)) {
179 log_error("Local image name '%s' is not valid.", local
);
184 r
= image_find(local
, NULL
);
186 return log_error_errno(r
, "Failed to check whether image '%s' exists: %m", local
);
188 log_error("Image '%s' already exists.", local
);
196 open_fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
198 return log_error_errno(errno
, "Failed to open raw image to import: %m");
202 log_info("Importing '%s', saving as '%s'.", path
, local
);
204 _cleanup_free_
char *pretty
= NULL
;
208 (void) readlink_malloc("/proc/self/fd/0", &pretty
);
209 log_info("Importing '%s', saving as '%s'.", pretty
, local
);
212 r
= sd_event_default(&event
);
214 return log_error_errno(r
, "Failed to allocate event loop: %m");
216 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
217 (void) sd_event_add_signal(event
, NULL
, SIGTERM
, interrupt_signal_handler
, NULL
);
218 (void) sd_event_add_signal(event
, NULL
, SIGINT
, interrupt_signal_handler
, NULL
);
220 r
= raw_import_new(&import
, event
, arg_image_root
, on_raw_finished
, event
);
222 return log_error_errno(r
, "Failed to allocate importer: %m");
224 r
= raw_import_start(import
, fd
, local
, arg_force
, arg_read_only
);
226 return log_error_errno(r
, "Failed to import image: %m");
228 r
= sd_event_loop(event
);
230 return log_error_errno(r
, "Failed to run event loop: %m");
232 log_info("Exiting.");
236 static int help(int argc
, char *argv
[], void *userdata
) {
238 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
239 "Import container or virtual machine images.\n\n"
240 " -h --help Show this help\n"
241 " --version Show package version\n"
242 " --force Force creation of image\n"
243 " --image-root=PATH Image root directory\n"
244 " --read-only Create a read-only image\n\n"
246 " tar FILE [NAME] Import a TAR image\n"
247 " raw FILE [NAME] Import a RAW image\n",
248 program_invocation_short_name
);
253 static int parse_argv(int argc
, char *argv
[]) {
262 static const struct option options
[] = {
263 { "help", no_argument
, NULL
, 'h' },
264 { "version", no_argument
, NULL
, ARG_VERSION
},
265 { "force", no_argument
, NULL
, ARG_FORCE
},
266 { "image-root", required_argument
, NULL
, ARG_IMAGE_ROOT
},
267 { "read-only", no_argument
, NULL
, ARG_READ_ONLY
},
276 while ((c
= getopt_long(argc
, argv
, "h", options
, NULL
)) >= 0)
281 return help(0, NULL
, NULL
);
291 arg_image_root
= optarg
;
295 arg_read_only
= true;
302 assert_not_reached("Unhandled option");
308 static int import_main(int argc
, char *argv
[]) {
310 static const Verb verbs
[] = {
311 { "help", VERB_ANY
, VERB_ANY
, 0, help
},
312 { "tar", 2, 3, 0, import_tar
},
313 { "raw", 2, 3, 0, import_raw
},
317 return dispatch_verb(argc
, argv
, verbs
, NULL
);
320 int main(int argc
, char *argv
[]) {
323 setlocale(LC_ALL
, "");
324 log_parse_environment();
327 r
= parse_argv(argc
, argv
);
331 (void) ignore_signals(SIGPIPE
, -1);
333 r
= import_main(argc
, argv
);
336 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;