import-tar.c revision b6e676ce41508e2aeea22202fc8f234126177f52
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye/***
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye This file is part of systemd.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye Copyright 2015 Lennart Poettering
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye systemd is free software; you can redistribute it and/or modify it
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye under the terms of the GNU Lesser General Public License as published by
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye the Free Software Foundation; either version 2.1 of the License, or
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye (at your option) any later version.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye systemd is distributed in the hope that it will be useful, but
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye WITHOUT ANY WARRANTY; without even the implied warranty of
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye Lesser General Public License for more details.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye You should have received a copy of the GNU Lesser General Public License
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye along with systemd; If not, see <http://www.gnu.org/licenses/>.
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye***/
fe80b749cd764b1f0f72b2f913b1fe10581911c3Knut Anders Hatlen
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include <linux/fs.h>
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
cf1f7b5e81583dfca30972cfef322266a6928e7fKnut Anders Hatlen#include "sd-daemon.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "sd-event.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "path-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "btrfs-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "copy.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "mkdir.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "ratelimit.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "machine-pool.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "qcow2-util.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "import-compress.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "import-common.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye#include "import-tar.h"
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbyestruct TarImport {
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye sd_event *event;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye char *image_root;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye TarImportFinished on_finished;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye void *userdata;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye char *local;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye bool force_local;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye bool read_only;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye bool grow_machine_directory;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye char *temp_path;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye char *final_path;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye int input_fd;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye int tar_fd;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye ImportCompress compress;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye uint64_t written_since_last_grow;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye sd_event_source *input_event_source;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye uint8_t buffer[16*1024];
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye size_t buffer_size;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye uint64_t written_compressed;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye uint64_t written_uncompressed;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye struct stat st;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye pid_t tar_pid;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye unsigned last_percent;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye RateLimit progress_rate_limit;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye};
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond NorbyeTarImport* tar_import_unref(TarImport *i) {
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye if (!i)
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye return NULL;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye sd_event_unref(i->event);
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye if (i->tar_pid > 1) {
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye (void) kill_and_sigcont(i->tar_pid, SIGKILL);
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye (void) wait_for_terminate(i->tar_pid, NULL);
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye }
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye if (i->temp_path) {
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen (void) btrfs_subvol_remove(i->temp_path);
fe80b749cd764b1f0f72b2f913b1fe10581911c3Knut Anders Hatlen (void) rm_rf_dangerous(i->temp_path, false, true, false);
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen free(i->temp_path);
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik }
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik import_compress_free(&i->compress);
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco sd_event_source_unref(i->input_event_source);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik safe_close(i->tar_fd);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen free(i->final_path);
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen free(i->image_root);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik free(i->local);
780cc7d1b57609ff15fb283201e93cb501ebe9e6Jorgen Austvik free(i);
7b9f9a1761f76744fc3772181877d5e301f122adKnut Anders Hatlen
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco return NULL;
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlen}
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlen
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlenint tar_import_new(
0466de7c67573e1ce5e0733325c1e5383270f5d5Knut Anders Hatlen TarImport **ret,
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco sd_event *event,
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco const char *image_root,
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco TarImportFinished on_finished,
1ed6b730409d4740e941142599767d5eac7e7d92Lubos Kosco void *userdata) {
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik _cleanup_(tar_import_unrefp) TarImport *i = NULL;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik int r;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco assert(ret);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik i = new0(TarImport, 1);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (!i)
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik return -ENOMEM;
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik i->input_fd = i->tar_fd = -1;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik i->on_finished = on_finished;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik i->userdata = userdata;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik RATELIMIT_INIT(i->progress_rate_limit, 500 * USEC_PER_MSEC, 1);
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco i->last_percent = (unsigned) -1;
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik
49f592091468eac515dde6139fbc8efa26056b0aJorgen Austvik i->image_root = strdup(image_root ?: "/var/lib/machines");
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik if (!i->image_root)
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik return -ENOMEM;
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik
945f4c3c36a15447913781dfb1894b34f2941c57Jorgen Austvik if (event)
1ed6b730409d4740e941142599767d5eac7e7d92Lubos Kosco i->event = sd_event_ref(event);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik else {
1ed6b730409d4740e941142599767d5eac7e7d92Lubos Kosco r = sd_event_default(&i->event);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (r < 0)
4d93e73b35c5009898b59c9bd7e6629ac5942c2cLubos Kosco return r;
4d93e73b35c5009898b59c9bd7e6629ac5942c2cLubos Kosco }
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco *ret = i;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco i = NULL;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco return 0;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco}
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Koscostatic void tar_import_report_progress(TarImport *i) {
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco unsigned percent;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco assert(i);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
45909b3ef8c6e568a87482cb890fec7b5dbb7733Lubos Kosco /* We have no size information, unless the source is a regular file */
45909b3ef8c6e568a87482cb890fec7b5dbb7733Lubos Kosco if (!S_ISREG(i->st.st_mode))
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco return;
fcb68bae47907ba23c545e379c81c3ee6e19f778Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco if (i->written_compressed >= (uint64_t) i->st.st_size)
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco percent = 100;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco else
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco if (percent == i->last_percent)
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco return;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco if (!ratelimit_test(&i->progress_rate_limit))
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco return;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco log_info("Imported %u%%.", percent);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco i->last_percent = percent;
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye}
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbyestatic int tar_import_finish(TarImport *i) {
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen int r;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen assert(i);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen assert(i->tar_fd >= 0);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen assert(i->temp_path);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen assert(i->final_path);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye i->tar_fd = safe_close(i->tar_fd);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
3d35131df8607ae05b064219b9448afc5c4b550aKnut Anders Hatlen if (i->tar_pid > 0) {
3d35131df8607ae05b064219b9448afc5c4b550aKnut Anders Hatlen r = wait_for_terminate_and_warn("tar", i->tar_pid, true);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye i->tar_pid = 0;
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye if (r < 0)
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye return r;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen }
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen if (i->read_only) {
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen r = import_make_read_only(i->temp_path);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen if (r < 0)
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen return r;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen }
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen if (i->force_local) {
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen (void) btrfs_subvol_remove(i->final_path);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen (void) rm_rf_dangerous(i->final_path, false, true, false);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen }
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen if (renameat2(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path, RENAME_NOREPLACE) < 0)
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen return log_error_errno(errno, "Failed to move image into place: %m");
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen free(i->temp_path);
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen i->temp_path = NULL;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen return 0;
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen}
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlenstatic int tar_import_fork_tar(TarImport *i) {
a5cc1506d5c0704805c6733a46c7f1f8f91ae724Knut Anders Hatlen int r;
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye assert(i);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye assert(!i->final_path);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye assert(!i->temp_path);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye assert(i->tar_fd < 0);
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbye i->final_path = strjoin(i->image_root, "/", i->local, NULL);
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik if (!i->final_path)
d3aa2b921c67d952f62c82503575ea545e274d69Knut Anders Hatlen return log_oom();
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco r = tempfn_random(i->final_path, &i->temp_path);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (r < 0)
2e3c025fdd5908a27cc82eb1d5346368a8be4e0dJorgen Austvik return log_oom();
d3d2404f9a49bf70b124053feabe666f85ef5361Knut Anders Hatlen
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye (void) mkdir_parents_label(i->temp_path, 0700);
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen r = btrfs_subvol_make(i->temp_path);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (r == -ENOTTY) {
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (mkdir(i->temp_path, 0755) < 0)
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen return log_error_errno(errno, "Failed to create directory %s: %m", i->temp_path);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen } else if (r < 0)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return log_error_errno(errno, "Failed to create subvolume %s: %m", i->temp_path);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen i->tar_fd = import_fork_tar(i->temp_path, &i->tar_pid);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (i->tar_fd < 0)
5a0c5ad4116f5a4dd0dd5a0a4e6d02973cd5eef9Lubos Kosco return i->tar_fd;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return 0;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen}
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlenstatic int tar_import_write(const void *p, size_t sz, void *userdata) {
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen TarImport *i = userdata;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen int r;
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen if (i->grow_machine_directory && i->written_since_last_grow >= GROW_INTERVAL_BYTES) {
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen i->written_since_last_grow = 0;
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen grow_machine_directory();
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen }
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen r = loop_write(i->tar_fd, p, sz, false);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (r < 0)
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return r;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen i->written_uncompressed += sz;
f53d230f3e516218f38a7f1f2866e42bb3e0290eKnut Anders Hatlen i->written_since_last_grow += sz;
752fbd3cf33aada419c8258959ff5574d2d2047dTrond Norbye
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen return 0;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen}
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
7b046969a1b2565787df8ae3a8126359e8cd6fafTrond Norbyestatic int tar_import_process(TarImport *i) {
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen ssize_t l;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen int r;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen assert(i);
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen assert(i->buffer_size < sizeof(i->buffer));
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size);
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen if (l < 0) {
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen r = log_error_errno(errno, "Failed to read input file: %m");
9661674ed58ba62a40e43d1a4b38d5e77c3c6545Knut Anders Hatlen goto finish;
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen }
2dbc1835e0ae88ad102e2b9a85e5c7b5298b14b6Knut Anders Hatlen if (l == 0) {
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen log_error("Premature end of file: %m");
64b763950bf11e9357facbd2b5666631a895c085Trond Norbye r = -EIO;
9cf297d9a579835e9336d587eaee187ca0954767Knut Anders Hatlen goto finish;
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco }
2c2a50fade805afbf4a5a880a38648613d7e01aeLubos Kosco
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye r = tar_import_finish(i);
20a0bde399487a651cdeb66fc8b44b2212036355Trond Norbye goto finish;
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye }
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye i->buffer_size += l;
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye if (r < 0) {
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye log_error("Failed to detect file compression: %m");
523201f786f6b12b7cf54091c6e5be167878cbeeTrond Norbye goto finish;
c0550b01024b910b8c1468811c0ea663b10b1372Trond Norbye }
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen if (r == 0) /* Need more data */
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen return 0;
e4d314d81209a23aae928ed62128ad9128c115bdLubos Kosco
c67bbf00f725074786ac47867d2276e7b935b570Trond Norbye r = tar_import_fork_tar(i);
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen if (r < 0)
e4d314d81209a23aae928ed62128ad9128c115bdLubos Kosco goto finish;
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen }
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen
0a0811923cbbd2976425db6f4c78eed811c2825bKnut Anders Hatlen r = import_uncompress(&i->compress, i->buffer, i->buffer_size, tar_import_write, i);
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen if (r < 0) {
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen log_error_errno(r, "Failed to decode and write: %m");
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen goto finish;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen }
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen i->written_compressed += i->buffer_size;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen i->buffer_size = 0;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco tar_import_report_progress(i);
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco
b34561d2c3d92fac37dbced05ba6a8738e3d20e9Lubos Kosco return 0;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlenfinish:
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco if (i->on_finished)
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco i->on_finished(i, r, i->userdata);
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco else
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco sd_event_exit(i->event, r);
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Kosco return 0;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen}
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
5e6c91d7e77062129cd0b6ac8aaa546dff216419Lubos Koscostatic int tar_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen TarImport *i = userdata;
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen return tar_import_process(i);
dce551c28e0e9e0a652e512c1094caef574916ceKnut Anders Hatlen}
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Koscostatic int tar_import_on_defer(sd_event_source *s, void *userdata) {
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco TarImport *i = userdata;
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen return tar_import_process(i);
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen}
a07b2874263e3c5f0cd2e83441719415d53059c2Knut Anders Hatlen
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlenint tar_import_start(TarImport *i, int fd, const char *local, bool force_local, bool read_only) {
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen int r;
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen assert(i);
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen assert(fd >= 0);
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen assert(local);
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco
a7f25b0d188e4ea80ddcabf3ac52ade1bdb4ebecLubos Kosco if (!machine_name_is_valid(local))
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen return -EINVAL;
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen
edcb01bf549171673fd0bb4239f2edfc7a810397Knut Anders Hatlen if (i->input_fd >= 0)
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik return -EBUSY;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik r = free_and_strdup(&i->local, local);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (r < 0)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik return r;
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik i->force_local = force_local;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik i->read_only = read_only;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (fstat(fd, &i->st) < 0)
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik return -errno;
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, tar_import_on_input, i);
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik if (r == -EPERM) {
52cf1d63b1f1b231ff1e86eca2058d88560579b5Lubos Kosco /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik r = sd_event_add_defer(i->event, &i->input_event_source, tar_import_on_defer, i);
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik if (r < 0)
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik return r;
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik
7ecd52b03dc1f0b03ff8f522b4891c8531896c3dJorgen Austvik r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON);
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik }
c7eb123c8b2081a261deff3c401fbf92ddba1b58Jorgen Austvik if (r < 0)
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik return r;
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik i->input_fd = fd;
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik return r;
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik}
85e0595857351c6e22f75b8928967d14cb679ac5Jorgen Austvik