From c4cb926419353daf34e0bef75994ddf5197e23cd Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Tue, 22 Dec 2020 14:22:51 +0000 Subject: [PATCH] Finish removing `ex container` code This should have been deleted in commit: bee9c0f60566d8abb00a77a659d46eb19befd23b Notice it wasn't listed in the Makefiles anymore, so it's dead. --- src/app/rpmostree-container-builtins.c | 490 ------------------------- src/app/rpmostree-container-builtins.h | 35 -- 2 files changed, 525 deletions(-) delete mode 100644 src/app/rpmostree-container-builtins.c delete mode 100644 src/app/rpmostree-container-builtins.h diff --git a/src/app/rpmostree-container-builtins.c b/src/app/rpmostree-container-builtins.c deleted file mode 100644 index bf0e0d6b..00000000 --- a/src/app/rpmostree-container-builtins.c +++ /dev/null @@ -1,490 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2015,2016 Colin Walters - * - * This program 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 licence 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, write to the - * Free Software Foundation, Inc., 59 Temple Place, Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include -#include - -#include "rpmostree-container-builtins.h" -#include "rpmostree-util.h" -#include "rpmostree-core.h" -#include "rpmostree-libbuiltin.h" -#include "rpmostree-postprocess.h" -#include "rpmostree-rpm-util.h" - -#include "libglnx.h" - - -static GOptionEntry init_option_entries[] = { - { NULL } -}; - -static gboolean opt_cache_only; - -static GOptionEntry assemble_option_entries[] = { - { "cache-only", 'C', 0, G_OPTION_ARG_NONE, &opt_cache_only, "Assume cache is present, do not attempt to update it", NULL }, - { NULL } -}; - -typedef struct { - int userroot_dfd; - - int roots_dfd; - OstreeRepo *repo; - RpmOstreeContext *ctx; - - int rpmmd_dfd; -} ROContainerContext; - -#define RO_CONTAINER_CONTEXT_INIT { .userroot_dfd = -1, .roots_dfd = -1, .rpmmd_dfd = -1 } - -static gboolean -roc_context_init_core (ROContainerContext *rocctx, - GError **error) -{ - if (!glnx_opendirat (AT_FDCWD, ".", TRUE, &rocctx->userroot_dfd, error)) - return FALSE; - - return TRUE; -} - -static gboolean -roc_context_init (ROContainerContext *rocctx, - GError **error) -{ - if (!roc_context_init_core (rocctx, error)) - return FALSE; - - rocctx->repo = ostree_repo_open_at (rocctx->userroot_dfd, "repo", NULL, error); - if (!rocctx->repo) - return FALSE; - - OstreeRepoMode mode = ostree_repo_get_mode (rocctx->repo); - if (mode != OSTREE_REPO_MODE_BARE_USER_ONLY) - return glnx_throw (error, "container repos are now required to be in bare-user-only mode"); - - if (!glnx_opendirat (rocctx->userroot_dfd, "roots", TRUE, &rocctx->roots_dfd, error)) - return FALSE; - - if (!glnx_opendirat (rocctx->userroot_dfd, "cache/rpm-md", FALSE, &rocctx->rpmmd_dfd, error)) - return FALSE; - - return TRUE; -} - -static gboolean -roc_context_prepare_for_root (ROContainerContext *rocctx, - RpmOstreeTreespec *treespec, - GCancellable *cancellable, - GError **error) -{ - rocctx->ctx = rpmostree_context_new_tree (rocctx->userroot_dfd, rocctx->repo, - cancellable, error); - if (!rocctx->ctx) - return FALSE; - - if (!rpmostree_context_setup (rocctx->ctx, NULL, NULL, treespec, cancellable, error)) - return FALSE; - - return TRUE; -} - -static void -roc_context_deinit (ROContainerContext *rocctx) -{ - glnx_close_fd (&rocctx->userroot_dfd); - g_clear_object (&rocctx->repo); - glnx_close_fd (&rocctx->roots_dfd); - glnx_close_fd (&rocctx->rpmmd_dfd); - g_clear_object (&rocctx->ctx); -} - -G_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(ROContainerContext, roc_context_deinit) - -int -rpmostree_container_builtin_init (int argc, - char **argv, - RpmOstreeCommandInvocation *invocation, - GCancellable *cancellable, - GError **error) -{ - g_auto(ROContainerContext) rocctx_data = RO_CONTAINER_CONTEXT_INIT; - ROContainerContext *rocctx = &rocctx_data; - g_autoptr(GOptionContext) context = g_option_context_new (""); - - if (!rpmostree_option_context_parse (context, - init_option_entries, - &argc, &argv, - invocation, - cancellable, - NULL, NULL, NULL, NULL, NULL, - error)) - return FALSE; - - if (!roc_context_init_core (rocctx, error)) - return FALSE; - - static const char* const directories[] = { "repo", "rpmmd.repos.d", "cache/rpm-md", "roots", "tmp" }; - for (guint i = 0; i < G_N_ELEMENTS (directories); i++) - { - if (!glnx_shutil_mkdir_p_at (rocctx->userroot_dfd, directories[i], 0755, cancellable, error)) - return FALSE; - } - - rocctx->repo = ostree_repo_create_at (rocctx->userroot_dfd, "repo", - OSTREE_REPO_MODE_BARE_USER_ONLY, NULL, - cancellable, error); - if (!rocctx->repo) - return FALSE; - - return TRUE; -} - -/* - * Like symlinkat() but overwrites (atomically) an existing - * symlink. - */ -static gboolean -symlink_at_replace (const char *oldpath, - int parent_dfd, - const char *newpath, - GCancellable *cancellable, - GError **error) -{ - /* Possibly in the future generate a temporary random name here, - * would need to move "generate a temporary name" code into - * libglnx or glib? - */ - const char *temppath = glnx_strjoina (newpath, ".tmp"); - - /* Clean up any stale temporary links */ - (void) unlinkat (parent_dfd, temppath, 0); - - /* Create the temp link */ - if (TEMP_FAILURE_RETRY (symlinkat (oldpath, parent_dfd, temppath)) < 0) - return glnx_throw_errno_prefix (error, "symlinkat(%s)", temppath); - - /* Rename it into place */ - if (!glnx_renameat (parent_dfd, temppath, parent_dfd, newpath, error)) - return FALSE; - - return TRUE; -} - -/* Download and import rpms, then generate a rootfs, and commit it */ -static gboolean -download_rpms_and_assemble_commit (ROContainerContext *rocctx, - char **out_commit, - GCancellable *cancellable, - GError **error) -{ - /* --- Download as necessary --- */ - if (!rpmostree_context_download (rocctx->ctx, cancellable, error)) - return FALSE; - - /* --- Import as necessary --- */ - if (!rpmostree_context_import (rocctx->ctx, cancellable, error)) - return FALSE; - - if (!rpmostree_context_assemble (rocctx->ctx, cancellable, error)) - return FALSE; - - if (!rpmostree_rootfs_postprocess_common (rpmostree_context_get_tmprootfs_dfd (rocctx->ctx), - cancellable, error)) - return FALSE; - - g_autofree char *ret_commit = NULL; - if (!rpmostree_context_commit (rocctx->ctx, NULL, RPMOSTREE_ASSEMBLE_TYPE_SERVER_BASE, - &ret_commit, cancellable, error)) - return FALSE; - - *out_commit = g_steal_pointer (&ret_commit); - return TRUE; -} - -int -rpmostree_container_builtin_assemble (int argc, - char **argv, - RpmOstreeCommandInvocation *invocation, - GCancellable *cancellable, - GError **error) -{ - g_autoptr(GOptionContext) context = g_option_context_new ("NAME [PKGNAME PKGNAME...]"); - g_auto(ROContainerContext) rocctx_data = RO_CONTAINER_CONTEXT_INIT; - ROContainerContext *rocctx = &rocctx_data; - - if (!rpmostree_option_context_parse (context, - assemble_option_entries, - &argc, &argv, - invocation, - cancellable, - NULL, NULL, NULL, NULL, NULL, - error)) - return FALSE; - - if (argc < 1) - { - rpmostree_usage_error (context, "SPEC must be specified", error); - return FALSE; - } - - const char *specpath = argv[1]; - g_autoptr(RpmOstreeTreespec) treespec = rpmostree_treespec_new_from_path (specpath, error); - if (!treespec) - return FALSE; - - const char *name = rpmostree_treespec_get_ref (treespec); - if (name == NULL) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Missing ref in treespec"); - return FALSE; - } - - if (!roc_context_init (rocctx, error)) - return FALSE; - - const char *target_rootdir = glnx_strjoina (name, ".0"); - - if (!glnx_fstatat_allow_noent (rocctx->roots_dfd, target_rootdir, NULL, - AT_SYMLINK_NOFOLLOW, error)) - { - glnx_set_error_from_errno (error); - return FALSE; - } - if (errno == 0) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Tree %s already exists", target_rootdir); - return FALSE; - } - - if (!roc_context_prepare_for_root (rocctx, treespec, cancellable, error)) - return FALSE; - - DnfContext *dnfctx = rpmostree_context_get_dnf (rocctx->ctx); - if (opt_cache_only) - dnf_context_set_cache_age (dnfctx, G_MAXUINT); - - /* --- Resolving dependencies --- */ - if (!rpmostree_context_prepare (rocctx->ctx, cancellable, error)) - return FALSE; - - rpmostree_print_transaction (rpmostree_context_get_dnf (rocctx->ctx)); - - g_autofree char *commit = NULL; - if (!download_rpms_and_assemble_commit (rocctx, &commit, cancellable, error)) - return FALSE; - g_print ("Checking out %s @ %s...\n", name, commit); - - { OstreeRepoCheckoutAtOptions opts = { OSTREE_REPO_CHECKOUT_MODE_USER, - OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES, }; - - /* Also, what we really want here is some sort of sane lifecycle - * management with whatever is running in the root. - */ - if (!glnx_shutil_rm_rf_at (rocctx->roots_dfd, target_rootdir, cancellable, error)) - return FALSE; - - if (!ostree_repo_checkout_at (rocctx->repo, &opts, rocctx->roots_dfd, target_rootdir, - commit, cancellable, error)) - return FALSE; - } - - g_print ("Checking out %s @ %s...done\n", name, commit); - - if (!symlink_at_replace (target_rootdir, rocctx->roots_dfd, name, - cancellable, error)) - return FALSE; - - g_print ("Creating current symlink...done\n"); - - return TRUE; -} - -#define APP_VERSION_REGEXP ".+\\.([01])" - -static gboolean -parse_app_version (const char *name, - guint *out_version, - GError **error) -{ - g_autoptr(GMatchInfo) match = NULL; - static gsize regex_initialized; - static GRegex *regex; - int ret_version; - - if (g_once_init_enter (®ex_initialized)) - { - regex = g_regex_new (APP_VERSION_REGEXP, 0, 0, NULL); - g_assert (regex); - g_once_init_leave (®ex_initialized, 1); - } - - if (!g_regex_match (regex, name, 0, &match)) - return glnx_throw (error, "Invalid app link %s", name); - - { g_autofree char *version_str = g_match_info_fetch (match, 1); - ret_version = g_ascii_strtoull (version_str, NULL, 10); - - switch (ret_version) - { - case 0: - case 1: - break; - default: - return glnx_throw (error, "Invalid version in app link %s", name); - } - } - - *out_version = ret_version; - return TRUE; -} - -gboolean -rpmostree_container_builtin_upgrade (int argc, char **argv, - RpmOstreeCommandInvocation *invocation, - GCancellable *cancellable, GError **error) -{ - g_autoptr(GOptionContext) context = g_option_context_new ("NAME"); - g_auto(ROContainerContext) rocctx_data = RO_CONTAINER_CONTEXT_INIT; - ROContainerContext *rocctx = &rocctx_data; - - if (!rpmostree_option_context_parse (context, - assemble_option_entries, - &argc, &argv, - invocation, - cancellable, - NULL, NULL, NULL, NULL, NULL, - error)) - return FALSE; - - if (argc < 1) - { - rpmostree_usage_error (context, "NAME must be specified", error); - return FALSE; - } - - const char *name = argv[1]; - - if (!roc_context_init (rocctx, error)) - return FALSE; - - g_autofree char *target_current_root = glnx_readlinkat_malloc (rocctx->roots_dfd, name, cancellable, error); - if (!target_current_root) - { - g_prefix_error (error, "Reading app link %s: ", name); - return FALSE; - } - - guint current_version = 2; - if (!parse_app_version (target_current_root, ¤t_version, error)) - return FALSE; - g_assert_cmpuint (current_version, <, 2); - - g_autofree char *commit_checksum = NULL; - g_autofree char *previous_state_sha512 = NULL; - g_autoptr(GVariant) metadata = NULL; - g_autoptr(RpmOstreeTreespec) treespec = NULL; - { if (!ostree_repo_resolve_rev (rocctx->repo, name, FALSE, &commit_checksum, error)) - return FALSE; - - g_autoptr(GVariant) commit = NULL; - if (!ostree_repo_load_variant (rocctx->repo, OSTREE_OBJECT_TYPE_COMMIT, commit_checksum, - &commit, error)) - return FALSE; - - metadata = g_variant_get_child_value (commit, 0); - g_autoptr(GVariantDict) metadata_dict = g_variant_dict_new (metadata); - - g_autoptr(GVariant) spec_v = - _rpmostree_vardict_lookup_value_required (metadata_dict, "rpmostree.spec", - (GVariantType*)"a{sv}", error); - if (!spec_v) - return FALSE; - - treespec = rpmostree_treespec_new (spec_v); - g_autoptr(GVariant) previous_sha512_v = - _rpmostree_vardict_lookup_value_required (metadata_dict, "rpmostree.state-sha512", - (GVariantType*)"s", error); - if (!previous_sha512_v) - return FALSE; - - previous_state_sha512 = g_variant_dup_string (previous_sha512_v, NULL); - } - - guint new_version = (current_version == 0 ? 1 : 0); - const char *target_new_root; - if (new_version == 0) - target_new_root = glnx_strjoina (name, ".0"); - else - target_new_root = glnx_strjoina (name, ".1"); - - if (!roc_context_prepare_for_root (rocctx, treespec, cancellable, error)) - return FALSE; - - if (!rpmostree_context_prepare (rocctx->ctx, cancellable, error)) - return FALSE; - - rpmostree_print_transaction (rpmostree_context_get_dnf (rocctx->ctx)); - - { - g_autofree char *new_state_sha512 = NULL; - if (!rpmostree_context_get_state_sha512 (rocctx->ctx, &new_state_sha512, error)) - return FALSE; - - if (strcmp (new_state_sha512, previous_state_sha512) == 0) - { - g_print ("No changes in inputs to %s (%s)\n", name, commit_checksum); - /* Note early return */ - return TRUE; - } - } - - g_autofree char *new_commit_checksum = NULL; - if (!download_rpms_and_assemble_commit (rocctx, &new_commit_checksum, cancellable, error)) - return FALSE; - - g_print ("Checking out %s @ %s...\n", name, new_commit_checksum); - - { OstreeRepoCheckoutAtOptions opts = { OSTREE_REPO_CHECKOUT_MODE_USER, - OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_FILES, }; - - if (!ostree_repo_checkout_at (rocctx->repo, &opts, rocctx->roots_dfd, target_new_root, - new_commit_checksum, cancellable, error)) - return FALSE; - } - - g_print ("Checking out %s @ %s...done\n", name, new_commit_checksum); - - if (!symlink_at_replace (target_new_root, rocctx->roots_dfd, name, - cancellable, error)) - return FALSE; - - g_print ("Creating current symlink...done\n"); - - return TRUE; -} diff --git a/src/app/rpmostree-container-builtins.h b/src/app/rpmostree-container-builtins.h deleted file mode 100644 index a7c0f2f1..00000000 --- a/src/app/rpmostree-container-builtins.h +++ /dev/null @@ -1,35 +0,0 @@ -/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- - * - * Copyright (C) 2016 Colin Walters - * - * 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, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#pragma once - -#include - -#include "rpmostree-builtins.h" - -G_BEGIN_DECLS - -gboolean rpmostree_container_builtin_init (int argc, char **argv, RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error); -gboolean rpmostree_container_builtin_assemble (int argc, char **argv, RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error); -/* gboolean rpmostree_container_builtin_start (int argc, char **argv, RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error); */ -gboolean rpmostree_container_builtin_upgrade (int argc, char **argv, RpmOstreeCommandInvocation *invocation, GCancellable *cancellable, GError **error); - -G_END_DECLS -