#include "bus-get-properties.h"
#include "bus-log-control-api.h"
#include "bus-polkit.h"
-#include "def.h"
+#include "constants.h"
#include "env-util.h"
#include "fd-util.h"
#include "float.h"
#include "machine-pool.h"
#include "main-func.h"
#include "missing_capability.h"
-#include "mkdir.h"
+#include "mkdir-label.h"
#include "parse-util.h"
#include "path-util.h"
#include "percent-util.h"
#include "strv.h"
#include "syslog-util.h"
#include "user-util.h"
-#include "util.h"
#include "web-util.h"
typedef struct Transfer Transfer;
int notify_fd;
sd_event_source *notify_event_source;
+
+ bool use_btrfs_subvol;
+ bool use_btrfs_quota;
};
#define TRANSFERS_MAX 64
free(t->format);
free(t->object_path);
- if (t->pid > 0) {
- (void) kill_and_sigcont(t->pid, SIGKILL);
- (void) wait_for_terminate(t->pid, NULL);
- }
+ if (t->pid > 1)
+ sigkill_wait(t->pid);
safe_close(t->log_fd);
safe_close(t->stdin_fd);
*t = (Transfer) {
.type = _TRANSFER_TYPE_INVALID,
- .log_fd = -1,
- .stdin_fd = -1,
- .stdout_fd = -1,
+ .log_fd = -EBADF,
+ .stdin_fd = -EBADF,
+ .stdout_fd = -EBADF,
.verify = _IMPORT_VERIFY_INVALID,
.progress_percent= UINT_MAX,
};
}
static int transfer_on_pid(sd_event_source *s, const siginfo_t *si, void *userdata) {
- Transfer *t = userdata;
+ Transfer *t = ASSERT_PTR(userdata);
bool success = false;
assert(s);
- assert(t);
if (si->si_code == CLD_EXITED) {
if (si->si_status != 0)
}
static int transfer_on_log(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
- Transfer *t = userdata;
+ Transfer *t = ASSERT_PTR(userdata);
ssize_t l;
assert(s);
- assert(t);
l = read(fd, t->log_message + t->log_message_size, sizeof(t->log_message) - t->log_message_size);
if (l < 0)
}
static int transfer_start(Transfer *t) {
- _cleanup_close_pair_ int pipefd[2] = { -1, -1 };
+ _cleanup_close_pair_ int pipefd[2] = PIPE_EBADF;
int r;
assert(t);
pipefd[0] = safe_close(pipefd[0]);
- r = rearrange_stdio(t->stdin_fd,
- t->stdout_fd < 0 ? pipefd[1] : t->stdout_fd,
+ r = rearrange_stdio(TAKE_FD(t->stdin_fd),
+ t->stdout_fd < 0 ? pipefd[1] : TAKE_FD(t->stdout_fd),
pipefd[1]);
+ TAKE_FD(pipefd[1]);
if (r < 0) {
log_error_errno(r, "Failed to set stdin/stdout/stderr: %m");
_exit(EXIT_FAILURE);
break;
default:
- assert_not_reached("Unexpected transfer type");
+ assert_not_reached();
}
switch (t->type) {
int r;
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
- if (IN_SET(n, -EAGAIN, -EINTR))
- return 0;
- if (n < 0)
+ if (n < 0) {
+ if (ERRNO_IS_TRANSIENT(n))
+ return 0;
return (int) n;
+ }
cmsg_close_all(&msghdr);
assert(ret);
- m = new0(Manager, 1);
+ m = new(Manager, 1);
if (!m)
return -ENOMEM;
+ *m = (Manager) {
+ .use_btrfs_subvol = true,
+ .use_btrfs_quota = true,
+ };
+
r = sd_event_default(&m->event);
if (r < 0)
return r;
_cleanup_(transfer_unrefp) Transfer *t = NULL;
int fd, force, read_only, r;
const char *local, *object;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
TransferType type;
struct stat st;
uint32_t id;
assert(msg);
- assert(m);
r = bus_verify_polkit_async(
msg,
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Local name %s is invalid", local);
- r = setup_machine_directory(error);
+ r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
if (r < 0)
return r;
_cleanup_(transfer_unrefp) Transfer *t = NULL;
int fd, force, read_only, r;
const char *local, *object;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
uint32_t id;
assert(msg);
- assert(m);
r = bus_verify_polkit_async(
msg,
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Local name %s is invalid", local);
- r = setup_machine_directory(error);
+ r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
if (r < 0)
return r;
_cleanup_(transfer_unrefp) Transfer *t = NULL;
int fd, r;
const char *local, *object, *format;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
TransferType type;
struct stat st;
uint32_t id;
assert(msg);
- assert(m);
r = bus_verify_polkit_async(
msg,
static int method_pull_tar_or_raw(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(transfer_unrefp) Transfer *t = NULL;
const char *remote, *local, *verify, *object;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
ImportVerify v;
TransferType type;
int force, r;
uint32_t id;
assert(msg);
- assert(m);
r = bus_verify_polkit_async(
msg,
if (r < 0)
return r;
- if (!http_url_is_valid(remote))
+ if (!http_url_is_valid(remote) && !file_url_is_valid(remote))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"URL %s is invalid", remote);
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Unknown verification mode %s", verify);
- r = setup_machine_directory(error);
+ r = setup_machine_directory(error, m->use_btrfs_subvol, m->use_btrfs_quota);
if (r < 0)
return r;
static int method_list_transfers(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
Transfer *t;
int r;
assert(msg);
- assert(m);
r = sd_bus_message_new_method_return(msg, &reply);
if (r < 0)
}
static int method_cancel(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
- Transfer *t = userdata;
+ Transfer *t = ASSERT_PTR(userdata);
int r;
assert(msg);
- assert(t);
r = bus_verify_polkit_async(
msg,
}
static int method_cancel_transfer(sd_bus_message *msg, void *userdata, sd_bus_error *error) {
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
Transfer *t;
uint32_t id;
int r;
assert(msg);
- assert(m);
r = bus_verify_polkit_async(
msg,
void *userdata,
sd_bus_error *error) {
- Transfer *t = userdata;
+ Transfer *t = ASSERT_PTR(userdata);
assert(bus);
assert(reply);
- assert(t);
return sd_bus_message_append(reply, "d", transfer_percent_as_double(t));
}
void **found,
sd_bus_error *error) {
- Manager *m = userdata;
+ Manager *m = ASSERT_PTR(userdata);
Transfer *t;
const char *p;
uint32_t id;
assert(path);
assert(interface);
assert(found);
- assert(m);
p = startswith(path, "/org/freedesktop/import1/transfer/_");
if (!p)
m);
}
+static void manager_parse_env(Manager *m) {
+ int r;
+
+ assert(m);
+
+ /* Same as src/import/{import,pull}.c:
+ * Let's make these relatively low-level settings also controllable via env vars. User can then set
+ * them for systemd-importd.service if they like to tweak behaviour */
+
+ r = getenv_bool("SYSTEMD_IMPORT_BTRFS_SUBVOL");
+ if (r >= 0)
+ m->use_btrfs_subvol = r;
+ else if (r != -ENXIO)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_IMPORT_BTRFS_SUBVOL: %m");
+
+ r = getenv_bool("SYSTEMD_IMPORT_BTRFS_QUOTA");
+ if (r >= 0)
+ m->use_btrfs_quota = r;
+ else if (r != -ENXIO)
+ log_warning_errno(r, "Failed to parse $SYSTEMD_IMPORT_BTRFS_QUOTA: %m");
+}
+
static int run(int argc, char *argv[]) {
_cleanup_(manager_unrefp) Manager *m = NULL;
int r;
if (r < 0)
return log_error_errno(r, "Failed to allocate manager object: %m");
+ manager_parse_env(m);
+
r = manager_add_bus_objects(m);
if (r < 0)
return r;