import.c revision 25300b5a1fcf54674a69d0f4ab08925be00b0227
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers/***
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers This file is part of systemd.
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers Copyright 2015 Lennart Poettering
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers systemd is free software; you can redistribute it and/or modify it
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers under the terms of the GNU Lesser General Public License as published by
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers the Free Software Foundation; either version 2.1 of the License, or
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers (at your option) any later version.
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers systemd is distributed in the hope that it will be useful, but
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers Lesser General Public License for more details.
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers You should have received a copy of the GNU Lesser General Public License
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers***/
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include <getopt.h>
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "sd-event.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "event-util.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "verbs.h"
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers#include "build.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "signal-util.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "hostname-util.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "machine-image.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "import-util.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "import-tar.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers#include "import-raw.h"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sieversstatic bool arg_force = false;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sieversstatic bool arg_read_only = false;
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnasstatic const char *arg_image_root = "/var/lib/machines";
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sieversstatic int interrupt_signal_handler(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_notice("Transfer aborted.");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers sd_event_exit(sd_event_source_get_event(s), EINTR);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return 0;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers}
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sieversstatic void on_tar_finished(TarImport *import, int error, void *userdata) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers sd_event *event = userdata;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers assert(import);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (error == 0)
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers log_info("Operation completed successfully.");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers sd_event_exit(event, abs(error));
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers}
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sieversstatic int import_tar(int argc, char *argv[], void *userdata) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers _cleanup_(tar_import_unrefp) TarImport *import = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers _cleanup_event_unref_ sd_event *event = NULL;
09d8f5d757515122d7b726218e249621e564157cKay Sievers const char *path = NULL, *local = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers _cleanup_free_ char *ll = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers _cleanup_close_ int open_fd = -1;
09d8f5d757515122d7b726218e249621e564157cKay Sievers int r, fd;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (argc >= 2)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers path = argv[1];
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (isempty(path) || streq(path, "-"))
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers path = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (argc >= 3)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = argv[2];
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers else if (path)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = basename(path);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (isempty(local) || streq(local, "-"))
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = NULL;
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (local) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = tar_strip_suffixes(local, &ll);
09d8f5d757515122d7b726218e249621e564157cKay Sievers if (r < 0)
09d8f5d757515122d7b726218e249621e564157cKay Sievers return log_oom();
09d8f5d757515122d7b726218e249621e564157cKay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = ll;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (!machine_name_is_valid(local)) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_error("Local image name '%s' is not valid.", local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return -EINVAL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (!arg_force) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = image_find(local, NULL);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers else if (r > 0) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_error_errno(EEXIST, "Image '%s' already exists.", local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return -EEXIST;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers } else
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = "imported";
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (path) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (open_fd < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(errno, "Failed to open tar image to import: %m");
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas fd = open_fd;
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers log_info("Importing '%s', saving as '%s'.", path, local);
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers } else {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers _cleanup_free_ char *pretty = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers fd = STDIN_FILENO;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers (void) readlink_malloc("/proc/self/fd/0", &pretty);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_info("Importing '%s', saving as '%s'.", strna(pretty), local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = sd_event_default(&event);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(r, "Failed to allocate event loop: %m");
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = tar_import_new(&import, event, arg_image_root, on_tar_finished, event);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(r, "Failed to allocate importer: %m");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = tar_import_start(import, fd, local, arg_force, arg_read_only);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers return log_error_errno(r, "Failed to import image: %m");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = sd_event_loop(event);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(r, "Failed to run event loop: %m");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_info("Exiting.");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return -r;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers}
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sieversstatic void on_raw_finished(RawImport *import, int error, void *userdata) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers sd_event *event = userdata;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers assert(import);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (error == 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_info("Operation completed successfully.");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers sd_event_exit(event, abs(error));
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers}
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sieversstatic int import_raw(int argc, char *argv[], void *userdata) {
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas _cleanup_(raw_import_unrefp) RawImport *import = NULL;
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas _cleanup_event_unref_ sd_event *event = NULL;
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers const char *path = NULL, *local = NULL;
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers _cleanup_free_ char *ll = NULL;
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers _cleanup_close_ int open_fd = -1;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers int r, fd;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (argc >= 2)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers path = argv[1];
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (isempty(path) || streq(path, "-"))
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers path = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (argc >= 3)
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers local = argv[2];
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers else if (path)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = basename(path);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (isempty(local) || streq(local, "-"))
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = NULL;
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (local) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = raw_strip_suffixes(local, &ll);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_oom();
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = ll;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (!machine_name_is_valid(local)) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_error("Local image name '%s' is not valid.", local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return -EINVAL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (!arg_force) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = image_find(local, NULL);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (r < 0)
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers else if (r > 0) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_error_errno(EEXIST, "Image '%s' already exists.", local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return -EEXIST;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers }
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers } else
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers local = "imported";
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (path) {
c35ddc5b69ef1911de39933329eda0b569cae4b9Kay Sievers open_fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers if (open_fd < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(errno, "Failed to open raw image to import: %m");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers fd = open_fd;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers log_info("Importing '%s', saving as '%s'.", path, local);
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers } else {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers _cleanup_free_ char *pretty = NULL;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas fd = STDIN_FILENO;
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas
796b06c21b62d13c9021e2fbd9c58a5c6edb2764Kay Sievers (void) readlink_malloc("/proc/self/fd/0", &pretty);
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers log_info("Importing '%s', saving as '%s'.", pretty, local);
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers }
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen r = sd_event_default(&event);
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen if (r < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(r, "Failed to allocate event loop: %m");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers assert_se(sigprocmask_many(SIG_BLOCK, NULL, SIGTERM, SIGINT, -1) >= 0);
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers (void) sd_event_add_signal(event, NULL, SIGTERM, interrupt_signal_handler, NULL);
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers (void) sd_event_add_signal(event, NULL, SIGINT, interrupt_signal_handler, NULL);
378cf88f72a9cda84baf703ed24f54c8c539fdcfKay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = raw_import_new(&import, event, arg_image_root, on_raw_finished, event);
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen if (r < 0)
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return log_error_errno(r, "Failed to allocate importer: %m");
f2f1861383c5cf4c07a7c6098d7c0b7134f06d51Kay Sievers
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers r = raw_import_start(import, fd, local, arg_force, arg_read_only);
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen if (r < 0)
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen return log_error_errno(r, "Failed to import image: %m");
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen r = sd_event_loop(event);
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen if (r < 0)
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen return log_error_errno(r, "Failed to run event loop: %m");
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen log_info("Exiting.");
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers return -r;
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers}
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersenstatic int help(int argc, char *argv[], void *userdata) {
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen printf("%s [OPTIONS...] {COMMAND} ...\n\n"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers "Import container or virtual machine images.\n\n"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers " -h --help Show this help\n"
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers " --version Show package version\n"
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas " --force Force creation of image\n"
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen " --image-root=PATH Image root directory\n"
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen " --read-only Create a read-only image\n\n"
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen "Commands:\n"
f2f1861383c5cf4c07a7c6098d7c0b7134f06d51Kay Sievers " tar FILE [NAME] Import a TAR image\n"
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen " raw FILE [NAME] Import a RAW image\n",
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen program_invocation_short_name);
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen return 0;
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen}
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersenstatic int parse_argv(int argc, char *argv[]) {
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen enum {
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen ARG_VERSION = 0x100,
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen ARG_FORCE,
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen ARG_IMAGE_ROOT,
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen ARG_READ_ONLY,
5fe25affc01fb003a3a66937458a25640a6075ceTom Gundersen };
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas
f9cd22249dbdcebe2ab54eea56c0b32e2a1c2ce5Mantas Mikulėnas static const struct option options[] = {
448004c340d41f1b7eb3c06cbd694b8862e6524dKay Sievers { "help", no_argument, NULL, 'h' },
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers { "version", no_argument, NULL, ARG_VERSION },
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers { "force", no_argument, NULL, ARG_FORCE },
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers { "image-root", required_argument, NULL, ARG_IMAGE_ROOT },
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers { "read-only", no_argument, NULL, ARG_READ_ONLY },
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers {}
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers };
8db6dcfd3c3d19d35767f04884a99368f6c64b36Kay Sievers
cf7ebcea78223b95b2676b97e1d2aad16caa3c86Kay Sievers int c;
assert(argc >= 0);
assert(argv);
while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
switch (c) {
case 'h':
return help(0, NULL, NULL);
case ARG_VERSION:
puts(PACKAGE_STRING);
puts(SYSTEMD_FEATURES);
return 0;
case ARG_FORCE:
arg_force = true;
break;
case ARG_IMAGE_ROOT:
arg_image_root = optarg;
break;
case ARG_READ_ONLY:
arg_read_only = true;
break;
case '?':
return -EINVAL;
default:
assert_not_reached("Unhandled option");
}
return 1;
}
static int import_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "help", VERB_ANY, VERB_ANY, 0, help },
{ "tar", 2, 3, 0, import_tar },
{ "raw", 2, 3, 0, import_raw },
{}
};
return dispatch_verb(argc, argv, verbs, NULL);
}
int main(int argc, char *argv[]) {
int r;
setlocale(LC_ALL, "");
log_parse_environment();
log_open();
r = parse_argv(argc, argv);
if (r <= 0)
goto finish;
(void) ignore_signals(SIGPIPE, -1);
r = import_main(argc, argv);
finish:
return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
}