import-tar.c revision 0b452006de98294d1690f045f6ea2f7f6630ec3b
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/***
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2015 Lennart Poettering
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU Lesser General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2.1 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Lesser General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU Lesser General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen***/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <linux/fs.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-daemon.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-event.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "path-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "btrfs-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "copy.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "mkdir.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "rm-rf.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "ratelimit.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "machine-pool.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "qcow2-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "import-compress.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "import-common.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "import-tar.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "process-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstruct TarImport {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event *event;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char *image_root;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TarImportFinished on_finished;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char *local;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool force_local;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool read_only;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool grow_machine_directory;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char *temp_path;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char *final_path;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int input_fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int tar_fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen ImportCompress compress;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint64_t written_since_last_grow;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_source *input_event_source;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint8_t buffer[16*1024];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen size_t buffer_size;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint64_t written_compressed;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint64_t written_uncompressed;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct stat st;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen pid_t tar_pid;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unsigned last_percent;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen RateLimit progress_rate_limit;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen};
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel AndersenTarImport* tar_import_unref(TarImport *i) {
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen if (!i)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_source_unref(i->input_event_source);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->tar_pid > 1) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) kill_and_sigcont(i->tar_pid, SIGKILL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) wait_for_terminate(i->tar_pid, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->temp_path) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) rm_rf(i->temp_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen import_compress_free(&i->compress);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_unref(i->event);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen safe_close(i->tar_fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(i->final_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(i->image_root);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(i->local);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint tar_import_new(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TarImport **ret,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event *event,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *image_root,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TarImportFinished on_finished,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata) {
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl _cleanup_(tar_import_unrefp) TarImport *i = NULL;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl int r;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl assert(ret);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl i = new0(TarImport, 1);
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt if (!i)
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt return -ENOMEM;
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt i->input_fd = i->tar_fd = -1;
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt i->on_finished = on_finished;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl i->userdata = userdata;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl RATELIMIT_INIT(i->progress_rate_limit, 100 * USEC_PER_MSEC, 1);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl i->last_percent = (unsigned) -1;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl i->image_root = strdup(image_root ?: "/var/lib/machines");
b7e7184634d573fb73143210962acce205f37f61Michael Biebl if (!i->image_root)
b7e7184634d573fb73143210962acce205f37f61Michael Biebl return -ENOMEM;
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
b7e7184634d573fb73143210962acce205f37f61Michael Biebl
b7e7184634d573fb73143210962acce205f37f61Michael Biebl if (event)
b7e7184634d573fb73143210962acce205f37f61Michael Biebl i->event = sd_event_ref(event);
b7e7184634d573fb73143210962acce205f37f61Michael Biebl else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_default(&i->event);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
91e7bad45dced1cb2dfaac79337bb08d6e2b74a9Andreas Henriksson }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *ret = i;
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen i = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void tar_import_report_progress(TarImport *i) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unsigned percent;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* We have no size information, unless the source is a regular file */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!S_ISREG(i->st.st_mode))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen if (i->written_compressed >= (uint64_t) i->st.st_size)
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen percent = 100;
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen else
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (percent == i->last_percent)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!ratelimit_test(&i->progress_rate_limit))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt log_info("Imported %u%%.", percent);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt i->last_percent = percent;
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt}
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pittstatic int tar_import_finish(TarImport *i) {
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt int r;
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt assert(i->tar_fd >= 0);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt assert(i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i->final_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->tar_fd = safe_close(i->tar_fd);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
aad0a2c80097926757d4385e5f5492082d47f006Zbigniew Jędrzejewski-Szmek if (i->tar_pid > 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->tar_pid = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->read_only) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = import_make_read_only(i->temp_path);
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen if (r < 0)
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->force_local)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(r, "Failed to move image into place: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->temp_path = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
d171ed1c50ba64928b7fb30ee2ae729fdfe0826bThomas Hindoe Paaboel Andersenstatic int tar_import_fork_tar(TarImport *i) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(!i->final_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(!i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i->tar_fd < 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->final_path = strjoin(i->image_root, "/", i->local, NULL);
260ad50f5b4a9795032e3119c64f838a2d03370dThomas Hindoe Paaboel Andersen if (!i->final_path)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
31938a8560a664c32a9d72f1fc2d4347b232e6e9Michal Schmidt r = tempfn_random(i->final_path, &i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_oom();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (void) mkdir_parents_label(i->temp_path, 0700);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = btrfs_subvol_make(i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -ENOTTY) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (mkdir(i->temp_path, 0755) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return log_error_errno(errno, "Failed to create subvolume %s: %m", i->temp_path);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->tar_fd = import_fork_tar_x(i->temp_path, &i->tar_pid);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->tar_fd < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return i->tar_fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int tar_import_write(const void *p, size_t sz, void *userdata) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TarImport *i = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->grow_machine_directory && i->written_since_last_grow >= GROW_INTERVAL_BYTES) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->written_since_last_grow = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen grow_machine_directory();
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = loop_write(i->tar_fd, p, sz, false);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->written_uncompressed += sz;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->written_since_last_grow += sz;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int tar_import_process(TarImport *i) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen ssize_t l;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i->buffer_size < sizeof(i->buffer));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (l < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (errno == EAGAIN)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = log_error_errno(errno, "Failed to read input file: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto finish;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt if (l == 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Premature end of file: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = -EIO;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto finish;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = tar_import_finish(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto finish;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->buffer_size += l;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error("Failed to detect file compression: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto finish;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == 0) /* Need more data */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt r = tar_import_fork_tar(i);
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt if (r < 0)
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt goto finish;
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt }
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt r = import_uncompress(&i->compress, i->buffer, i->buffer_size, tar_import_write, i);
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen log_error_errno(r, "Failed to decode and write: %m");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto finish;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->written_compressed += i->buffer_size;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->buffer_size = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen tar_import_report_progress(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
29e0e6d8c1f7f648b7c998880d034eaa3e58c53aMartin Pitt return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenfinish:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->on_finished)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->on_finished(i, r, i->userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_exit(i->event, r);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int tar_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TarImport *i = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return tar_import_process(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int tar_import_on_defer(sd_event_source *s, void *userdata) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen TarImport *i = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return tar_import_process(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint tar_import_start(TarImport *i, int fd, const char *local, bool force_local, bool read_only) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(fd >= 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(local);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!machine_name_is_valid(local))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (i->input_fd >= 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EBUSY;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = fd_nonblock(fd, true);
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt if (r < 0)
77354c7e6f096a447245a8781c1eaa4acbe67089Martin Pitt return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = free_and_strdup(&i->local, local);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->force_local = force_local;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->read_only = read_only;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
79008bddf679a5e0900369950eb346c9fa687107Lennart Poettering if (fstat(fd, &i->st) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -errno;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, tar_import_on_input, i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -EPERM) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_add_defer(i->event, &i->input_event_source, tar_import_on_defer, i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen i->input_fd = fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen