mirror of
https://github.com/systemd/systemd.git
synced 2024-11-23 10:13:34 +08:00
dissect: add --make-archive option to convert DDI to tarball
This commit is contained in:
parent
6811774510
commit
b68f4cade4
@ -41,6 +41,9 @@ actions:
|
||||
- 'sed -i "/^CONFIGURE_OPTS=(/a--werror" .packit_rpm/systemd.spec'
|
||||
# Ignore unpackaged standalone binaries
|
||||
- "sed -i 's/assert False,.*/pass/' .packit_rpm/split-files.py"
|
||||
# Temporarily add libarchive-devel build dep until the change propagates to
|
||||
# Rawhide's specfile
|
||||
- "sed -ri '0,/^BuildRequires: .+$/s//&\\nBuildRequires: libarchive-devel/' .packit_rpm/systemd.spec"
|
||||
|
||||
jobs:
|
||||
- job: copr_build
|
||||
|
@ -53,6 +53,9 @@
|
||||
<cmdsynopsis>
|
||||
<command>systemd-dissect</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg>--copy-to</arg> <arg choice="plain"><replaceable>IMAGE</replaceable></arg> <arg choice="opt"><replaceable>SOURCE</replaceable></arg> <arg choice="plain"><replaceable>PATH</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-dissect</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg>--make-archive</arg> <arg choice="plain"><replaceable>IMAGE</replaceable></arg> <arg choice="opt"><replaceable>TARGET</replaceable></arg>
|
||||
</cmdsynopsis>
|
||||
<cmdsynopsis>
|
||||
<command>systemd-dissect</command> <arg choice="opt" rep="repeat">OPTIONS</arg> <arg>--discover</arg>
|
||||
</cmdsynopsis>
|
||||
@ -305,6 +308,21 @@
|
||||
<xi:include href="version-info.xml" xpointer="v247"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--make-archive</option></term>
|
||||
|
||||
<listitem><para>Generates an archive file from the specified disk image. Expects two arguments: the
|
||||
path to the disk image and optionally the output archive file path. If the latter is omitted the
|
||||
archive is written to standard output. The archive file format is determined automatically from the
|
||||
specified output archive file name, e.g. any path suffixed with <literal>.tar.xz</literal> will
|
||||
result in an xz compressed UNIX tarball (if the path is omitted an uncompressed UNIX tarball is
|
||||
created). See
|
||||
<citerefentry><refentrytitle>libarchive</refentrytitle><manvolnum>3</manvolnum></citerefentry> for a
|
||||
list of supported archive formats and compression schemes.</para>
|
||||
|
||||
<xi:include href="version-info.xml" xpointer="v256"/></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--discover</option></term>
|
||||
|
||||
@ -535,10 +553,18 @@
|
||||
<title>Examples</title>
|
||||
|
||||
<example>
|
||||
<title>Generate a tarball from an OS disk image</title>
|
||||
<title>Generate a tarball from an OS disk image (<option>--with</option>)</title>
|
||||
|
||||
<programlisting># systemd-dissect --with foo.raw tar cz . >foo.tar.gz</programlisting>
|
||||
</example>
|
||||
|
||||
<para>or alternatively just:</para>
|
||||
|
||||
<example>
|
||||
<title>Generate a tarball from an OS disk image (<option>--make-archive</option>)</title>
|
||||
|
||||
<programlisting># systemd-dissect --make-archive foo.raw foo.tar.gz</programlisting>
|
||||
</example>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -1413,6 +1413,11 @@ elif compression == 'xz' and not libxz.found()
|
||||
endif
|
||||
conf.set('DEFAULT_COMPRESSION', 'COMPRESSION_@0@'.format(compression.to_upper()))
|
||||
|
||||
libarchive = dependency('libarchive',
|
||||
version : '>= 3.0',
|
||||
required : get_option('libarchive'))
|
||||
conf.set10('HAVE_LIBARCHIVE', libarchive.found())
|
||||
|
||||
libxkbcommon = dependency('xkbcommon',
|
||||
version : '>= 0.3.0',
|
||||
required : get_option('xkbcommon'))
|
||||
|
@ -451,6 +451,8 @@ option('glib', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'd
|
||||
description : 'libglib support (for tests only)')
|
||||
option('dbus', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
|
||||
description : 'libdbus support (for tests only)')
|
||||
option('libarchive', type : 'feature',
|
||||
description : 'libarchive support')
|
||||
|
||||
option('bootloader', type : 'feature', deprecated : { 'true' : 'enabled', 'false' : 'disabled' },
|
||||
description : 'sd-boot/stub and userspace tools')
|
||||
|
@ -153,6 +153,7 @@ if [ ! -f "$BUILDDIR"/build.ninja ]; then
|
||||
-D initrd=true
|
||||
-D fexecve=true
|
||||
-D default-keymap="$DEFAULT_KEYMAP"
|
||||
-D libarchive=enabled
|
||||
)
|
||||
|
||||
# On debian-like systems the library directory is not /usr/lib64 but /usr/lib/<arch-triplet>/.
|
||||
|
@ -8,6 +8,7 @@ Packages=
|
||||
cryptsetup
|
||||
dbus
|
||||
gnutls
|
||||
libarchive
|
||||
libbpf
|
||||
libfido2
|
||||
libmicrohttpd
|
||||
|
@ -9,6 +9,7 @@ Packages=
|
||||
audit-libs
|
||||
cryptsetup-libs
|
||||
gnutls
|
||||
libarchive
|
||||
libasan
|
||||
libbpf
|
||||
libfido2
|
||||
@ -39,6 +40,7 @@ BuildPackages=
|
||||
pkgconfig(glib-2.0)
|
||||
pkgconfig(gnutls)
|
||||
pkgconfig(libacl)
|
||||
pkgconfig(libarchive)
|
||||
pkgconfig(libbpf)
|
||||
pkgconfig(libcap)
|
||||
pkgconfig(libcryptsetup)
|
||||
|
@ -8,6 +8,7 @@ Distribution=|ubuntu
|
||||
Packages=
|
||||
dmsetup
|
||||
libapparmor1
|
||||
libarchive13
|
||||
libfdisk1
|
||||
libfido2-1
|
||||
libglib2.0-0
|
||||
@ -30,6 +31,7 @@ BuildPackages=
|
||||
g++
|
||||
libacl1-dev
|
||||
libapparmor-dev
|
||||
libarchive-dev
|
||||
libaudit-dev
|
||||
libblkid-dev
|
||||
libbpf-dev
|
||||
|
@ -14,6 +14,7 @@ Packages=
|
||||
grep
|
||||
gzip
|
||||
libbpf1
|
||||
libarchive13
|
||||
libcrypt1
|
||||
libcryptsetup12
|
||||
libdw1
|
||||
@ -53,6 +54,7 @@ BuildPackages=
|
||||
intltool
|
||||
libacl-devel
|
||||
libapparmor-devel
|
||||
libarchive-devel
|
||||
libblkid-devel
|
||||
libbpf-devel
|
||||
libcap-devel
|
||||
|
@ -238,6 +238,12 @@ const char* const systemd_features =
|
||||
" -SYSVINIT"
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBARCHIVE
|
||||
" +LIBARCHIVE"
|
||||
#else
|
||||
" -LIBARCHIVE"
|
||||
#endif
|
||||
|
||||
" default-hierarchy=" DEFAULT_HIERARCHY_NAME
|
||||
;
|
||||
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "format-util.h"
|
||||
#include "fs-util.h"
|
||||
#include "hexdecoct.h"
|
||||
#include "libarchive-util.h"
|
||||
#include "log.h"
|
||||
#include "loop-util.h"
|
||||
#include "main-func.h"
|
||||
@ -63,6 +64,7 @@ static enum {
|
||||
ACTION_COPY_TO,
|
||||
ACTION_DISCOVER,
|
||||
ACTION_VALIDATE,
|
||||
ACTION_MAKE_ARCHIVE,
|
||||
} arg_action = ACTION_DISSECT;
|
||||
static char *arg_image = NULL;
|
||||
static char *arg_root = NULL;
|
||||
@ -116,6 +118,7 @@ static int help(void) {
|
||||
"%1$s [OPTIONS...] --with IMAGE [COMMAND…]\n"
|
||||
"%1$s [OPTIONS...] --copy-from IMAGE PATH [TARGET]\n"
|
||||
"%1$s [OPTIONS...] --copy-to IMAGE [SOURCE] PATH\n"
|
||||
"%1$s [OPTIONS...] --make-archive IMAGE [TARGET]\n"
|
||||
"%1$s [OPTIONS...] --discover\n"
|
||||
"%1$s [OPTIONS...] --validate IMAGE\n"
|
||||
"\n%5$sDissect a Discoverable Disk Image (DDI).%6$s\n\n"
|
||||
@ -157,6 +160,7 @@ static int help(void) {
|
||||
" --with Mount, run command, unmount\n"
|
||||
" -x --copy-from Copy files from image to host\n"
|
||||
" -a --copy-to Copy files from host to image\n"
|
||||
" --make-archive Convert the DDI to an archive file\n"
|
||||
" --discover Discover DDIs in well known directories\n"
|
||||
" --validate Validate image and image policy\n"
|
||||
"\nSee the %2$s for details.\n",
|
||||
@ -263,6 +267,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_IMAGE_POLICY,
|
||||
ARG_VALIDATE,
|
||||
ARG_MTREE_HASH,
|
||||
ARG_MAKE_ARCHIVE,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -295,6 +300,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "image-policy", required_argument, NULL, ARG_IMAGE_POLICY },
|
||||
{ "validate", no_argument, NULL, ARG_VALIDATE },
|
||||
{ "mtree-hash", required_argument, NULL, ARG_MTREE_HASH },
|
||||
{ "make-archive", no_argument, NULL, ARG_MAKE_ARCHIVE },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -518,6 +524,15 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
return r;
|
||||
break;
|
||||
|
||||
case ARG_MAKE_ARCHIVE:
|
||||
|
||||
r = dlopen_libarchive();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Archive support not available (compiled without libarchive, or libarchive not installed?).");
|
||||
|
||||
arg_action = ACTION_MAKE_ARCHIVE;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@ -600,6 +615,19 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_flags |= DISSECT_IMAGE_READ_ONLY | DISSECT_IMAGE_REQUIRE_ROOT;
|
||||
break;
|
||||
|
||||
case ACTION_MAKE_ARCHIVE:
|
||||
if (argc < optind + 1 || argc > optind + 2)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Expected an image file, and an optional target path as only arguments.");
|
||||
|
||||
r = parse_image_path_argument(argv[optind], &arg_root, &arg_image);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
arg_target = argc > optind + 1 ? empty_or_dash_to_null(argv[optind + 1]) : NULL;
|
||||
arg_flags |= DISSECT_IMAGE_READ_ONLY | DISSECT_IMAGE_REQUIRE_ROOT;
|
||||
break;
|
||||
|
||||
case ACTION_COPY_FROM:
|
||||
if (argc < optind + 2 || argc > optind + 3)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
@ -1274,13 +1302,116 @@ static int mtree_print_item(
|
||||
return RECURSE_DIR_CONTINUE;
|
||||
}
|
||||
|
||||
static int action_list_or_mtree_or_copy(DissectedImage *m, LoopDevice *d) {
|
||||
#if HAVE_LIBARCHIVE
|
||||
static int archive_item(
|
||||
RecurseDirEvent event,
|
||||
const char *path,
|
||||
int dir_fd,
|
||||
int inode_fd,
|
||||
const struct dirent *de,
|
||||
const struct statx *sx,
|
||||
void *userdata) {
|
||||
|
||||
struct archive *a = ASSERT_PTR(userdata);
|
||||
int r;
|
||||
|
||||
assert(path);
|
||||
|
||||
if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
|
||||
return RECURSE_DIR_CONTINUE;
|
||||
|
||||
assert(inode_fd >= 0);
|
||||
assert(sx);
|
||||
|
||||
log_debug("Archiving %s\n", path);
|
||||
|
||||
_cleanup_(sym_archive_entry_freep) struct archive_entry *entry = NULL;
|
||||
entry = sym_archive_entry_new();
|
||||
if (!entry)
|
||||
return log_oom();
|
||||
|
||||
assert(FLAGS_SET(sx->stx_mask, STATX_TYPE|STATX_MODE));
|
||||
sym_archive_entry_set_pathname(entry, path);
|
||||
sym_archive_entry_set_filetype(entry, sx->stx_mode);
|
||||
|
||||
if (!S_ISLNK(sx->stx_mode))
|
||||
sym_archive_entry_set_perm(entry, sx->stx_mode);
|
||||
|
||||
if (FLAGS_SET(sx->stx_mask, STATX_UID))
|
||||
sym_archive_entry_set_uid(entry, sx->stx_uid);
|
||||
if (FLAGS_SET(sx->stx_mask, STATX_GID))
|
||||
sym_archive_entry_set_gid(entry, sx->stx_gid);
|
||||
|
||||
if (S_ISREG(sx->stx_mode)) {
|
||||
if (!FLAGS_SET(sx->stx_mask, STATX_SIZE))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EIO), "Unable to determine file size of '%s'.", path);
|
||||
|
||||
sym_archive_entry_set_size(entry, sx->stx_size);
|
||||
}
|
||||
|
||||
if (S_ISCHR(sx->stx_mode) || S_ISBLK(sx->stx_mode)) {
|
||||
sym_archive_entry_set_rdevmajor(entry, sx->stx_rdev_major);
|
||||
sym_archive_entry_set_rdevminor(entry, sx->stx_rdev_minor);
|
||||
}
|
||||
|
||||
/* We care about a modicum of reproducibility here, hence we don't save atime/btime here */
|
||||
if (FLAGS_SET(sx->stx_mask, STATX_MTIME))
|
||||
sym_archive_entry_set_mtime(entry, sx->stx_mtime.tv_sec, sx->stx_mtime.tv_nsec);
|
||||
if (FLAGS_SET(sx->stx_mask, STATX_CTIME))
|
||||
sym_archive_entry_set_ctime(entry, sx->stx_ctime.tv_sec, sx->stx_ctime.tv_nsec);
|
||||
|
||||
if (S_ISLNK(sx->stx_mode)) {
|
||||
_cleanup_free_ char *s = NULL;
|
||||
|
||||
assert(dir_fd >= 0);
|
||||
assert(de);
|
||||
|
||||
r = readlinkat_malloc(dir_fd, de->d_name, &s);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to read symlink target of '%s': %m", path);
|
||||
|
||||
sym_archive_entry_set_symlink(entry, s);
|
||||
}
|
||||
|
||||
if (sym_archive_write_header(a, entry) != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to write archive entry header: %s", sym_archive_error_string(a));
|
||||
|
||||
if (S_ISREG(sx->stx_mode)) {
|
||||
_cleanup_close_ int data_fd = -EBADF;
|
||||
|
||||
/* Convert the O_PATH fd in a proper fd */
|
||||
data_fd = fd_reopen(inode_fd, O_RDONLY|O_CLOEXEC);
|
||||
if (data_fd < 0)
|
||||
return log_error_errno(data_fd, "Failed to open '%s': %m", path);
|
||||
|
||||
for (;;) {
|
||||
char buffer[64*1024];
|
||||
ssize_t l;
|
||||
|
||||
l = read(data_fd, buffer, sizeof(buffer));
|
||||
if (l < 0)
|
||||
return log_error_errno(errno, "Failed to read '%s': %m", path);
|
||||
if (l == 0)
|
||||
break;
|
||||
|
||||
la_ssize_t k;
|
||||
k = sym_archive_write_data(a, buffer, l);
|
||||
if (k < 0)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to write archive data: %s", sym_archive_error_string(a));
|
||||
}
|
||||
}
|
||||
|
||||
return RECURSE_DIR_CONTINUE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int action_list_or_mtree_or_copy_or_make_archive(DissectedImage *m, LoopDevice *d) {
|
||||
_cleanup_(umount_and_rmdir_and_freep) char *mounted_dir = NULL;
|
||||
_cleanup_free_ char *t = NULL;
|
||||
const char *root;
|
||||
int r;
|
||||
|
||||
assert(IN_SET(arg_action, ACTION_LIST, ACTION_MTREE, ACTION_COPY_FROM, ACTION_COPY_TO));
|
||||
assert(IN_SET(arg_action, ACTION_LIST, ACTION_MTREE, ACTION_COPY_FROM, ACTION_COPY_TO, ACTION_MAKE_ARCHIVE));
|
||||
|
||||
if (arg_image) {
|
||||
assert(m);
|
||||
@ -1466,6 +1597,68 @@ static int action_list_or_mtree_or_copy(DissectedImage *m, LoopDevice *d) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case ACTION_MAKE_ARCHIVE: {
|
||||
#if HAVE_LIBARCHIVE
|
||||
_cleanup_(unlink_and_freep) char *tar = NULL;
|
||||
_cleanup_close_ int dfd = -EBADF;
|
||||
_cleanup_fclose_ FILE *f = NULL;
|
||||
|
||||
dfd = open(root, O_DIRECTORY|O_CLOEXEC|O_RDONLY);
|
||||
if (dfd < 0)
|
||||
return log_error_errno(errno, "Failed to open mount directory: %m");
|
||||
|
||||
_cleanup_(sym_archive_write_freep) struct archive *a = sym_archive_write_new();
|
||||
if (!a)
|
||||
return log_oom();
|
||||
|
||||
if (arg_target)
|
||||
r = sym_archive_write_set_format_filter_by_ext(a, arg_target);
|
||||
else
|
||||
r = sym_archive_write_set_format_gnutar(a);
|
||||
if (r != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set libarchive output format: %s", sym_archive_error_string(a));
|
||||
|
||||
if (arg_target) {
|
||||
r = fopen_tmpfile_linkable(arg_target, O_WRONLY|O_CLOEXEC, &tar, &f);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to create target file '%s': %m", arg_target);
|
||||
|
||||
r = sym_archive_write_open_FILE(a, f);
|
||||
} else {
|
||||
if (isatty(STDOUT_FILENO))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EBADF), "Refusing to write archive to TTY.");
|
||||
|
||||
r = sym_archive_write_open_fd(a, STDOUT_FILENO);
|
||||
}
|
||||
if (r != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Failed to set libarchive output file: %s", sym_archive_error_string(a));
|
||||
|
||||
r = recurse_dir(dfd,
|
||||
".",
|
||||
STATX_TYPE|STATX_MODE|STATX_UID|STATX_GID|STATX_SIZE|STATX_ATIME|STATX_CTIME,
|
||||
UINT_MAX,
|
||||
RECURSE_DIR_SORT|RECURSE_DIR_INODE_FD|RECURSE_DIR_TOPLEVEL,
|
||||
archive_item,
|
||||
a);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to make archive: %m");
|
||||
|
||||
r = sym_archive_write_close(a);
|
||||
if (r != ARCHIVE_OK)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(ENOTRECOVERABLE), "Unable to finish writing archive: %s", sym_archive_error_string(a));
|
||||
|
||||
if (arg_target) {
|
||||
r = flink_tmpfile(f, tar, arg_target, LINK_TMPFILE_REPLACE);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to move archive file into place: %m");
|
||||
}
|
||||
|
||||
return 0;
|
||||
#else
|
||||
assert_not_reached();
|
||||
#endif
|
||||
}
|
||||
|
||||
default:
|
||||
assert_not_reached();
|
||||
}
|
||||
@ -1914,7 +2107,8 @@ static int run(int argc, char *argv[]) {
|
||||
case ACTION_MTREE:
|
||||
case ACTION_COPY_FROM:
|
||||
case ACTION_COPY_TO:
|
||||
return action_list_or_mtree_or_copy(m, d);
|
||||
case ACTION_MAKE_ARCHIVE:
|
||||
return action_list_or_mtree_or_copy_or_make_archive(m, d);
|
||||
|
||||
case ACTION_WITH:
|
||||
return action_with(m, d);
|
||||
|
62
src/shared/libarchive-util.c
Normal file
62
src/shared/libarchive-util.c
Normal file
@ -0,0 +1,62 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include "libarchive-util.h"
|
||||
|
||||
#if HAVE_LIBARCHIVE
|
||||
static void *libarchive_dl = NULL;
|
||||
|
||||
DLSYM_FUNCTION(archive_entry_free);
|
||||
DLSYM_FUNCTION(archive_entry_new);
|
||||
DLSYM_FUNCTION(archive_entry_set_ctime);
|
||||
DLSYM_FUNCTION(archive_entry_set_filetype);
|
||||
DLSYM_FUNCTION(archive_entry_set_gid);
|
||||
DLSYM_FUNCTION(archive_entry_set_mtime);
|
||||
DLSYM_FUNCTION(archive_entry_set_pathname);
|
||||
DLSYM_FUNCTION(archive_entry_set_perm);
|
||||
DLSYM_FUNCTION(archive_entry_set_rdevmajor);
|
||||
DLSYM_FUNCTION(archive_entry_set_rdevminor);
|
||||
DLSYM_FUNCTION(archive_entry_set_symlink);
|
||||
DLSYM_FUNCTION(archive_entry_set_size);
|
||||
DLSYM_FUNCTION(archive_entry_set_uid);
|
||||
DLSYM_FUNCTION(archive_error_string);
|
||||
DLSYM_FUNCTION(archive_write_close);
|
||||
DLSYM_FUNCTION(archive_write_data);
|
||||
DLSYM_FUNCTION(archive_write_free);
|
||||
DLSYM_FUNCTION(archive_write_header);
|
||||
DLSYM_FUNCTION(archive_write_new);
|
||||
DLSYM_FUNCTION(archive_write_open_FILE);
|
||||
DLSYM_FUNCTION(archive_write_open_fd);
|
||||
DLSYM_FUNCTION(archive_write_set_format_filter_by_ext);
|
||||
DLSYM_FUNCTION(archive_write_set_format_gnutar);
|
||||
|
||||
int dlopen_libarchive(void) {
|
||||
return dlopen_many_sym_or_warn(
|
||||
&libarchive_dl,
|
||||
"libarchive.so.13",
|
||||
LOG_DEBUG,
|
||||
DLSYM_ARG(archive_entry_free),
|
||||
DLSYM_ARG(archive_entry_new),
|
||||
DLSYM_ARG(archive_entry_set_ctime),
|
||||
DLSYM_ARG(archive_entry_set_filetype),
|
||||
DLSYM_ARG(archive_entry_set_gid),
|
||||
DLSYM_ARG(archive_entry_set_mtime),
|
||||
DLSYM_ARG(archive_entry_set_pathname),
|
||||
DLSYM_ARG(archive_entry_set_perm),
|
||||
DLSYM_ARG(archive_entry_set_rdevmajor),
|
||||
DLSYM_ARG(archive_entry_set_rdevminor),
|
||||
DLSYM_ARG(archive_entry_set_size),
|
||||
DLSYM_ARG(archive_entry_set_symlink),
|
||||
DLSYM_ARG(archive_entry_set_uid),
|
||||
DLSYM_ARG(archive_error_string),
|
||||
DLSYM_ARG(archive_write_close),
|
||||
DLSYM_ARG(archive_write_data),
|
||||
DLSYM_ARG(archive_write_free),
|
||||
DLSYM_ARG(archive_write_header),
|
||||
DLSYM_ARG(archive_write_new),
|
||||
DLSYM_ARG(archive_write_open_FILE),
|
||||
DLSYM_ARG(archive_write_open_fd),
|
||||
DLSYM_ARG(archive_write_set_format_filter_by_ext),
|
||||
DLSYM_ARG(archive_write_set_format_gnutar));
|
||||
}
|
||||
|
||||
#endif
|
45
src/shared/libarchive-util.h
Normal file
45
src/shared/libarchive-util.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
#pragma once
|
||||
|
||||
#include "dlfcn-util.h"
|
||||
|
||||
#if HAVE_LIBARCHIVE
|
||||
#include <archive.h>
|
||||
#include <archive_entry.h>
|
||||
|
||||
DLSYM_PROTOTYPE(archive_entry_free);
|
||||
DLSYM_PROTOTYPE(archive_entry_new);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_ctime);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_filetype);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_gid);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_mtime);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_pathname);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_perm);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_rdevmajor);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_rdevminor);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_symlink);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_size);
|
||||
DLSYM_PROTOTYPE(archive_entry_set_uid);
|
||||
DLSYM_PROTOTYPE(archive_error_string);
|
||||
DLSYM_PROTOTYPE(archive_write_close);
|
||||
DLSYM_PROTOTYPE(archive_write_data);
|
||||
DLSYM_PROTOTYPE(archive_write_free);
|
||||
DLSYM_PROTOTYPE(archive_write_header);
|
||||
DLSYM_PROTOTYPE(archive_write_new);
|
||||
DLSYM_PROTOTYPE(archive_write_open_FILE);
|
||||
DLSYM_PROTOTYPE(archive_write_open_fd);
|
||||
DLSYM_PROTOTYPE(archive_write_set_format_filter_by_ext);
|
||||
DLSYM_PROTOTYPE(archive_write_set_format_gnutar);
|
||||
|
||||
int dlopen_libarchive(void);
|
||||
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct archive_entry*, sym_archive_entry_free, NULL);
|
||||
DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(struct archive*, sym_archive_write_free, NULL);
|
||||
|
||||
#else
|
||||
|
||||
static inline int dlopen_libarchive(void) {
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
#endif
|
@ -103,6 +103,7 @@ shared_sources = files(
|
||||
'keyring-util.c',
|
||||
'killall.c',
|
||||
'label-util.c',
|
||||
'libarchive-util.c',
|
||||
'libcrypt-util.c',
|
||||
'libfido2-util.c',
|
||||
'libmount-util.c',
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "cryptsetup-util.h"
|
||||
#include "elf-util.h"
|
||||
#include "idn-util.h"
|
||||
#include "libarchive-util.h"
|
||||
#include "libfido2-util.h"
|
||||
#include "macro.h"
|
||||
#include "main-func.h"
|
||||
@ -70,6 +71,10 @@ static int run(int argc, char **argv) {
|
||||
assert_se(dlopen_p11kit() >= 0);
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBARCHIVE
|
||||
assert_se(dlopen_libarchive() >= 0);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,7 @@ test_append_files() {
|
||||
generate_module_dependencies
|
||||
inst_binary wc
|
||||
inst_binary sha256sum
|
||||
inst_binary tar
|
||||
if command -v openssl >/dev/null 2>&1; then
|
||||
inst_binary openssl
|
||||
fi
|
||||
|
@ -1551,7 +1551,7 @@ install_missing_libraries() {
|
||||
local lib path
|
||||
# A number of dependencies is now optional via dlopen, so the install
|
||||
# script will not pick them up, since it looks at linkage.
|
||||
for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1; do
|
||||
for lib in libcryptsetup libidn libidn2 pwquality libqrencode tss2-esys tss2-rc tss2-mu tss2-tcti-device libfido2 libbpf libelf libdw xkbcommon p11-kit-1 libarchive; do
|
||||
ddebug "Searching for $lib via pkg-config"
|
||||
if pkg-config --exists "$lib"; then
|
||||
path="$(pkg-config --variable=libdir "$lib")"
|
||||
|
@ -54,6 +54,17 @@ read -r SHA256SUM2 _ < <(systemd-dissect --read-only --with "${image}.raw" sha25
|
||||
test "$SHA256SUM2" != ""
|
||||
test "$SHA256SUM1" = "$SHA256SUM2"
|
||||
|
||||
if systemctl --version | grep -qF -- "+LIBARCHIVE" ; then
|
||||
# Make sure tarballs are reproducible
|
||||
read -r SHA256SUM1 _ < <(systemd-dissect --make-archive "${image}.raw" | sha256sum)
|
||||
test "$SHA256SUM1" != ""
|
||||
read -r SHA256SUM2 _ < <(systemd-dissect --make-archive "${image}.raw" | sha256sum)
|
||||
test "$SHA256SUM2" != ""
|
||||
test "$SHA256SUM1" = "$SHA256SUM2"
|
||||
# Also check that a file we expect to be there is there
|
||||
systemd-dissect --make-archive "${image}.raw" | tar t | grep etc/os-release
|
||||
fi
|
||||
|
||||
mv "${image}.verity" "${image}.fooverity"
|
||||
mv "${image}.roothash" "${image}.foohash"
|
||||
systemd-dissect --json=short "${image}.raw" --root-hash="${roothash}" --verity-data="${image}.fooverity" | grep -q -F '{"rw":"ro","designator":"root","partition_uuid":null,"partition_label":null,"fstype":"squashfs","architecture":null,"verity":"external"'
|
||||
|
Loading…
Reference in New Issue
Block a user