mirror of
https://github.com/systemd/systemd.git
synced 2024-11-07 01:27:11 +03:00
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:
parent
56ebfaf1ca
commit
0d6e763b48
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,7 @@
|
|||||||
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
/***
|
/***
|
||||||
This file is part of systemd.
|
This file is part of systemd.
|
||||||
|
|
||||||
@ -24,12 +26,11 @@
|
|||||||
|
|
||||||
typedef struct RawImport RawImport;
|
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);
|
RawImport* raw_import_unref(RawImport *import);
|
||||||
|
|
||||||
DEFINE_TRIVIAL_CLEANUP_FUNC(RawImport*, raw_import_unref);
|
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_pull(RawImport *import, const char *url, const char *local, bool force_local);
|
||||||
int raw_import_cancel(RawImport *import, const char *name);
|
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
#include <curl/curl.h>
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include "hashmap.h"
|
|
||||||
#include "utf8.h"
|
#include "utf8.h"
|
||||||
#include "strv.h"
|
#include "strv.h"
|
||||||
#include "copy.h"
|
#include "copy.h"
|
||||||
@ -46,8 +45,6 @@ struct TarImport {
|
|||||||
TarImportFinished on_finished;
|
TarImportFinished on_finished;
|
||||||
void *userdata;
|
void *userdata;
|
||||||
|
|
||||||
bool finished;
|
|
||||||
|
|
||||||
char *local;
|
char *local;
|
||||||
bool force_local;
|
bool force_local;
|
||||||
|
|
||||||
@ -74,6 +71,7 @@ TarImport* tar_import_unref(TarImport *i) {
|
|||||||
if (i->temp_path) {
|
if (i->temp_path) {
|
||||||
(void) btrfs_subvol_remove(i->temp_path);
|
(void) btrfs_subvol_remove(i->temp_path);
|
||||||
(void) rm_rf_dangerous(i->temp_path, false, true, false);
|
(void) rm_rf_dangerous(i->temp_path, false, true, false);
|
||||||
|
free(i->temp_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(i->final_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;
|
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) {
|
static void tar_import_job_on_finished(ImportJob *j) {
|
||||||
TarImport *i;
|
TarImport *i;
|
||||||
int r;
|
int r;
|
||||||
@ -132,7 +152,6 @@ static void tar_import_job_on_finished(ImportJob *j) {
|
|||||||
assert(j->userdata);
|
assert(j->userdata);
|
||||||
|
|
||||||
i = j->userdata;
|
i = j->userdata;
|
||||||
|
|
||||||
if (j->error != 0) {
|
if (j->error != 0) {
|
||||||
r = j->error;
|
r = j->error;
|
||||||
goto finish;
|
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");
|
r = log_error_errno(errno, "Failed to rename to final image name: %m");
|
||||||
goto finish;
|
goto finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
free(i->temp_path);
|
||||||
|
i->temp_path = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i->local) {
|
r = tar_import_make_local_copy(i);
|
||||||
if (!i->final_path) {
|
if (r < 0)
|
||||||
r = import_make_path(j->url, j->etag, i->image_root, ".tar-", NULL, &i->final_path);
|
goto finish;
|
||||||
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 = 0;
|
r = 0;
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
i->finished = true;
|
|
||||||
|
|
||||||
if (i->on_finished)
|
if (i->on_finished)
|
||||||
i->on_finished(i, r, i->userdata);
|
i->on_finished(i, r, i->userdata);
|
||||||
else
|
else
|
||||||
|
@ -147,28 +147,47 @@ int import_make_local_copy(const char *final, const char *image_root, const char
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int import_make_read_only(const char *path) {
|
int import_make_read_only_fd(int fd) {
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
r = btrfs_subvol_set_read_only(path, true);
|
assert(fd >= 0);
|
||||||
if (r == -ENOTTY) {
|
|
||||||
|
/* 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;
|
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)
|
if (r < 0)
|
||||||
return log_error_errno(errno, "Failed to stat temporary image: %m");
|
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 log_error_errno(errno, "Failed to chmod() final image: %m");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
if (r < 0)
|
} else if (r < 0)
|
||||||
return log_error_errno(r, "Failed to mark final image read-only: %m");
|
return log_error_errno(r, "Failed to make subvolume read-only: %m");
|
||||||
|
|
||||||
return 0;
|
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) {
|
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;
|
_cleanup_free_ char *escaped_url = NULL;
|
||||||
char *path;
|
char *path;
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
bool http_etag_is_valid(const char *etag);
|
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_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_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_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);
|
int import_make_path(const char *url, const char *etag, const char *image_root, const char *prefix, const char *suffix, char **ret);
|
||||||
|
@ -226,7 +226,7 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
|
|||||||
_cleanup_(raw_import_unrefp) RawImport *import = NULL;
|
_cleanup_(raw_import_unrefp) RawImport *import = NULL;
|
||||||
_cleanup_event_unref_ sd_event *event = NULL;
|
_cleanup_event_unref_ sd_event *event = NULL;
|
||||||
const char *url, *local;
|
const char *url, *local;
|
||||||
_cleanup_free_ char *l = NULL;
|
_cleanup_free_ char *l = NULL, *ll = NULL;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
url = argv[1];
|
url = argv[1];
|
||||||
@ -238,44 +238,37 @@ static int pull_raw(int argc, char *argv[], void *userdata) {
|
|||||||
if (argc >= 3)
|
if (argc >= 3)
|
||||||
local = argv[2];
|
local = argv[2];
|
||||||
else {
|
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);
|
local = l;
|
||||||
while (e > url && e[-1] == '/')
|
|
||||||
e--;
|
|
||||||
|
|
||||||
p = e;
|
|
||||||
while (p > url && p[-1] != '/')
|
|
||||||
p--;
|
|
||||||
|
|
||||||
local = strndupa(p, e - p);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isempty(local) || streq(local, "-"))
|
if (isempty(local) || streq(local, "-"))
|
||||||
local = NULL;
|
local = NULL;
|
||||||
|
|
||||||
if (local) {
|
if (local) {
|
||||||
const char *p;
|
r = strip_raw_suffixes(local, &ll);
|
||||||
|
|
||||||
r = strip_raw_suffixes(local, &l);
|
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return log_oom();
|
return log_oom();
|
||||||
|
|
||||||
local = l;
|
local = ll;
|
||||||
|
|
||||||
if (!machine_name_is_valid(local)) {
|
if (!machine_name_is_valid(local)) {
|
||||||
log_error("Local image name '%s' is not valid.", local);
|
log_error("Local image name '%s' is not valid.", local);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
p = strappenda(arg_image_root, "/", local, ".raw");
|
if (!arg_force) {
|
||||||
if (laccess(p, F_OK) >= 0) {
|
r = image_find(local, NULL);
|
||||||
if (!arg_force) {
|
if (r < 0)
|
||||||
log_info("Image '%s' already exists.", local);
|
return log_error_errno(r, "Failed to check whether image '%s' exists: %m", local);
|
||||||
return 0;
|
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);
|
log_info("Pulling '%s', saving as '%s'.", url, local);
|
||||||
} else
|
} else
|
||||||
@ -417,7 +410,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
|||||||
" --image-root= Image root directory\n"
|
" --image-root= Image root directory\n"
|
||||||
" --dkr-index-url=URL Specify index URL to use for downloads\n\n"
|
" --dkr-index-url=URL Specify index URL to use for downloads\n\n"
|
||||||
"Commands:\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-raw URL [NAME] Download a RAW image\n"
|
||||||
" pull-dkr REMOTE [NAME] Download a DKR image\n",
|
" pull-dkr REMOTE [NAME] Download a DKR image\n",
|
||||||
program_invocation_short_name);
|
program_invocation_short_name);
|
||||||
|
@ -228,14 +228,18 @@ int btrfs_subvol_remove(const char *path) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int btrfs_subvol_set_read_only(const char *path, bool b) {
|
int btrfs_subvol_set_read_only_fd(int fd, bool b) {
|
||||||
_cleanup_close_ int fd = -1;
|
|
||||||
uint64_t flags, nflags;
|
uint64_t flags, nflags;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
fd = open(path, O_RDONLY|O_NOCTTY|O_CLOEXEC);
|
assert(fd >= 0);
|
||||||
if (fd < 0)
|
|
||||||
|
if (fstat(fd, &st) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
if (!S_ISDIR(st.st_mode) || st.st_ino != 256)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
|
if (ioctl(fd, BTRFS_IOC_SUBVOL_GETFLAGS, &flags) < 0)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
@ -253,6 +257,16 @@ int btrfs_subvol_set_read_only(const char *path, bool b) {
|
|||||||
return 0;
|
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) {
|
int btrfs_subvol_get_read_only_fd(int fd) {
|
||||||
uint64_t flags;
|
uint64_t flags;
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ int btrfs_subvol_make_label(const char *path);
|
|||||||
int btrfs_subvol_remove(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_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_set_read_only(const char *path, bool b);
|
||||||
int btrfs_subvol_get_read_only_fd(int fd);
|
int btrfs_subvol_get_read_only_fd(int fd);
|
||||||
int btrfs_subvol_get_id_fd(int fd, uint64_t *ret);
|
int btrfs_subvol_get_id_fd(int fd, uint64_t *ret);
|
||||||
|
Loading…
Reference in New Issue
Block a user