import: port pull-raw to helper tools implemented for pull-tar

This allows us to reuse a lot more code, and simplify pull-raw
drastically.
This commit is contained in:
Lennart Poettering 2015-01-20 03:00:07 +01:00
parent 56ebfaf1ca
commit 0d6e763b48
8 changed files with 293 additions and 839 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,7 @@
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
#pragma once
/***
This file is part of systemd.
@ -24,12 +26,11 @@
typedef struct RawImport RawImport;
typedef void (*raw_import_on_finished)(RawImport *import, int error, void *userdata);
typedef void (*RawImportFinished)(RawImport *import, int error, void *userdata);
int raw_import_new(RawImport **import, sd_event *event, const char *image_root, raw_import_on_finished on_finished, void *userdata);
int raw_import_new(RawImport **import, sd_event *event, const char *image_root, RawImportFinished on_finished, void *userdata);
RawImport* raw_import_unref(RawImport *import);
DEFINE_TRIVIAL_CLEANUP_FUNC(RawImport*, raw_import_unref);
int raw_import_pull(RawImport *import, const char *url, const char *local, bool force_local);
int raw_import_cancel(RawImport *import, const char *name);

View File

@ -22,7 +22,6 @@
#include <sys/prctl.h>
#include <curl/curl.h>
#include "hashmap.h"
#include "utf8.h"
#include "strv.h"
#include "copy.h"
@ -46,8 +45,6 @@ struct TarImport {
TarImportFinished on_finished;
void *userdata;
bool finished;
char *local;
bool force_local;
@ -74,6 +71,7 @@ TarImport* tar_import_unref(TarImport *i) {
if (i->temp_path) {
(void) btrfs_subvol_remove(i->temp_path);
(void) rm_rf_dangerous(i->temp_path, false, true, false);
free(i->temp_path);
}
free(i->final_path);
@ -124,6 +122,28 @@ int tar_import_new(TarImport **ret, sd_event *event, const char *image_root, Tar
return 0;
}
static int tar_import_make_local_copy(TarImport *i) {
int r;
assert(i);
assert(i->tar_job);
if (!i->local)
return 0;
if (!i->final_path) {
r = import_make_path(i->tar_job->url, i->tar_job->etag, i->image_root, ".tar-", NULL, &i->final_path);
if (r < 0)
return log_oom();
r = import_make_local_copy(i->final_path, i->image_root, i->local, i->force_local);
if (r < 0)
return r;
}
return 0;
}
static void tar_import_job_on_finished(ImportJob *j) {
TarImport *i;
int r;
@ -132,7 +152,6 @@ static void tar_import_job_on_finished(ImportJob *j) {
assert(j->userdata);
i = j->userdata;
if (j->error != 0) {
r = j->error;
goto finish;
@ -160,25 +179,18 @@ static void tar_import_job_on_finished(ImportJob *j) {
r = log_error_errno(errno, "Failed to rename to final image name: %m");
goto finish;
}
free(i->temp_path);
i->temp_path = NULL;
}
if (i->local) {
if (!i->final_path) {
r = import_make_path(j->url, j->etag, i->image_root, ".tar-", NULL, &i->final_path);
if (r < 0)
goto finish;
}
r = import_make_local_copy(i->final_path, i->image_root, i->local, i->force_local);
if (r < 0)
goto finish;
}
r = tar_import_make_local_copy(i);
if (r < 0)
goto finish;
r = 0;
finish:
i->finished = true;
if (i->on_finished)
i->on_finished(i, r, i->userdata);
else

View File

@ -147,28 +147,47 @@ int import_make_local_copy(const char *final, const char *image_root, const char
return 0;
}
int import_make_read_only(const char *path) {
int import_make_read_only_fd(int fd) {
int r;
r = btrfs_subvol_set_read_only(path, true);
if (r == -ENOTTY) {
assert(fd >= 0);
/* First, let's make this a read-only subvolume if it refers
* to a subvolume */
r = btrfs_subvol_set_read_only_fd(fd, true);
if (r == -ENOTTY || r == -ENOTDIR || r == -EINVAL) {
struct stat st;
r = stat(path, &st);
/* This doesn't refer to a subvolume, or the file
* system isn't even btrfs. In that, case fall back to
* chmod()ing */
r = fstat(fd, &st);
if (r < 0)
return log_error_errno(errno, "Failed to stat temporary image: %m");
if (chmod(path, st.st_mode & 0755) < 0)
/* Drop "w" flag */
if (fchmod(fd, st.st_mode & 07555) < 0)
return log_error_errno(errno, "Failed to chmod() final image: %m");
return 0;
}
if (r < 0)
return log_error_errno(r, "Failed to mark final image read-only: %m");
} else if (r < 0)
return log_error_errno(r, "Failed to make subvolume read-only: %m");
return 0;
}
int import_make_read_only(const char *path) {
_cleanup_close_ int fd = 1;
fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return log_error_errno(errno, "Failed to open %s: %m", path);
return import_make_read_only_fd(fd);
}
int import_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret) {
_cleanup_free_ char *escaped_url = NULL;
char *path;

View File

@ -26,6 +26,10 @@
bool http_etag_is_valid(const char *etag);
int import_make_local_copy(const char *final, const char *root, const char *local, bool force_local);
int import_find_old_etags(const char *url, const char *root, int dt, const char *prefix, const char *suffix, char ***etags);
int import_make_read_only_fd(int fd);
int import_make_read_only(const char *path);
int import_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret);

View File

@ -226,7 +226,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
_cleanup_(raw_import_unrefp) RawImport *import = NULL;
_cleanup_event_unref_ sd_event *event = NULL;
const char *url, *local;
_cleanup_free_ char *l = NULL;
_cleanup_free_ char *l = NULL, *ll = NULL;
int r;
url = argv[1];
@ -238,44 +238,37 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
if (argc >= 3)
local = argv[2];
else {
const char *e, *p;
r = url_final_component(url, &l);
if (r < 0)
return log_error_errno(r, "Failed get final component of URL: %m");
e = url + strlen(url);
while (e > url && e[-1] == '/')
e--;
p = e;
while (p > url && p[-1] != '/')
p--;
local = strndupa(p, e - p);
local = l;
}
if (isempty(local) || streq(local, "-"))
local = NULL;
if (local) {
const char *p;
r = strip_raw_suffixes(local, &l);
r = strip_raw_suffixes(local, &ll);
if (r < 0)
return log_oom();
local = l;
local = ll;
if (!machine_name_is_valid(local)) {
log_error("Local image name '%s' is not valid.", local);
return -EINVAL;
}
p = strappenda(arg_image_root, "/", local, ".raw");
if (laccess(p, F_OK) >= 0) {
if (!arg_force) {
log_info("Image '%s' already exists.", local);
return 0;
if (!arg_force) {
r = image_find(local, NULL);
if (r < 0)
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
else if (r > 0) {
log_error_errno(EEXIST, "Image '%s' already exists.", local);
return -EEXIST;
}
} else if (errno != ENOENT)
return log_error_errno(errno, "Can't check if image '%s' already exists: %m", local);
}
log_info("Pulling '%s', saving as '%s'.", url, local);
} else
@ -417,7 +410,7 @@ static int help(int argc, char *argv[], void *userdata) {
" --image-root= Image root directory\n"
" --dkr-index-url=URL Specify index URL to use for downloads\n\n"
"Commands:\n"
" pull-tar URL Download a TAR image\n"
" pull-tar URL [NAME] Download a TAR image\n"
" pull-raw URL [NAME] Download a RAW image\n"
" pull-dkr REMOTE [NAME] Download a DKR image\n",
program_invocation_short_name);

View File

@ -228,14 +228,18 @@ int btrfs_subvol_remove(const char *path) {
return 0;
}
int btrfs_subvol_set_read_only(const char *path, bool b) {
_cleanup_close_ int fd = -1;
int btrfs_subvol_set_read_only_fd(int fd, bool b) {
uint64_t flags, nflags;
struct stat st;
fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
assert(fd >= 0);
if (fstat(fd, &st) < 0)
return -errno;
if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
return -EINVAL;
if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
return -errno;
@ -253,6 +257,16 @@ int btrfs_subvol_set_read_only(const char *path, bool b) {
return 0;
}
int btrfs_subvol_set_read_only(const char *path, bool b) {
_cleanup_close_ int fd = -1;
fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY);
if (fd < 0)
return -errno;
return btrfs_subvol_set_read_only_fd(fd, b);
}
int btrfs_subvol_get_read_only_fd(int fd) {
uint64_t flags;

View File

@ -48,6 +48,7 @@ int btrfs_subvol_make_label(const char *path);
int btrfs_subvol_remove(const char *path);
int btrfs_subvol_snapshot(const char *old_path, const char *new_path, bool read_only, bool fallback_copy);
int btrfs_subvol_set_read_only_fd(int fd, bool b);
int btrfs_subvol_set_read_only(const char *path, bool b);
int btrfs_subvol_get_read_only_fd(int fd);
int btrfs_subvol_get_id_fd(int fd, uint64_t *ret);