diff --git a/Makefile-ostree.am b/Makefile-ostree.am index d2447ffe9d..5b511c23b4 100644 --- a/Makefile-ostree.am +++ b/Makefile-ostree.am @@ -76,6 +76,7 @@ ostree_SOURCES += \ src/ostree/ot-admin-builtin-set-default.c \ src/ostree/ot-admin-builtin-instutil.c \ src/ostree/ot-admin-builtin-kargs.c \ + src/ostree/ot-admin-builtin-metadata.c \ src/ostree/ot-admin-builtin-cleanup.c \ src/ostree/ot-admin-builtin-os-init.c \ src/ostree/ot-admin-builtin-set-origin.c \ diff --git a/src/libostree/ostree-deployment.c b/src/libostree/ostree-deployment.c index 8be2fdd507..3ec238024b 100644 --- a/src/libostree/ostree-deployment.c +++ b/src/libostree/ostree-deployment.c @@ -18,6 +18,7 @@ #include "config.h" #include "ostree-deployment-private.h" +#include "ostree-sysroot-private.h" #include "ostree.h" #include "otutil.h" @@ -476,3 +477,60 @@ ostree_deployment_is_finalization_locked (OstreeDeployment *self) { return self->finalization_locked; } + +/** + * ostree_deployment_set_ext_metadata: + * @self: Deployment + * @metadata_key: extended attribute(metadata) name/key to add. + * @metadata_value: extended attribute(metadata) value to add. + * @error: a #GError + * + */ +gboolean +ostree_deployment_set_ext_metadata (OstreeDeployment *self, const char *metadata_key, const char *metadata_value, GError **error) +{ + g_autofree char *backing_relpath = _ostree_sysroot_get_deployment_backing_relpath (self); + if (setxattr (backing_relpath, metadata_key, metadata_value, strlen(metadata_value), 0) < 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to set deployment metadata %s on %s: %s", metadata_key, backing_relpath, + g_strerror (errno)); + return FALSE; + } + return TRUE; +} + +/** + * ostree_deployment_get_ext_metadata: + * @self: Deployment + * @metadata_key: (nullable): key of extended attribute + * @error: a #GError + * Returns: The value of a extended attribute(metadata) checksum given the key. + */ +const char * +ostree_deployment_get_ext_metadata (OstreeDeployment *self, const char *metadata_key, GError **error) +{ + g_autofree char *backing_relpath = _ostree_sysroot_get_deployment_backing_relpath (self); + g_autofree char *metadata_value = NULL; + g_autofree int len = getxattr (backing_relpath, metadata_key, NULL, 0); + if (len < 0) + { + if (errno == ENODATA) + return NULL; + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to get deployment metadata %s on %s: %s", metadata_key, backing_relpath, + g_strerror (errno)); + return NULL; + } + metadata_value = g_malloc (len + 1); + len = getxattr (backing_relpath, metadata_key, metadata_value, len); + if (len < 0) + { + g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), + "Failed to get deployment metadata %s on %s: %s", metadata_key, backing_relpath, + g_strerror (errno)); + return NULL; + } + metadata_value[len] = '\0'; + return metadata_value; +} diff --git a/src/libostree/ostree-deployment.h b/src/libostree/ostree-deployment.h index 0536d9810c..6dfb72cc39 100644 --- a/src/libostree/ostree-deployment.h +++ b/src/libostree/ostree-deployment.h @@ -107,4 +107,13 @@ const char *ostree_deployment_unlocked_state_to_string (OstreeDeploymentUnlocked _OSTREE_PUBLIC OstreeDeploymentUnlockedState ostree_deployment_get_unlocked (OstreeDeployment *self); + +_OSTREE_PUBLIC +gboolean ostree_deployment_set_ext_metadata (OstreeDeployment *self, const char *metadata_key, + const char *metadata_value, GError **error); + +_OSTREE_PUBLIC +const char *ostree_deployment_get_ext_metadata (OstreeDeployment *self, const char *metadata_key, + GError **error); + G_END_DECLS diff --git a/src/ostree/ot-admin-builtin-metadata.c b/src/ostree/ot-admin-builtin-metadata.c new file mode 100644 index 0000000000..734702e806 --- /dev/null +++ b/src/ostree/ot-admin-builtin-metadata.c @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2015 Colin Walters + * + * SPDX-License-Identifier: LGPL-2.0+ + * + * 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 . + */ + +#include "config.h" + +#include "ot-admin-builtins.h" +#include "ot-admin-functions.h" +#include "otutil.h" + +static char **opt_set; +static char **opt_get; + +static GOptionEntry options[] + = { { "set", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_set, + "Set deployment metadata, like DATE=030424; this overrides any metadata with the " + "same name", + "KEY=VALUE" }, + { "get", 0, 0, G_OPTION_ARG_STRING_ARRAY, &opt_get, + "Get the value of a deployment metadata.", "KEY" }, + { NULL } }; + +gboolean +ot_admin_builtin_metadata (int argc, char **argv, OstreeCommandInvocation *invocation, + GCancellable *cancellable, GError **error) +{ + gboolean ret = FALSE; + g_autoptr (GPtrArray) deployments = NULL; + OstreeDeployment *first_deployment = NULL; + g_autoptr (GOptionContext) context = NULL; + g_autoptr (OstreeSysroot) sysroot = NULL; + + if (!ostree_admin_option_context_parse (context, options, &argc, &argv, + OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER, invocation, &sysroot, + cancellable, error)) + goto out; + + if (deployments->len == 0) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unable to find a deployment in sysroot"); + goto out; + } + + first_deployment = deployments->pdata[0]; + + if (opt_set) + { + char *key = strtok(*opt_set, "="); + char *value = strtok(NULL, "="); + // ^^ This needs error checking and probably is wrong... but builds! + ostree_deployment_set_ext_metadata(first_deployment, key, value, error); + } + + if (opt_get) + { + ostree_deployment_get_ext_metadata (first_deployment, *opt_get, error); + } + + ret = TRUE; +out: + return ret; +} diff --git a/src/ostree/ot-admin-builtins.h b/src/ostree/ot-admin-builtins.h index cd1472bf3d..b4a623a508 100644 --- a/src/ostree/ot-admin-builtins.h +++ b/src/ostree/ot-admin-builtins.h @@ -51,6 +51,7 @@ BUILTINPROTO (kargs); BUILTINPROTO (post_copy); BUILTINPROTO (lock_finalization); BUILTINPROTO (state_overlay); +BUILTINPROTO (metadata); #undef BUILTINPROTO diff --git a/src/ostree/ot-builtin-admin.c b/src/ostree/ot-builtin-admin.c index 53face6a2d..23da6a26eb 100644 --- a/src/ostree/ot-builtin-admin.c +++ b/src/ostree/ot-builtin-admin.c @@ -70,6 +70,8 @@ static OstreeCommand admin_subcommands[] = { { "upgrade", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_upgrade, "Construct new tree from current origin and deploy it, if it changed" }, { "kargs", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_kargs, "Change kernel arguments" }, + { "deployment-metadata", OSTREE_BUILTIN_FLAG_NO_REPO, ot_admin_builtin_metadata, + "Set extended metadata for current the deployment" }, { NULL, 0, NULL, NULL } };