b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering/***
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering This file is part of systemd.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering Copyright 2015 Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering systemd is free software; you can redistribute it and/or modify it
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering under the terms of the GNU Lesser General Public License as published by
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (at your option) any later version.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering systemd is distributed in the hope that it will be useful, but
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering Lesser General Public License for more details.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering You should have received a copy of the GNU Lesser General Public License
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering***/
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include <linux/fs.h>
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include "sd-daemon.h"
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include "sd-event.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "alloc-util.h"
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include "btrfs-util.h"
c8b3094de58e3b1e37d06f3d56c9346cffbe320aLennart Poettering#include "chattr-util.h"
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include "copy.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "fd-util.h"
0d39fa9c69b97a2ceb156053deef69c0866c2b97Lennart Poettering#include "fileio.h"
f4f15635ec05293ffcc83a5b39f624bbabbd8fd0Lennart Poettering#include "fs-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "hostname-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "import-common.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "import-compress.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "import-raw.h"
c004493cdefc1f43a3956ca529e8070f8d70be56Lennart Poettering#include "io-util.h"
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include "machine-pool.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "mkdir.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "path-util.h"
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#include "qcow2-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "ratelimit.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "rm-rf.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "string-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "util.h"
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstruct RawImport {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event *event;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering char *image_root;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RawImportFinished on_finished;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering void *userdata;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering char *local;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering bool force_local;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering bool read_only;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering bool grow_machine_directory;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering char *temp_path;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering char *final_path;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int input_fd;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int output_fd;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering ImportCompress compress;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering uint64_t written_since_last_grow;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event_source *input_event_source;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering uint8_t buffer[16*1024];
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering size_t buffer_size;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering uint64_t written_compressed;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering uint64_t written_uncompressed;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering struct stat st;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering unsigned last_percent;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RateLimit progress_rate_limit;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering};
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart PoetteringRawImport* raw_import_unref(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!i)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event_unref(i->event);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->temp_path) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (void) unlink(i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering free(i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering import_compress_free(&i->compress);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event_source_unref(i->input_event_source);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering safe_close(i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering free(i->final_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering free(i->image_root);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering free(i->local);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering free(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint raw_import_new(
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RawImport **ret,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event *event,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering const char *image_root,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RawImportFinished on_finished,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering void *userdata) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering _cleanup_(raw_import_unrefp) RawImport *i = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(ret);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i = new0(RawImport, 1);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!i)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -ENOMEM;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->input_fd = i->output_fd = -1;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->on_finished = on_finished;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->userdata = userdata;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering RATELIMIT_INIT(i->progress_rate_limit, 100 * USEC_PER_MSEC, 1);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->last_percent = (unsigned) -1;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->image_root = strdup(image_root ?: "/var/lib/machines");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!i->image_root)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -ENOMEM;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->grow_machine_directory = path_startswith(i->image_root, "/var/lib/machines");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (event)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->event = sd_event_ref(event);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering else {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = sd_event_default(&i->event);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering *ret = i;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic void raw_import_report_progress(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering unsigned percent;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* We have no size information, unless the source is a regular file */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!S_ISREG(i->st.st_mode))
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->written_compressed >= (uint64_t) i->st.st_size)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering percent = 100;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering else
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering percent = (unsigned) ((i->written_compressed * UINT64_C(100)) / (uint64_t) i->st.st_size);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (percent == i->last_percent)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!ratelimit_test(&i->progress_rate_limit))
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_notifyf(false, "X_IMPORT_PROGRESS=%u", percent);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering log_info("Imported %u%%.", percent);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->last_percent = percent;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_maybe_convert_qcow2(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering _cleanup_close_ int converted_fd = -1;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering _cleanup_free_ char *t = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = qcow2_detect(i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_error_errno(r, "Failed to detect whether this is a QCOW2 image: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r == 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* This is a QCOW2 image, let's convert it */
14bcf25c8b94b5c3556ba3983028a2b35ed0572fLennart Poettering r = tempfn_random(i->final_path, NULL, &t);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_oom();
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering converted_fd = open(t, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (converted_fd < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_error_errno(errno, "Failed to create %s: %m", t);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
1ed8f8c16da99551c6731764759878a0bc243fdeLennart Poettering r = chattr_fd(converted_fd, FS_NOCOW_FL, FS_NOCOW_FL);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
709f6e46a35ec492b70eb92943d82a8d838ce918Michal Schmidt log_warning_errno(r, "Failed to set file attributes on %s: %m", t);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering log_info("Unpacking QCOW2 file.");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = qcow2_convert(i->output_fd, converted_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering unlink(t);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_error_errno(r, "Failed to convert qcow2 image: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (void) unlink(i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering free(i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->temp_path = t;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering t = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering safe_close(i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->output_fd = converted_fd;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering converted_fd = -1;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 1;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_finish(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->output_fd >= 0);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->final_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* In case this was a sparse file, make sure the file system is right */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->written_uncompressed > 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (ftruncate(i->output_fd, i->written_uncompressed) < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_error_errno(errno, "Failed to truncate file: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = raw_import_maybe_convert_qcow2(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (S_ISREG(i->st.st_mode)) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (void) copy_times(i->input_fd, i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (void) copy_xattr(i->input_fd, i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->read_only) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = import_make_read_only_fd(i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering if (i->force_local)
d9e2daaf3d8649650cf9784b4fe9d9de4507da0cLennart Poettering (void) rm_rf(i->final_path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
f85ef957e647c5182acf5e64298f68e4b7fbfe8fAlban Crequy r = rename_noreplace(AT_FDCWD, i->temp_path, AT_FDCWD, i->final_path);
f85ef957e647c5182acf5e64298f68e4b7fbfe8fAlban Crequy if (r < 0)
f85ef957e647c5182acf5e64298f68e4b7fbfe8fAlban Crequy return log_error_errno(r, "Failed to move image into place: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
a1e58e8ee1c84b633d6d6d651d5328d4dd4eba5bLennart Poettering i->temp_path = mfree(i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_open_disk(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(!i->final_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(!i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->output_fd < 0);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->final_path = strjoin(i->image_root, "/", i->local, ".raw", NULL);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!i->final_path)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_oom();
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
14bcf25c8b94b5c3556ba3983028a2b35ed0572fLennart Poettering r = tempfn_random(i->final_path, NULL, &i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_oom();
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (void) mkdir_parents_label(i->temp_path, 0700);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->output_fd = open(i->temp_path, O_RDWR|O_CREAT|O_EXCL|O_NOCTTY|O_CLOEXEC, 0664);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->output_fd < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_error_errno(errno, "Failed to open destination %s: %m", i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
1ed8f8c16da99551c6731764759878a0bc243fdeLennart Poettering r = chattr_fd(i->output_fd, FS_NOCOW_FL, FS_NOCOW_FL);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
709f6e46a35ec492b70eb92943d82a8d838ce918Michal Schmidt log_warning_errno(r, "Failed to set file attributes on %s: %m", i->temp_path);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_try_reflink(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering off_t p;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->input_fd >= 0);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->output_fd >= 0);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->compress.type != IMPORT_COMPRESS_UNCOMPRESSED)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!S_ISREG(i->st.st_mode))
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering p = lseek(i->input_fd, 0, SEEK_CUR);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (p == (off_t) -1)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return log_error_errno(errno, "Failed to read file offset of input file: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* Let's only try a btrfs reflink, if we are reading from the beginning of the file */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if ((uint64_t) p != (uint64_t) i->buffer_size)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = btrfs_reflink(i->input_fd, i->output_fd);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r >= 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 1;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_write(const void *p, size_t sz, void *userdata) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RawImport *i = userdata;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering ssize_t n;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->grow_machine_directory && i->written_since_last_grow >= GROW_INTERVAL_BYTES) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->written_since_last_grow = 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering grow_machine_directory();
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering n = sparse_write(i->output_fd, p, sz, 64);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (n < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -errno;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if ((size_t) n < sz)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -EIO;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->written_uncompressed += sz;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->written_since_last_grow += sz;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_process(RawImport *i) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering ssize_t l;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i->buffer_size < sizeof(i->buffer));
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering l = read(i->input_fd, i->buffer + i->buffer_size, sizeof(i->buffer) - i->buffer_size);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (l < 0) {
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering if (errno == EAGAIN)
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering return 0;
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = log_error_errno(errno, "Failed to read input file: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (l == 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering log_error("Premature end of file: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = -EIO;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = raw_import_finish(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->buffer_size += l;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->compress.type == IMPORT_COMPRESS_UNKNOWN) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = import_uncompress_detect(&i->compress, i->buffer, i->buffer_size);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering log_error("Failed to detect file compression: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r == 0) /* Need more data */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = raw_import_open_disk(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = raw_import_try_reflink(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r > 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = raw_import_finish(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = import_uncompress(&i->compress, i->buffer, i->buffer_size, raw_import_write, i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering log_error_errno(r, "Failed to decode and write: %m");
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering goto finish;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->written_compressed += i->buffer_size;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->buffer_size = 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering raw_import_report_progress(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringfinish:
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->on_finished)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->on_finished(i, r, i->userdata);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering else
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event_exit(i->event, r);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return 0;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_on_input(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RawImport *i = userdata;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return raw_import_process(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int raw_import_on_defer(sd_event_source *s, void *userdata) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering RawImport *i = userdata;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return raw_import_process(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint raw_import_start(RawImport *i, int fd, const char *local, bool force_local, bool read_only) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering int r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(fd >= 0);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert(local);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (!machine_name_is_valid(local))
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -EINVAL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (i->input_fd >= 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -EBUSY;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering r = fd_nonblock(fd, true);
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering if (r < 0)
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering return r;
587fec427c80b6c34dcf1d7570f891fcb652a7c5Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = free_and_strdup(&i->local, local);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->force_local = force_local;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->read_only = read_only;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (fstat(fd, &i->st) < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return -errno;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = sd_event_add_io(i->event, &i->input_event_source, fd, EPOLLIN, raw_import_on_input, i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r == -EPERM) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* This fd does not support epoll, for example because it is a regular file. Busy read in that case */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = sd_event_add_defer(i->event, &i->input_event_source, raw_import_on_defer, i);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = sd_event_source_set_enabled(i->input_event_source, SD_EVENT_ON);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering }
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (r < 0)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering i->input_fd = fd;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return r;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering}