New upstream version 2022.6

This commit is contained in:
Simon McVittie committed 2022-10-14 19:30:33 +01:00
commit 46bfe6e238
79 files changed
+2679 -2141

No files matched your search

@@ -0,0 +1,35 @@
# Copyright (C) 2018 Red Hat, Inc.
# Copyright (C) 2022 Endless OS Foundation LLC
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see <https://www.gnu.org/licenses/>.
# See https://github.com/ostreedev/ostree/pull/2543 for background.
[Unit]
Description=Hold /boot Open for OSTree Finalize Staged Deployment
Documentation=man:ostree(1)
ConditionPathExists=/run/ostree-booted
DefaultDependencies=no
RequiresMountsFor=/sysroot /boot
After=local-fs.target
Before=basic.target final.target
[Service]
Type=exec
# This is explicitly run in the root namespace to ensure an automounted
# /boot doesn't time out since autofs doesn't handle mount namespaces.
#
# https://bugzilla.redhat.com/show_bug.cgi?id=2056090
ExecStart=+/usr/bin/ostree admin finalize-staged --hold
+5
View File
@@ -29,6 +29,11 @@ Before=basic.target final.target
After=systemd-journal-flush.service
Conflicts=final.target
# Start the hold unit and ensure it stays active throughout this
# service.
Wants=ostree-finalize-staged-hold.service
After=ostree-finalize-staged-hold.service
[Service]
Type=oneshot
RemainAfterExit=yes
+1 -1
View File
@@ -73,7 +73,7 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser *self,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (!self->parsed, FALSE);
g_assert (!self->parsed);
g_autofree char *contents = glnx_file_get_contents_utf8_at (dfd, path, NULL, cancellable, error);
if (!contents)
+88 -34
View File
@@ -20,6 +20,7 @@
#include "ostree-sysroot-private.h"
#include "ostree-bootloader-zipl.h"
#include "ostree-deployment-private.h"
#include "ostree-libarchive-private.h"
#include "otutil.h"
#include <sys/mount.h>
#include <sys/stat.h>
@@ -34,7 +35,10 @@
#define SECURE_EXECUTION_LUKS_ROOT_KEY "/etc/luks/root"
#define SECURE_EXECUTION_LUKS_BOOT_KEY "/etc/luks/boot"
#define SECURE_EXECUTION_LUKS_CONFIG "/etc/crypttab"
#define SECURE_EXECUTION_RAMDISK_TOOL PKGLIBEXECDIR "/s390x-se-luks-gencpio"
#if !(defined HAVE_LIBARCHIVE) && defined(__s390x__)
#error libarchive is required for s390x
#endif
/* This is specific to zipl today, but in the future we could also
* use it for the grub2-mkconfig case.
@@ -195,31 +199,86 @@ static gboolean
_ostree_secure_execution_luks_key_exists (void)
{
return (access(SECURE_EXECUTION_LUKS_CONFIG, F_OK) == 0 &&
(access(SECURE_EXECUTION_LUKS_ROOT_KEY, F_OK) == 0 || access(SECURE_EXECUTION_LUKS_BOOT_KEY, F_OK) == 0));
access(SECURE_EXECUTION_LUKS_ROOT_KEY, F_OK) == 0 &&
access(SECURE_EXECUTION_LUKS_BOOT_KEY, F_OK) == 0);
}
static gboolean
_ostree_secure_execution_enable_luks(const gchar *oldramfs,
const gchar *newramfs,
GError **error)
_ostree_secure_execution_append_luks_keys (int initrd_fd,
GCancellable *cancellable,
GError **error)
{
const char *const argv[] = {SECURE_EXECUTION_RAMDISK_TOOL, oldramfs, newramfs, NULL};
g_autofree gchar *out = NULL;
g_autofree gchar *err = NULL;
int status = 0;
if (!g_spawn_sync (NULL, (char**)argv, NULL, G_SPAWN_SEARCH_PATH,
NULL, NULL, &out, &err, &status, error))
return glnx_prefix_error(error, "s390x SE: spawning %s", SECURE_EXECUTION_RAMDISK_TOOL);
#ifdef HAVE_LIBARCHIVE
// appending cpio gzip archive with LUKS keys
g_autoptr(OtAutoArchiveWrite) a = archive_write_new ();
g_assert (a != NULL);
if (!g_spawn_check_exit_status (status, error))
if (archive_write_set_format_cpio_newc (a) != 0 ||
archive_write_add_filter_gzip (a) != 0 ||
archive_write_open_fd(a, initrd_fd) != 0)
return glnx_prefix_error (error, "s390x SE: initing cpio: %s", archive_error_string (a));
const char *files[] = {"/etc", "/etc/luks", SECURE_EXECUTION_LUKS_CONFIG, SECURE_EXECUTION_LUKS_BOOT_KEY, SECURE_EXECUTION_LUKS_ROOT_KEY};
for (uint i = 0; i != G_N_ELEMENTS (files); ++i)
{
g_printerr("s390x SE: `%s` stdout: %s\n", SECURE_EXECUTION_RAMDISK_TOOL, out);
g_printerr("s390x SE: `%s` stderr: %s\n", SECURE_EXECUTION_RAMDISK_TOOL, err);
return glnx_prefix_error(error, "s390x SE: `%s` failed", SECURE_EXECUTION_RAMDISK_TOOL);
}
const char *path = files[i];
struct stat st;
if (stat(path, &st) != 0)
glnx_throw_errno_prefix (error, "s390x SE: stat(%s) failed", path);
ot_journal_print(LOG_INFO, "s390x SE: luks key added to initrd");
g_autoptr(OtArchiveEntry) ae = archive_entry_new ();
g_assert (ae != NULL);
archive_entry_copy_stat (ae, &st);
archive_entry_set_pathname (ae, path);
if (archive_write_header (a, ae) != 0)
glnx_prefix_error (error, "s390x SE: writing cpio header: %s", archive_error_string (a));
if (S_ISREG (st.st_mode))
{
ot_journal_print(LOG_INFO, "s390x SE: appending %s to initrd", path);
glnx_autofd int fd = -1;
if (!glnx_openat_rdonly (AT_FDCWD, path, TRUE, &fd, error))
return glnx_prefix_error (error, "s390x SE: opening %s", path);
g_autoptr(GBytes) data = glnx_fd_readall_bytes (fd, cancellable, error);
if (!data)
return glnx_prefix_error (error, "s390x SE: reading %s", path);
gsize size = 0;
const char *ptr = (const char *) g_bytes_get_data (data, &size);
ssize_t written = archive_write_data (a, ptr, size);
if (written == -1)
return glnx_prefix_error (error, "s390x SE: writing cpio entry: %s", archive_error_string (a));
if (written != size)
return glnx_prefix_error (error, "s390x SE: writing cpio entry %zd != %zu", written, size);
}
}
ot_journal_print(LOG_INFO, "s390x SE: luks keys added to initrd");
return TRUE;
#else
return glnx_throw (error, "'libarchive' is required for s390x");
#endif
}
static gboolean
_ostree_secure_execution_generate_initrd (const gchar *initrd,
GLnxTmpfile *out_initrd,
GCancellable *cancellable,
GError **error)
{
if (!_ostree_secure_execution_luks_key_exists ())
return glnx_throw (error, "s390x SE: missing luks keys and config");
if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, out_initrd, error))
return glnx_prefix_error (error, "s390x SE: opening new ramdisk");
{
glnx_autofd int fd = -1;
glnx_openat_rdonly (AT_FDCWD, initrd, TRUE, &fd, error);
if (glnx_regfile_copy_bytes (fd, out_initrd->fd, (off_t) -1) < 0)
return glnx_throw_errno_prefix (error, "s390x SE: copying ramdisk");
}
return _ostree_secure_execution_append_luks_keys (out_initrd->fd, cancellable, error);
}
static gboolean
@@ -227,6 +286,7 @@ _ostree_secure_execution_generate_sdboot (gchar *vmlinuz,
gchar *initramfs,
gchar *options,
GPtrArray *keys,
GCancellable *cancellable,
GError **error)
{
g_assert (vmlinuz && initramfs && options && keys && keys->len);
@@ -234,34 +294,28 @@ _ostree_secure_execution_generate_sdboot (gchar *vmlinuz,
ot_journal_print(LOG_INFO, "s390x SE: initrd: %s", initramfs);
ot_journal_print(LOG_INFO, "s390x SE: kargs: %s", options);
pid_t self = getpid();
pid_t self = getpid ();
// Store kernel options to temp file, so `genprotimg` can later embed it
g_auto(GLnxTmpfile) cmdline = { 0, };
if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &cmdline, error))
return glnx_prefix_error(error, "s390x SE: opening cmdline file");
return glnx_prefix_error (error, "s390x SE: opening cmdline file");
if (glnx_loop_write (cmdline.fd, options, strlen (options)) < 0)
return glnx_throw_errno_prefix (error, "s390x SE: writting cmdline file");
return glnx_throw_errno_prefix (error, "s390x SE: writing cmdline file");
g_autofree gchar *cmdline_filename = g_strdup_printf ("/proc/%d/fd/%d", self, cmdline.fd);
// Copy initramfs to temp file and embed LUKS key and config into it
// Copy initramfs to temp file and embed LUKS keys & config into it
g_auto(GLnxTmpfile) ramdisk = { 0, };
g_autofree gchar *ramdisk_filename = NULL;
if (_ostree_secure_execution_luks_key_exists ())
{
if (!glnx_open_anonymous_tmpfile (O_RDWR | O_CLOEXEC, &ramdisk, error))
return glnx_prefix_error(error, "s390x SE: creating new ramdisk");
ramdisk_filename = g_strdup_printf ("/proc/%d/fd/%d", self, ramdisk.fd);
if (!_ostree_secure_execution_enable_luks (initramfs, ramdisk_filename, error))
return FALSE;
}
if (!_ostree_secure_execution_generate_initrd (initramfs, &ramdisk, cancellable, error))
return FALSE;
g_autofree gchar *ramdisk_filename = g_strdup_printf ("/proc/%d/fd/%d", self, ramdisk.fd);
g_autoptr(GPtrArray) argv = g_ptr_array_new ();
g_ptr_array_add (argv, "genprotimg");
g_ptr_array_add (argv, "-i");
g_ptr_array_add (argv, vmlinuz);
g_ptr_array_add (argv, "-r");
g_ptr_array_add (argv, (ramdisk_filename == NULL) ? initramfs: ramdisk_filename);
g_ptr_array_add (argv, ramdisk_filename);
g_ptr_array_add (argv, "-p");
g_ptr_array_add (argv, cmdline_filename);
for (guint i = 0; i < keys->len; ++i)
@@ -300,7 +354,7 @@ _ostree_secure_execution_call_zipl (GError **error)
if (!g_spawn_check_exit_status (status, error))
return glnx_prefix_error(error, "s390x SE: `zipl` failed");
ot_journal_print(LOG_INFO, "s390x SE: `sd-boot` zipled");
ot_journal_print(LOG_INFO, "s390x SE: `sdboot` zipled");
return TRUE;
}
@@ -318,7 +372,7 @@ _ostree_secure_execution_enable (OstreeBootloaderZipl *self,
gboolean rc =
_ostree_secure_execution_mount (error) &&
_ostree_secure_execution_get_bls_config (self, bootversion, &vmlinuz, &initramfs, &options, cancellable, error) &&
_ostree_secure_execution_generate_sdboot (vmlinuz, initramfs, options, keys, error) &&
_ostree_secure_execution_generate_sdboot (vmlinuz, initramfs, options, keys, cancellable, error) &&
_ostree_secure_execution_call_zipl (error) &&
_ostree_secure_execution_umount (error);
+5 -5
View File
@@ -31,7 +31,7 @@ _ostree_bootloader_query (OstreeBootloader *self,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
g_assert (OSTREE_IS_BOOTLOADER (self));
return OSTREE_BOOTLOADER_GET_IFACE (self)->query (self, out_is_active, cancellable, error);
}
@@ -44,7 +44,7 @@ _ostree_bootloader_query (OstreeBootloader *self,
const char *
_ostree_bootloader_get_name (OstreeBootloader *self)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), NULL);
g_assert (OSTREE_IS_BOOTLOADER (self));
return OSTREE_BOOTLOADER_GET_IFACE (self)->get_name (self);
}
@@ -56,7 +56,7 @@ _ostree_bootloader_write_config (OstreeBootloader *self,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
g_assert (OSTREE_IS_BOOTLOADER (self));
return OSTREE_BOOTLOADER_GET_IFACE (self)->write_config (self, bootversion,
new_deployments,
@@ -69,7 +69,7 @@ _ostree_bootloader_post_bls_sync (OstreeBootloader *self,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
g_assert (OSTREE_IS_BOOTLOADER (self));
if (OSTREE_BOOTLOADER_GET_IFACE (self)->post_bls_sync)
return OSTREE_BOOTLOADER_GET_IFACE (self)->post_bls_sync (self, bootversion, cancellable, error);
@@ -80,7 +80,7 @@ _ostree_bootloader_post_bls_sync (OstreeBootloader *self,
gboolean
_ostree_bootloader_is_atomic (OstreeBootloader *self)
{
g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
g_assert (OSTREE_IS_BOOTLOADER (self));
if (OSTREE_BOOTLOADER_GET_IFACE (self)->is_atomic)
return OSTREE_BOOTLOADER_GET_IFACE (self)->is_atomic (self);
+4 -2
View File
@@ -882,8 +882,10 @@ initiate_next_curl_request (FetcherRequest *req,
if (!(self->config_flags & OSTREE_FETCHER_FLAGS_DISABLE_HTTP2))
{
#if CURL_AT_LEAST_VERSION(7, 51, 0)
rc = curl_easy_setopt (req->easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
g_assert_cmpint (rc, ==, CURLM_OK);
if ((curl_version_info (CURLVERSION_NOW))->features & CURL_VERSION_HTTP2) {
rc = curl_easy_setopt (req->easy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2_0);
g_assert_cmpint (rc, ==, CURLM_OK);
}
#endif
/* https://github.com/curl/curl/blob/curl-7_53_0/docs/examples/http2-download.c */
#if (CURLPIPE_MULTIPLEX > 0)
@@ -38,6 +38,8 @@ G_BEGIN_DECLS
#ifdef HAVE_LIBARCHIVE
typedef struct archive OtAutoArchiveWrite;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OtAutoArchiveWrite, archive_write_free)
typedef struct archive_entry OtArchiveEntry;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OtArchiveEntry, archive_entry_free)
typedef struct archive OtAutoArchiveRead;
G_DEFINE_AUTOPTR_CLEANUP_FUNC(OtAutoArchiveRead, archive_read_free)
+22 -2
View File
@@ -24,10 +24,12 @@
#include <fcntl.h>
#include <sys/ioctl.h>
// This should be the only file including linux/fs.h; see
// https://sourceware.org/glibc/wiki/Release/2.36#Usage_of_.3Clinux.2Fmount.h.3E_and_.3Csys.2Fmount.h.3E
// https://github.com/ostreedev/ostree/issues/2685
#include <linux/fs.h>
#include <ext2fs/ext2_fs.h>
#include "otutil.h"
/**
* _ostree_linuxfs_fd_alter_immutable_flag:
* @fd: A file descriptor
@@ -88,3 +90,21 @@ _ostree_linuxfs_fd_alter_immutable_flag (int fd,
return TRUE;
}
/* Wrapper for FIFREEZE ioctl.
* This is split into a separate wrapped API for
* reasons around conflicts between glibc and linux/fs.h
* includes; see above.
*/
int
_ostree_linuxfs_filesystem_freeze (int fd)
{
return TEMP_FAILURE_RETRY (ioctl (fd, FIFREEZE, 0));
}
/* Wrapper for FITHAW ioctl. See above. */
int
_ostree_linuxfs_filesystem_thaw (int fd)
{
return TEMP_FAILURE_RETRY (ioctl (fd, FITHAW, 0));
}
+3
View File
@@ -29,4 +29,7 @@ _ostree_linuxfs_fd_alter_immutable_flag (int fd,
GCancellable *cancellable,
GError **error);
int _ostree_linuxfs_filesystem_freeze (int fd);
int _ostree_linuxfs_filesystem_thaw (int fd);
G_END_DECLS
-6
View File
@@ -303,8 +303,6 @@ ostree_mutable_tree_replace_file (OstreeMutableTree *self,
const char *checksum,
GError **error)
{
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
return FALSE;
@@ -338,8 +336,6 @@ ostree_mutable_tree_remove (OstreeMutableTree *self,
gboolean allow_noent,
GError **error)
{
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
return FALSE;
@@ -374,8 +370,6 @@ ostree_mutable_tree_ensure_dir (OstreeMutableTree *self,
OstreeMutableTree **out_subdir,
GError **error)
{
g_return_val_if_fail (name != NULL, FALSE);
if (!ot_util_filename_validate (name, error))
return FALSE;
+128 -1
View File
@@ -35,6 +35,8 @@
#define WHITEOUT_PREFIX ".wh."
#define OPAQUE_WHITEOUT_NAME ".wh..wh..opq"
#define OVERLAYFS_WHITEOUT_PREFIX ".ostree-wh."
/* Per-checkout call state/caching */
typedef struct {
GString *path_buf; /* buffer for real path if filtering enabled */
@@ -582,6 +584,117 @@ checkout_file_hardlink (OstreeRepo *self,
return TRUE;
}
static gboolean
_checkout_overlayfs_whiteout_at_no_overwrite (OstreeRepoCheckoutAtOptions *options,
int destination_dfd,
const char *destination_name,
GFileInfo *file_info,
GVariant *xattrs,
gboolean *found_exant_file,
GCancellable *cancellable,
GError **error)
{
if (found_exant_file != NULL)
*found_exant_file = FALSE;
guint32 file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
if (mknodat(destination_dfd, destination_name, (file_mode & ~S_IFMT) | S_IFCHR, (dev_t)0) < 0)
{
if (errno == EEXIST && found_exant_file != NULL)
{
*found_exant_file = TRUE;
return TRUE;
}
return glnx_throw_errno_prefix (error, "Creating whiteout char device");
}
if (options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
{
if (xattrs != NULL &&
!glnx_dfd_name_set_all_xattrs(destination_dfd, destination_name, xattrs,
cancellable, error))
return glnx_throw_errno_prefix (error, "Setting xattrs for whiteout char device");
if (TEMP_FAILURE_RETRY(fchownat(destination_dfd, destination_name,
g_file_info_get_attribute_uint32 (file_info, "unix::uid"),
g_file_info_get_attribute_uint32 (file_info, "unix::gid"),
AT_SYMLINK_NOFOLLOW) < 0))
return glnx_throw_errno_prefix (error, "fchownat");
if (TEMP_FAILURE_RETRY (fchmodat (destination_dfd, destination_name, file_mode & ~S_IFMT, 0)) < 0)
return glnx_throw_errno_prefix (error, "fchmodat %s to 0%o", destination_name, file_mode & ~S_IFMT);
}
return TRUE;
}
static gboolean
_checkout_overlayfs_whiteout_at (OstreeRepo *repo,
OstreeRepoCheckoutAtOptions *options,
int destination_dfd,
const char *destination_name,
GFileInfo *file_info,
GVariant *xattrs,
GCancellable *cancellable,
GError **error)
{
gboolean found_exant_file = FALSE;
if (!_checkout_overlayfs_whiteout_at_no_overwrite(options, destination_dfd, destination_name,
file_info, xattrs,&found_exant_file,
cancellable, error))
return FALSE;
if (!found_exant_file)
return TRUE;
guint32 uid = g_file_info_get_attribute_uint32 (file_info, "unix::uid");
guint32 gid = g_file_info_get_attribute_uint32 (file_info, "unix::gid");
guint32 file_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode");
struct stat dest_stbuf;
switch(options->overwrite_mode)
{
case OSTREE_REPO_CHECKOUT_OVERWRITE_NONE:
return FALSE;
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES:
if (!ot_ensure_unlinked_at (destination_dfd, destination_name, error))
return FALSE;
return _checkout_overlayfs_whiteout_at_no_overwrite(options, destination_dfd, destination_name,
file_info, xattrs, NULL, cancellable, error);
case OSTREE_REPO_CHECKOUT_OVERWRITE_ADD_FILES:
return TRUE;
case OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL:
if (!glnx_fstatat(destination_dfd, destination_name, &dest_stbuf, AT_SYMLINK_NOFOLLOW,
error))
return FALSE;
if (!(repo->disable_xattrs || repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY))
{
g_autoptr(GVariant) fs_xattrs;
if (!glnx_dfd_name_get_all_xattrs (destination_dfd, destination_name,
&fs_xattrs, cancellable, error))
return FALSE;
if (!g_variant_equal(fs_xattrs, xattrs))
return glnx_throw(error, "existing destination file %s xattrs don't match",
destination_name);
}
if (options->mode != OSTREE_REPO_CHECKOUT_MODE_USER)
{
if (gid != dest_stbuf.st_gid)
return glnx_throw(error, "existing destination file %s does not match gid %d",
destination_name, gid);
if (uid != dest_stbuf.st_uid)
return glnx_throw(error, "existing destination file %s does not match uid %d",
destination_name, gid);
if ((file_mode & ALLPERMS) != (dest_stbuf.st_mode & ALLPERMS))
return glnx_throw(error, "existing destination file %s does not match mode %o",
destination_name, file_mode);
}
break;
}
return TRUE;
}
static gboolean
checkout_one_file_at (OstreeRepo *repo,
OstreeRepoCheckoutAtOptions *options,
@@ -603,7 +716,8 @@ checkout_one_file_at (OstreeRepo *repo,
/* FIXME - avoid the GFileInfo here */
g_autoptr(GFileInfo) source_info = NULL;
if (!ostree_repo_load_file (repo, checksum, NULL, &source_info, NULL,
g_autoptr(GVariant) source_xattrs = NULL;
if (!ostree_repo_load_file (repo, checksum, NULL, &source_info, &source_xattrs,
cancellable, error))
return FALSE;
@@ -623,6 +737,7 @@ checkout_one_file_at (OstreeRepo *repo,
const gboolean is_unreadable = (!is_symlink && (source_mode & S_IRUSR) == 0);
const gboolean is_whiteout = (!is_symlink && options->process_whiteouts &&
g_str_has_prefix (destination_name, WHITEOUT_PREFIX));
const gboolean is_overlayfs_whiteout = (!is_symlink && g_str_has_prefix (destination_name, OVERLAYFS_WHITEOUT_PREFIX));
const gboolean is_reg_zerosized = (!is_symlink && g_file_info_get_size (source_info) == 0);
const gboolean override_user_unreadable = (options->mode == OSTREE_REPO_CHECKOUT_MODE_USER && is_unreadable);
@@ -643,6 +758,18 @@ checkout_one_file_at (OstreeRepo *repo,
need_copy = FALSE;
}
else if (is_overlayfs_whiteout && options->process_passthrough_whiteouts)
{
const char *name = destination_name + (sizeof (OVERLAYFS_WHITEOUT_PREFIX) - 1);
if (!name[0])
return glnx_throw (error, "Invalid empty overlayfs whiteout '%s'", name);
g_assert (name[0] != '/'); /* Sanity */
return _checkout_overlayfs_whiteout_at(repo, options, destination_dfd, name,
source_info, source_xattrs, cancellable, error);
}
else if (is_reg_zerosized || override_user_unreadable)
{
/* In https://github.com/ostreedev/ostree/commit/673cacd633f9d6b653cdea530657d3e780a41bbd we
+3 -7
View File
@@ -30,7 +30,6 @@
#include <sys/xattr.h>
#include <glib/gprintf.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <ext2fs/ext2_fs.h>
#include "otutil.h"
@@ -882,11 +881,8 @@ _try_clone_from_payload_link (OstreeRepo *self,
else
{
/* This undoes all of the previous writes; we want to generate reflinked data. */
if (ftruncate (tmpf->fd, 0) < 0)
return glnx_throw_errno_prefix (error, "ftruncate");
if (glnx_regfile_copy_bytes (fdf, tmpf->fd, -1) < 0)
return glnx_throw_errno_prefix (error, "regfile copy");
if (ioctl (tmpf->fd, FICLONE, fdf) < 0)
return glnx_throw_errno_prefix (error, "FICLONE");
return TRUE;
}
@@ -1749,7 +1745,7 @@ ostree_repo_prepare_transaction (OstreeRepo *self,
return FALSE;
/* Success: do not abort the transaction when returning. */
txn->repo = NULL; (void) txn;
g_clear_object (&txn->repo); (void) txn;
if (out_transaction_resume)
*out_transaction_resume = ret_transaction_resume;
+1 -1
View File
@@ -3680,7 +3680,7 @@ all_requested_refs_have_commit (GHashTable *requested_refs /* (element-type Ostr
* * `override-commit-ids` (`as`): Array of specific commit IDs to fetch for refs
* * `timestamp-check` (`b`): Verify commit timestamps are newer than current (when pulling via ref); Since: 2017.11
* * `timestamp-check-from-rev` (`s`): Verify that all fetched commit timestamps are newer than timestamp of given rev; Since: 2020.4
* * `metadata-size-restriction` (`t`): Restrict metadata objects to a maximum number of bytes; 0 to disable. Since: 2018.9
* * `max-metadata-size` (`t`): Restrict metadata objects to a maximum number of bytes; 0 to disable. Since: 2018.9
* * `dry-run` (`b`): Only print information on what will be downloaded (requires static deltas)
* * `override-url` (`s`): Fetch objects from this URL if remote specifies no metalink in options
* * `inherit-transaction` (`b`): Don't initiate, finish or abort a transaction, useful to do multiple pulls in one transaction.
@@ -1369,7 +1369,6 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
g_autoptr(GPtrArray) builder_parts = g_ptr_array_new_with_free_func ((GDestroyNotify)ostree_static_delta_part_builder_unref);
g_autoptr(GPtrArray) builder_fallback_objects = g_ptr_array_new_with_free_func ((GDestroyNotify)g_variant_unref);
g_auto(GLnxTmpfile) descriptor_tmpf = { 0, };
g_autoptr(OtVariantBuilder) descriptor_builder = NULL;
const char *opt_sign_name;
const char **opt_key_ids;
@@ -1456,7 +1455,10 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
&descriptor_tmpf, error))
return FALSE;
descriptor_builder = ot_variant_builder_new (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT), descriptor_tmpf.fd);
g_autoptr(OtVariantBuilder) descriptor_builder =
ot_variant_builder_new (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT),
descriptor_tmpf.fd);
g_assert (descriptor_builder != NULL);
/* Open the metadata dict */
if (!ot_variant_builder_open (descriptor_builder, G_VARIANT_TYPE ("a{sv}"), error))
@@ -1603,7 +1605,6 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
const gchar *signature_key = NULL;
g_autoptr(GVariantBuilder) signature_builder = NULL;
g_auto(GLnxTmpfile) descriptor_sign_tmpf = { 0, };
g_autoptr(OtVariantBuilder) descriptor_sign_builder = NULL;
lseek (descriptor_tmpf.fd, 0, SEEK_SET);
tmpdata = glnx_fd_readall_bytes (descriptor_tmpf.fd, cancellable, error);
@@ -1640,8 +1641,10 @@ ostree_repo_static_delta_generate (OstreeRepo *self,
&descriptor_sign_tmpf, error))
return FALSE;
descriptor_sign_builder = ot_variant_builder_new (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SIGNED_FORMAT),
descriptor_sign_tmpf.fd);
g_autoptr(OtVariantBuilder) descriptor_sign_builder =
ot_variant_builder_new (G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SIGNED_FORMAT),
descriptor_sign_tmpf.fd);
g_assert (descriptor_sign_builder != NULL);
if (!ot_variant_builder_add (descriptor_sign_builder, error, "t",
GUINT64_TO_BE (OSTREE_STATIC_DELTA_SIGNED_MAGIC)))
+1 -1
View File
@@ -3514,7 +3514,7 @@ reload_sysroot_config (OstreeRepo *self,
* https://github.com/ostreedev/ostree/issues/1719
* https://github.com/ostreedev/ostree/issues/1801
*/
gboolean valid_bootloader;
gboolean valid_bootloader = FALSE;
for (int i = 0; CFG_SYSROOT_BOOTLOADER_OPTS_STR[i]; i++)
{
if (g_str_equal (bootloader, CFG_SYSROOT_BOOTLOADER_OPTS_STR[i]))
+3 -2
View File
@@ -989,8 +989,9 @@ typedef struct {
gboolean force_copy; /* Since: 2017.6 */
gboolean bareuseronly_dirs; /* Since: 2017.7 */
gboolean force_copy_zerosized; /* Since: 2018.9 */
gboolean unused_bools[4];
/* 4 byte hole on 64 bit */
gboolean process_passthrough_whiteouts;
gboolean unused_bools[3];
/* 3 byte hole on 64 bit */
const char *subpath;
+41 -19
View File
@@ -96,8 +96,11 @@ ostree_sign_default_init (OstreeSignInterface *iface)
const gchar *
ostree_sign_metadata_key (OstreeSign *self)
{
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->metadata_key == NULL)
return NULL;
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_key != NULL, NULL);
return OSTREE_SIGN_GET_IFACE (self)->metadata_key (self);
}
@@ -116,8 +119,11 @@ ostree_sign_metadata_key (OstreeSign *self)
const gchar *
ostree_sign_metadata_format (OstreeSign *self)
{
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->metadata_format == NULL)
return NULL;
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->metadata_format != NULL, NULL);
return OSTREE_SIGN_GET_IFACE (self)->metadata_format (self);
}
@@ -136,7 +142,8 @@ gboolean
ostree_sign_clear_keys (OstreeSign *self,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->clear_keys == NULL)
return glnx_throw (error, "not implemented");
@@ -163,7 +170,8 @@ ostree_sign_set_sk (OstreeSign *self,
GVariant *secret_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->set_sk == NULL)
return glnx_throw (error, "not implemented");
@@ -191,7 +199,8 @@ ostree_sign_set_pk (OstreeSign *self,
GVariant *public_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->set_pk == NULL)
return glnx_throw (error, "not implemented");
@@ -219,7 +228,8 @@ ostree_sign_add_pk (OstreeSign *self,
GVariant *public_key,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->add_pk == NULL)
return glnx_throw (error, "not implemented");
@@ -258,7 +268,8 @@ ostree_sign_load_pk (OstreeSign *self,
GVariant *options,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->load_pk == NULL)
return glnx_throw (error, "not implemented");
@@ -290,8 +301,8 @@ ostree_sign_data (OstreeSign *self,
GCancellable *cancellable,
GError **error)
{
g_assert (OSTREE_IS_SIGN (self));
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
if (OSTREE_SIGN_GET_IFACE (self)->data == NULL)
return glnx_throw (error, "not implemented");
@@ -324,7 +335,8 @@ ostree_sign_data_verify (OstreeSign *self,
char **out_success_message,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (OSTREE_SIGN_GET_IFACE (self)->data_verify == NULL)
return glnx_throw (error, "not implemented");
@@ -337,9 +349,13 @@ ostree_sign_data_verify (OstreeSign *self,
static GVariant *
_sign_detached_metadata_append (OstreeSign *self,
GVariant *existing_metadata,
GBytes *signature_bytes)
GBytes *signature_bytes,
GError **error)
{
g_return_val_if_fail (signature_bytes != NULL, FALSE);
g_assert (OSTREE_IS_SIGN (self));
if (signature_bytes == NULL)
return glnx_null_throw (error, "Invalid NULL signature bytes");
GVariantDict metadata_dict;
g_autoptr(GVariant) signature_data = NULL;
@@ -395,7 +411,7 @@ ostree_sign_commit_verify (OstreeSign *self,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_assert (OSTREE_IS_SIGN (self));
g_autoptr(GVariant) commit_variant = NULL;
/* Load the commit */
@@ -447,10 +463,12 @@ ostree_sign_commit_verify (OstreeSign *self,
const gchar *
ostree_sign_get_name (OstreeSign *self)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), NULL);
g_return_val_if_fail (OSTREE_SIGN_GET_IFACE (self)->get_name != NULL, NULL);
g_assert (OSTREE_IS_SIGN (self));
return OSTREE_SIGN_GET_IFACE (self)->get_name (self);
if (OSTREE_SIGN_GET_IFACE (self)->get_name == NULL)
return NULL;
return OSTREE_SIGN_GET_IFACE (self)->get_name (self);
}
/**
@@ -503,7 +521,9 @@ ostree_sign_commit (OstreeSign *self,
return glnx_prefix_error (error, "Not able to sign the cobject");
new_metadata =
_sign_detached_metadata_append (self, old_metadata, signature);
_sign_detached_metadata_append (self, old_metadata, signature, error);
if (new_metadata == NULL)
return FALSE;
if (!ostree_repo_write_commit_detached_metadata (repo,
commit_checksum,
@@ -603,8 +623,8 @@ ostree_sign_summary (OstreeSign *self,
GCancellable *cancellable,
GError **error)
{
g_return_val_if_fail (OSTREE_IS_SIGN (self), FALSE);
g_return_val_if_fail (OSTREE_IS_REPO (repo), FALSE);
g_assert (OSTREE_IS_SIGN (self));
g_assert (OSTREE_IS_REPO (repo));
g_autoptr(GVariant) normalized = NULL;
g_autoptr(GBytes) summary_data = NULL;
@@ -653,7 +673,9 @@ ostree_sign_summary (OstreeSign *self,
g_autoptr(GVariant) old_metadata = g_steal_pointer (&metadata);
metadata =
_sign_detached_metadata_append (self, old_metadata, signature);
_sign_detached_metadata_append (self, old_metadata, signature, error);
if (metadata == NULL)
return FALSE;
}
g_variant_iter_free (iter);
+54 -25
View File
@@ -29,7 +29,6 @@
#include <sys/ioctl.h>
#include <stdbool.h>
#include <sys/poll.h>
#include <linux/fs.h>
#include <err.h>
#ifdef HAVE_LIBMOUNT
@@ -642,7 +641,7 @@ checkout_deployment_tree (OstreeSysroot *sysroot,
return FALSE;
/* Generate hardlink farm, then opendir it */
OstreeRepoCheckoutAtOptions checkout_opts = { 0, };
OstreeRepoCheckoutAtOptions checkout_opts = { .process_passthrough_whiteouts = TRUE };
if (!ostree_repo_checkout_at (repo, &checkout_opts, osdeploy_dfd,
checkout_target_name, csum,
cancellable, error))
@@ -1476,7 +1475,7 @@ fsfreeze_thaw_cycle (OstreeSysroot *self,
* EOPNOTSUPP: If the filesystem doesn't support it
*/
int saved_errno = errno;
(void) TEMP_FAILURE_RETRY (ioctl (rootfs_dfd, FITHAW, 0));
_ostree_linuxfs_filesystem_thaw (rootfs_dfd);
errno = saved_errno;
/* But if we got an error from poll, let's log it */
if (r < 0)
@@ -1517,7 +1516,7 @@ fsfreeze_thaw_cycle (OstreeSysroot *self,
return glnx_throw (error, "aborting due to test-fifreeze");
}
/* Do a freeze/thaw cycle; TODO add a FIFREEZETHAW ioctl */
if (ioctl (rootfs_dfd, FIFREEZE, 0) != 0)
if (_ostree_linuxfs_filesystem_freeze (rootfs_dfd) != 0)
{
/* Not supported, we're running in the unit tests (as non-root), or
* the filesystem is already frozen (EBUSY).
@@ -1539,7 +1538,7 @@ fsfreeze_thaw_cycle (OstreeSysroot *self,
return glnx_throw_errno_prefix (error, "ioctl(FIFREEZE)");
}
/* And finally thaw, then signal our completion to the watchdog */
if (TEMP_FAILURE_RETRY (ioctl (rootfs_dfd, FITHAW, 0)) != 0)
if (_ostree_linuxfs_filesystem_thaw (rootfs_dfd) != 0)
{
/* Warn but don't error if the filesystem was already thawed */
if (errno == EINVAL)
@@ -2006,7 +2005,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
&variant, NULL))
{
metadata = g_variant_get_child_value (variant, 0);
g_variant_lookup (metadata, OSTREE_COMMIT_META_KEY_VERSION, "s", &deployment_version);
(void) g_variant_lookup (metadata, OSTREE_COMMIT_META_KEY_VERSION, "s", &deployment_version);
}
}
@@ -2233,7 +2232,7 @@ get_deployment_ostree_version (OstreeRepo *repo,
if (ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT, csum, &variant, NULL))
{
g_autoptr(GVariant) metadata = g_variant_get_child_value (variant, 0);
g_variant_lookup (metadata, OSTREE_COMMIT_META_KEY_VERSION, "s", &version);
(void) g_variant_lookup (metadata, OSTREE_COMMIT_META_KEY_VERSION, "s", &version);
}
return g_steal_pointer (&version);
@@ -3595,7 +3594,7 @@ ostree_sysroot_deployment_set_kargs (OstreeSysroot *self,
* ostree_sysroot_deployment_set_kargs_in_place:
* @self: Sysroot
* @deployment: A deployment
* @kargs_str: (allow none): Replace @deployment's kernel arguments
* @kargs_str: (allow-none): Replace @deployment's kernel arguments
* @cancellable: Cancellable
* @error: Error
*
@@ -3615,25 +3614,55 @@ ostree_sysroot_deployment_set_kargs_in_place (OstreeSysroot *self,
if (!_ostree_sysroot_ensure_writable (self, error))
return FALSE;
g_assert (!ostree_deployment_is_staged (deployment));
// handle staged deployment
if (ostree_deployment_is_staged (deployment))
{
/* Read the staged state from disk */
glnx_autofd int fd = -1;
if (!glnx_openat_rdonly (AT_FDCWD, _OSTREE_SYSROOT_RUNSTATE_STAGED, TRUE, &fd, error))
return FALSE;
OstreeBootconfigParser *new_bootconfig = ostree_deployment_get_bootconfig (deployment);
ostree_bootconfig_parser_set (new_bootconfig, "options", kargs_str);
g_autofree char *bootconf_name =
g_strdup_printf ("ostree-%d-%s.conf",
self->deployments->len - ostree_deployment_get_index (deployment),
ostree_deployment_get_osname (deployment));
g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", self->bootversion);
glnx_autofd int bootconf_dfd = -1;
if (!glnx_opendirat (self->boot_fd, bootconfdir, TRUE, &bootconf_dfd, error))
return FALSE;
if (!ostree_bootconfig_parser_write_at (new_bootconfig,
bootconf_dfd, bootconf_name,
g_autoptr(GBytes) contents = ot_fd_readall_or_mmap (fd, 0, error);
if (!contents)
return FALSE;
g_autoptr(GVariant) staged_deployment_data =
g_variant_new_from_bytes ((GVariantType*)"a{sv}", contents, TRUE);
g_autoptr(GVariantDict) staged_deployment_dict =
g_variant_dict_new (staged_deployment_data);
g_autoptr(OstreeKernelArgs) kargs = ostree_kernel_args_from_string (kargs_str);
g_auto(GStrv) kargs_strv = ostree_kernel_args_to_strv (kargs);
g_variant_dict_insert (staged_deployment_dict, "kargs", "^a&s", kargs_strv);
g_autoptr(GVariant) new_staged_deployment_data = g_variant_dict_end (staged_deployment_dict);
if (!glnx_file_replace_contents_at (fd, _OSTREE_SYSROOT_RUNSTATE_STAGED,
g_variant_get_data (new_staged_deployment_data),
g_variant_get_size (new_staged_deployment_data),
GLNX_FILE_REPLACE_NODATASYNC,
cancellable, error))
return FALSE;
return FALSE;
}
else
{
OstreeBootconfigParser *new_bootconfig = ostree_deployment_get_bootconfig (deployment);
ostree_bootconfig_parser_set (new_bootconfig, "options", kargs_str);
g_autofree char *bootconf_name =
g_strdup_printf ("ostree-%d-%s.conf",
self->deployments->len - ostree_deployment_get_index (deployment),
ostree_deployment_get_osname (deployment));
g_autofree char *bootconfdir = g_strdup_printf ("loader.%d/entries", self->bootversion);
glnx_autofd int bootconf_dfd = -1;
if (!glnx_opendirat (self->boot_fd, bootconfdir, TRUE, &bootconf_dfd, error))
return FALSE;
if (!ostree_bootconfig_parser_write_at (new_bootconfig,
bootconf_dfd, bootconf_name,
cancellable, error))
return FALSE;
}
return TRUE;
}
+4 -4
View File
@@ -41,7 +41,7 @@
*
* Since: 2017.4
*/
#define OSTREE_RELEASE_VERSION (5)
#define OSTREE_RELEASE_VERSION (6)
/**
* OSTREE_VERSION
@@ -50,7 +50,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION (2022.5)
#define OSTREE_VERSION (2022.6)
/**
* OSTREE_VERSION_S:
@@ -60,7 +60,7 @@
*
* Since: 2017.4
*/
#define OSTREE_VERSION_S "2022.5"
#define OSTREE_VERSION_S "2022.6"
#define OSTREE_ENCODE_VERSION(year,release) \
((year) << 16 | (release))
@@ -99,5 +99,5 @@
* Since: 2019.3
*/
#ifndef __GI_SCANNER__
#define OSTREE_BUILT_FEATURES "libsoup gpgme ex-fsverity libarchive selinux libmount systemd release p2p"
#define OSTREE_BUILT_FEATURES "libsoup gpgme ex-fsverity libarchive selinux avahi libmount systemd release p2p"
#endif
-22
View File
@@ -1,22 +0,0 @@
#!/bin/bash
# This script creates new initramdisk with LUKS config within
set -euo pipefail
old_initrd=$1
new_initrd=$2
currdir=$PWD
# Copying existing initramdisk
cp ${old_initrd} ${new_initrd}
# Appending LUKS root keys and crypttab config to the end of initrd
workdir=$(mktemp -d -p /tmp se-initramfs-XXXXXX)
cd ${workdir}
mkdir -p etc/luks
cp -f /etc/luks/* etc/luks/
cp -f /etc/crypttab etc/
find . -mindepth 1 | cpio --quiet -H newc -o | gzip -9 -n >> ${new_initrd}
# Cleanup
cd ${currdir}
rm -rf ${workdir}
+7 -10
View File
@@ -758,11 +758,9 @@ struct _OtVariantBuilder {
static OtVariantBuilderInfo *
ot_variant_builder_info_new (OtVariantBuilder *builder, const GVariantType *type)
{
OtVariantBuilderInfo *info;
g_assert (g_variant_type_is_container (type));
g_return_val_if_fail (g_variant_type_is_container (type), NULL);
info = (OtVariantBuilderInfo *) g_slice_new0 (OtVariantBuilderInfo);
OtVariantBuilderInfo *info = (OtVariantBuilderInfo *) g_slice_new0 (OtVariantBuilderInfo);
info->builder = builder;
info->type = g_variant_type_copy (type);
@@ -843,11 +841,9 @@ OtVariantBuilder *
ot_variant_builder_new (const GVariantType *type,
int fd)
{
OtVariantBuilder *builder;
g_assert (g_variant_type_is_container (type));
g_return_val_if_fail (g_variant_type_is_container (type), NULL);
builder = (OtVariantBuilder *) g_slice_new0 (OtVariantBuilder);
OtVariantBuilder *builder = (OtVariantBuilder *) g_slice_new0 (OtVariantBuilder);
builder->head = ot_variant_builder_info_new (builder, type);
builder->ref_count = 1;
@@ -1083,7 +1079,6 @@ ot_variant_builder_open (OtVariantBuilder *builder,
GError **error)
{
OtVariantBuilderInfo *info = builder->head;
OtVariantBuilderInfo *new_info;
g_assert (info->n_children < info->max_items);
g_assert (!info->expected_type ||
@@ -1096,7 +1091,9 @@ ot_variant_builder_open (OtVariantBuilder *builder,
if (!ot_variant_builder_pre_add (info, type, error))
return FALSE;
new_info = ot_variant_builder_info_new (builder, type);
OtVariantBuilderInfo *new_info = ot_variant_builder_info_new (builder, type);
g_assert (new_info != NULL);
new_info->parent = info;
/* push the prev_item_type down into the subcontainer */
+49 -5
View File
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2018 Red Hat, Inc.
* Copyright (C) 2022 Endless OS Foundation LLC
*
* SPDX-License-Identifier: LGPL-2.0+
*
@@ -19,8 +20,9 @@
#include "config.h"
#include "config.h"
#include <glib-unix.h>
#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include "ot-main.h"
@@ -32,7 +34,10 @@
#include "ostree-cmd-private.h"
#include "ostree.h"
static gboolean opt_hold;
static GOptionEntry options[] = {
{ "hold", 0, 0, G_OPTION_ARG_NONE, &opt_hold, "Hold /boot open during finalization", NULL },
{ NULL }
};
@@ -50,13 +55,52 @@ ot_admin_builtin_finalize_staged (int argc, char **argv, OstreeCommandInvocation
g_autoptr(GOptionContext) context = g_option_context_new ("");
g_autoptr(OstreeSysroot) sysroot = NULL;
/* First parse the args without loading the sysroot to see what options are
* set. */
if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,
OSTREE_ADMIN_BUILTIN_FLAG_NO_LOAD,
invocation, &sysroot, cancellable, error))
return FALSE;
if (!ostree_cmd__private__()->ostree_finalize_staged (sysroot, cancellable, error))
return FALSE;
if (opt_hold)
{
/* Load the sysroot unlocked so that a separate namespace isn't
* created. */
if (!ostree_admin_sysroot_load (sysroot,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
cancellable, error))
return FALSE;
/* In case it's an automount, open /boot so that the automount doesn't
* expire until before this process exits. If it did expire and got
* unmounted, the service would be stopped and the deployment would be
* finalized earlier than expected.
*/
int sysroot_fd = ostree_sysroot_get_fd (sysroot);
glnx_autofd int boot_fd = -1;
g_debug ("Opening /boot directory");
if (!glnx_opendirat (sysroot_fd, "boot", TRUE, &boot_fd, error))
return FALSE;
/* We want to keep /boot open until the deployment is finalized during
* system shutdown, so block until we get SIGTERM which systemd will send
* when the unit is stopped.
*/
pause ();
}
else
{
/* Load the sysroot with the normal flags and actually finalize the
* deployment. */
if (!ostree_admin_sysroot_load (sysroot,
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER,
cancellable, error))
return FALSE;
if (!ostree_cmd__private__()->ostree_finalize_staged (sysroot, cancellable, error))
return FALSE;
}
return TRUE;
}
+6 -1
View File
@@ -37,6 +37,7 @@ static gboolean opt_union;
static gboolean opt_union_add;
static gboolean opt_union_identical;
static gboolean opt_whiteouts;
static gboolean opt_process_passthrough_whiteouts;
static gboolean opt_from_stdin;
static char *opt_from_file;
static gboolean opt_disable_fsync;
@@ -77,6 +78,7 @@ static GOptionEntry options[] = {
{ "union-add", 0, 0, G_OPTION_ARG_NONE, &opt_union_add, "Keep existing files/directories, only add new", NULL },
{ "union-identical", 0, 0, G_OPTION_ARG_NONE, &opt_union_identical, "When layering checkouts, error out if a file would be replaced with a different version, but add new files and directories", NULL },
{ "whiteouts", 0, 0, G_OPTION_ARG_NONE, &opt_whiteouts, "Process 'whiteout' (Docker style) entries", NULL },
{ "process-passthrough-whiteouts", 0, 0, G_OPTION_ARG_NONE, &opt_process_passthrough_whiteouts, "Enable overlayfs whiteout extraction into char 0:0 devices", NULL },
{ "allow-noent", 0, 0, G_OPTION_ARG_NONE, &opt_allow_noent, "Do nothing if specified path does not exist", NULL },
{ "from-stdin", 0, 0, G_OPTION_ARG_NONE, &opt_from_stdin, "Process many checkouts from standard input", NULL },
{ "from-file", 0, 0, G_OPTION_ARG_STRING, &opt_from_file, "Process many checkouts from input file", "FILE" },
@@ -129,7 +131,8 @@ process_one_checkout (OstreeRepo *repo,
if (opt_disable_cache || opt_whiteouts || opt_require_hardlinks ||
opt_union_add || opt_force_copy || opt_force_copy_zerosized ||
opt_bareuseronly_dirs || opt_union_identical ||
opt_skiplist_file || opt_selinux_policy || opt_selinux_prefix)
opt_skiplist_file || opt_selinux_policy || opt_selinux_prefix ||
opt_process_passthrough_whiteouts)
{
OstreeRepoCheckoutAtOptions checkout_options = { 0, };
@@ -162,6 +165,8 @@ process_one_checkout (OstreeRepo *repo,
}
if (opt_whiteouts)
checkout_options.process_whiteouts = TRUE;
if (opt_process_passthrough_whiteouts)
checkout_options.process_passthrough_whiteouts = TRUE;
if (subpath)
checkout_options.subpath = subpath;
+44 -18
View File
@@ -25,47 +25,73 @@
#include "ot-builtins.h"
#include "ostree.h"
#include "otutil.h"
#include <stdbool.h>
/* ATTENTION:
* Please remember to update the bash-completion script (bash/ostree) and
* man page (man/ostree-rev-parse.xml) when changing the option list.
*/
static gboolean opt_single;
static GOptionEntry options[] = {
{ "single", 'S', 0, G_OPTION_ARG_NONE, &opt_single, "If the repository has exactly one commit, then print it; any other case will result in an error", NULL },
{ NULL }
};
gboolean
ostree_builtin_rev_parse (int argc, char **argv, OstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error)
{
g_autoptr(GOptionContext) context = NULL;
g_autoptr(GOptionContext) context = g_option_context_new ("REV");
g_autoptr(OstreeRepo) repo = NULL;
gboolean ret = FALSE;
const char *rev = "master";
int i;
g_autofree char *resolved_rev = NULL;
context = g_option_context_new ("REV");
if (!ostree_option_context_parse (context, options, &argc, &argv, invocation, &repo, cancellable, error))
goto out;
return FALSE;
if (opt_single)
{
if (argc >= 2)
{
ot_util_usage_error (context, "Cannot specify arguments with --single", error);
return FALSE;
}
g_autoptr(GHashTable) objects = NULL;
if (!ostree_repo_list_commit_objects_starting_with (repo, "", &objects, cancellable, error))
return FALSE;
GVariant *found = NULL;
GLNX_HASH_TABLE_FOREACH (objects, GVariant*, key)
{
if (found)
return glnx_throw (error, "Multiple commit objects found");
found = key;
}
if (!found)
return glnx_throw (error, "No commit objects found");
const char *checksum;
OstreeObjectType objtype;
ostree_object_name_deserialize (found, &checksum, &objtype);
g_assert (objtype == OSTREE_OBJECT_TYPE_COMMIT);
g_print ("%s\n", checksum);
return TRUE; /* Note early return */
}
if (argc < 2)
{
ot_util_usage_error (context, "REV must be specified", error);
goto out;
return FALSE;
}
for (i = 1; i < argc; i++)
for (gint i = 1; i < argc; i++)
{
rev = argv[i];
g_free (resolved_rev);
resolved_rev = NULL;
const char *rev = argv[i];
g_autofree char *resolved_rev = NULL;
if (!ostree_repo_resolve_rev (repo, rev, FALSE, &resolved_rev, error))
goto out;
return FALSE;
g_print ("%s\n", resolved_rev);
}
ret = TRUE;
out:
return ret;
return TRUE;
}
+49 -35
View File
@@ -28,7 +28,6 @@
#include <string.h>
#include <sys/statvfs.h>
#include <sys/mount.h>
#include <linux/fs.h>
#include "ot-main.h"
#include "ostree.h"
@@ -580,41 +579,11 @@ on_sysroot_journal_msg (OstreeSysroot *sysroot,
}
gboolean
ostree_admin_option_context_parse (GOptionContext *context,
const GOptionEntry *main_entries,
int *argc,
char ***argv,
OstreeAdminBuiltinFlags flags,
OstreeCommandInvocation *invocation,
OstreeSysroot **out_sysroot,
GCancellable *cancellable,
GError **error)
ostree_admin_sysroot_load (OstreeSysroot *sysroot,
OstreeAdminBuiltinFlags flags,
GCancellable *cancellable,
GError **error)
{
/* Entries are listed in --help output in the order added. We add the
* main entries ourselves so that we can add the --sysroot entry first. */
g_option_context_add_main_entries (context, global_admin_entries, NULL);
if (!ostree_option_context_parse (context, main_entries, argc, argv,
invocation, NULL, cancellable, error))
return FALSE;
if (!opt_print_current_dir && (flags & OSTREE_ADMIN_BUILTIN_FLAG_NO_SYSROOT))
{
g_assert_null (out_sysroot);
/* Early return if no sysroot is requested */
return TRUE;
}
g_autoptr(GFile) sysroot_path = NULL;
if (opt_sysroot != NULL)
sysroot_path = g_file_new_for_path (opt_sysroot);
g_autoptr(OstreeSysroot) sysroot = ostree_sysroot_new (sysroot_path);
if (!ostree_sysroot_initialize (sysroot, error))
return FALSE;
g_signal_connect (sysroot, "journal-msg", G_CALLBACK (on_sysroot_journal_msg), NULL);
if ((flags & OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED) == 0)
{
/* If we're requested to lock the sysroot, first check if we're operating
@@ -658,6 +627,51 @@ ostree_admin_option_context_parse (GOptionContext *context,
}
}
return TRUE;
}
gboolean
ostree_admin_option_context_parse (GOptionContext *context,
const GOptionEntry *main_entries,
int *argc,
char ***argv,
OstreeAdminBuiltinFlags flags,
OstreeCommandInvocation *invocation,
OstreeSysroot **out_sysroot,
GCancellable *cancellable,
GError **error)
{
/* Entries are listed in --help output in the order added. We add the
* main entries ourselves so that we can add the --sysroot entry first. */
g_option_context_add_main_entries (context, global_admin_entries, NULL);
if (!ostree_option_context_parse (context, main_entries, argc, argv,
invocation, NULL, cancellable, error))
return FALSE;
if (!opt_print_current_dir && (flags & OSTREE_ADMIN_BUILTIN_FLAG_NO_SYSROOT))
{
g_assert_null (out_sysroot);
/* Early return if no sysroot is requested */
return TRUE;
}
g_autoptr(GFile) sysroot_path = NULL;
if (opt_sysroot != NULL)
sysroot_path = g_file_new_for_path (opt_sysroot);
g_autoptr(OstreeSysroot) sysroot = ostree_sysroot_new (sysroot_path);
if (!ostree_sysroot_initialize (sysroot, error))
return FALSE;
g_signal_connect (sysroot, "journal-msg", G_CALLBACK (on_sysroot_journal_msg), NULL);
if (opt_print_current_dir || (flags & OSTREE_ADMIN_BUILTIN_FLAG_NO_LOAD) == 0)
{
if (!ostree_admin_sysroot_load (sysroot, flags, cancellable, error))
return FALSE;
}
if (opt_print_current_dir)
{
g_autoptr(GPtrArray) deployments = NULL;
+6
View File
@@ -36,6 +36,7 @@ typedef enum {
OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER = (1 << 0),
OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED = (1 << 1),
OSTREE_ADMIN_BUILTIN_FLAG_NO_SYSROOT = (1 << 2),
OSTREE_ADMIN_BUILTIN_FLAG_NO_LOAD = (1 << 3),
} OstreeAdminBuiltinFlags;
@@ -91,6 +92,11 @@ gboolean ostree_admin_option_context_parse (GOptionContext *context,
OstreeSysroot **out_sysroot,
GCancellable *cancellable, GError **error);
gboolean ostree_admin_sysroot_load (OstreeSysroot *sysroot,
OstreeAdminBuiltinFlags flags,
GCancellable *cancellable,
GError **error);
gboolean ostree_ensure_repo_writable (OstreeRepo *repo, GError **error);
void ostree_print_gpg_verify_result (OstreeGpgVerifyResult *result);