1 /* SPDX-License-Identifier: LGPL-2.1+ */
8 #include "alloc-util.h"
11 #include "hostname-util.h"
12 #include "import-raw.h"
13 #include "import-tar.h"
14 #include "import-util.h"
15 #include "machine-image.h"
16 #include "main-func.h"
17 #include "signal-util.h"
18 #include "string-util.h"
21 static bool arg_force
= false;
22 static bool arg_read_only
= false;
23 static const char *arg_image_root
= "/var/lib/machines";
25 static int interrupt_signal_handler(sd_event_source
*s
, const struct signalfd_siginfo
*si
, void *userdata
) {
26 log_notice("Transfer aborted.");
27 sd_event_exit(sd_event_source_get_event(s
), EINTR
);
31 static void on_tar_finished(TarImport
*import
, int error
, void *userdata
) {
32 sd_event
*event
= userdata
;
36 log_info("Operation completed successfully.");
38 sd_event_exit(event
, abs(error
));
41 static int import_tar(int argc
, char *argv
[], void *userdata
) {
42 _cleanup_(tar_import_unrefp
) TarImport
*import
= NULL
;
43 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
44 const char *path
= NULL
, *local
= NULL
;
45 _cleanup_free_
char *ll
= NULL
;
46 _cleanup_close_
int open_fd
= -1;
51 if (isempty(path
) || streq(path
, "-"))
57 local
= basename(path
);
58 if (isempty(local
) || streq(local
, "-"))
62 r
= tar_strip_suffixes(local
, &ll
);
68 if (!machine_name_is_valid(local
)) {
69 log_error("Local image name '%s' is not valid.", local
);
74 r
= image_find(IMAGE_MACHINE
, local
, NULL
);
77 return log_error_errno(r
, "Failed to check whether image '%s' exists: %m", local
);
79 log_error("Image '%s' already exists.", local
);
87 open_fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
89 return log_error_errno(errno
, "Failed to open tar image to import: %m");
93 log_info("Importing '%s', saving as '%s'.", path
, local
);
95 _cleanup_free_
char *pretty
= NULL
;
99 (void) fd_get_path(fd
, &pretty
);
100 log_info("Importing '%s', saving as '%s'.", strna(pretty
), local
);
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
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
108 (void) sd_event_add_signal(event
, NULL
, SIGTERM
, interrupt_signal_handler
, NULL
);
109 (void) sd_event_add_signal(event
, NULL
, SIGINT
, interrupt_signal_handler
, NULL
);
111 r
= tar_import_new(&import
, event
, arg_image_root
, on_tar_finished
, event
);
113 return log_error_errno(r
, "Failed to allocate importer: %m");
115 r
= tar_import_start(import
, fd
, local
, arg_force
, arg_read_only
);
117 return log_error_errno(r
, "Failed to import image: %m");
119 r
= sd_event_loop(event
);
121 return log_error_errno(r
, "Failed to run event loop: %m");
123 log_info("Exiting.");
127 static void on_raw_finished(RawImport
*import
, int error
, void *userdata
) {
128 sd_event
*event
= userdata
;
132 log_info("Operation completed successfully.");
134 sd_event_exit(event
, abs(error
));
137 static int import_raw(int argc
, char *argv
[], void *userdata
) {
138 _cleanup_(raw_import_unrefp
) RawImport
*import
= NULL
;
139 _cleanup_(sd_event_unrefp
) sd_event
*event
= NULL
;
140 const char *path
= NULL
, *local
= NULL
;
141 _cleanup_free_
char *ll
= NULL
;
142 _cleanup_close_
int open_fd
= -1;
147 if (isempty(path
) || streq(path
, "-"))
153 local
= basename(path
);
154 if (isempty(local
) || streq(local
, "-"))
158 r
= raw_strip_suffixes(local
, &ll
);
164 if (!machine_name_is_valid(local
)) {
165 log_error("Local image name '%s' is not valid.", local
);
170 r
= image_find(IMAGE_MACHINE
, local
, NULL
);
173 return log_error_errno(r
, "Failed to check whether image '%s' exists: %m", local
);
175 log_error("Image '%s' already exists.", local
);
183 open_fd
= open(path
, O_RDONLY
|O_CLOEXEC
|O_NOCTTY
);
185 return log_error_errno(errno
, "Failed to open raw image to import: %m");
189 log_info("Importing '%s', saving as '%s'.", path
, local
);
191 _cleanup_free_
char *pretty
= NULL
;
195 (void) fd_get_path(fd
, &pretty
);
196 log_info("Importing '%s', saving as '%s'.", strempty(pretty
), local
);
199 r
= sd_event_default(&event
);
201 return log_error_errno(r
, "Failed to allocate event loop: %m");
203 assert_se(sigprocmask_many(SIG_BLOCK
, NULL
, SIGTERM
, SIGINT
, -1) >= 0);
204 (void) sd_event_add_signal(event
, NULL
, SIGTERM
, interrupt_signal_handler
, NULL
);
205 (void) sd_event_add_signal(event
, NULL
, SIGINT
, interrupt_signal_handler
, NULL
);
207 r
= raw_import_new(&import
, event
, arg_image_root
, on_raw_finished
, event
);
209 return log_error_errno(r
, "Failed to allocate importer: %m");
211 r
= raw_import_start(import
, fd
, local
, arg_force
, arg_read_only
);
213 return log_error_errno(r
, "Failed to import image: %m");
215 r
= sd_event_loop(event
);
217 return log_error_errno(r
, "Failed to run event loop: %m");
219 log_info("Exiting.");
223 static int help(int argc
, char *argv
[], void *userdata
) {
225 printf("%s [OPTIONS...] {COMMAND} ...\n\n"
226 "Import container or virtual machine images.\n\n"
227 " -h --help Show this help\n"
228 " --version Show package version\n"
229 " --force Force creation of image\n"
230 " --image-root=PATH Image root directory\n"
231 " --read-only Create a read-only image\n\n"
233 " tar FILE [NAME] Import a TAR image\n"
234 " raw FILE [NAME] Import a RAW image\n",
235 program_invocation_short_name
);
240 static int parse_argv(int argc
, char *argv
[]) {
249 static const struct option options
[] = {
250 { "help", no_argument
, NULL
, 'h' },
251 { "version", no_argument
, NULL
, ARG_VERSION
},
252 { "force", no_argument
, NULL
, ARG_FORCE
},
253 { "image-root", required_argument
, NULL
, ARG_IMAGE_ROOT
},
254 { "read-only", no_argument
, NULL
, ARG_READ_ONLY
},
263 while ((c
= getopt_long(argc
, argv
, "h", options
, NULL
)) >= 0)
268 return help(0, NULL
, NULL
);
278 arg_image_root
= optarg
;
282 arg_read_only
= true;
289 assert_not_reached("Unhandled option");
295 static int import_main(int argc
, char *argv
[]) {
296 static const Verb verbs
[] = {
297 { "help", VERB_ANY
, VERB_ANY
, 0, help
},
298 { "tar", 2, 3, 0, import_tar
},
299 { "raw", 2, 3, 0, import_raw
},
303 return dispatch_verb(argc
, argv
, verbs
, NULL
);
306 static int run(int argc
, char *argv
[]) {
309 setlocale(LC_ALL
, "");
310 log_parse_environment();
313 r
= parse_argv(argc
, argv
);
317 (void) ignore_signals(SIGPIPE
, -1);
319 return import_main(argc
, argv
);
322 DEFINE_MAIN_FUNCTION(run
);