libostree: Nearly complete move of API into OstreeSysroot

Move the deployment code too.
This commit is contained in:
Colin Walters 2013-09-15 20:16:20 -04:00
parent 95f07d486a
commit c6292942ff
17 changed files with 399 additions and 542 deletions

View File

@ -46,6 +46,7 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-sysroot-private.h \
src/libostree/ostree-sysroot.c \
src/libostree/ostree-sysroot-cleanup.c \
src/libostree/ostree-sysroot-deploy.c \
src/libostree/ostree-bootconfig-parser.c \
src/libostree/ostree-deployment.c \
src/libostree/ostree-bootloader.c \
@ -53,6 +54,8 @@ libostree_1_la_SOURCES = \
src/libostree/ostree-bootloader-syslinux.c \
src/libostree/ostree-bootloader-uboot.h \
src/libostree/ostree-bootloader-uboot.c \
src/libostree/ostree-ordered-hash.h \
src/libostree/ostree-ordered-hash.c \
$(NULL)
if USE_LIBARCHIVE
libostree_1_la_SOURCES += src/libostree/ostree-libarchive-input-stream.h \

View File

@ -59,13 +59,8 @@ ostree_SOURCES += \
src/ostree/ot-admin-builtin-status.c \
src/ostree/ot-admin-builtin-upgrade.c \
src/ostree/ot-admin-builtins.h \
src/ostree/ot-admin-util.c \
src/ostree/ot-admin-functions.h \
src/ostree/ot-admin-functions.c \
src/ostree/ot-admin-deploy.h \
src/ostree/ot-admin-deploy.c \
src/ostree/ot-ordered-hash.h \
src/ostree/ot-ordered-hash.c \
$(NULL)
ostree_bin_shared_cflags = $(AM_CFLAGS) -I$(srcdir)/src/libgsystem -I$(srcdir)/src/libotutil -I$(srcdir)/src/libostree -I$(srcdir)/src/ostree -DLOCALEDIR=\"$(datadir)/locale\"

View File

@ -20,21 +20,21 @@
#include "config.h"
#include "ot-ordered-hash.h"
#include "ostree-ordered-hash.h"
#include "libgsystem.h"
OtOrderedHash *
ot_ordered_hash_new (void)
OstreeOrderedHash *
_ostree_ordered_hash_new (void)
{
OtOrderedHash *ret;
ret = g_new0 (OtOrderedHash, 1);
OstreeOrderedHash *ret;
ret = g_new0 (OstreeOrderedHash, 1);
ret->order = g_ptr_array_new_with_free_func (g_free);
ret->table = g_hash_table_new (g_str_hash, g_str_equal);
return ret;
}
void
ot_ordered_hash_free (OtOrderedHash *ohash)
_ostree_ordered_hash_free (OstreeOrderedHash *ohash)
{
if (!ohash)
return;
@ -44,13 +44,13 @@ ot_ordered_hash_free (OtOrderedHash *ohash)
}
void
ot_ordered_hash_cleanup (void *loc)
_ostree_ordered_hash_cleanup (void *loc)
{
ot_ordered_hash_free (*((OtOrderedHash**)loc));
_ostree_ordered_hash_free (*((OstreeOrderedHash**)loc));
}
void
ot_ordered_hash_replace_key_take (OtOrderedHash *ohash,
_ostree_ordered_hash_replace_key_take (OstreeOrderedHash *ohash,
char *key,
const char *value)
{
@ -63,7 +63,7 @@ ot_ordered_hash_replace_key_take (OtOrderedHash *ohash,
}
void
ot_ordered_hash_replace_key (OtOrderedHash *ohash,
_ostree_ordered_hash_replace_key (OstreeOrderedHash *ohash,
const char *key,
const char *val)
{
@ -79,5 +79,5 @@ ot_ordered_hash_replace_key (OtOrderedHash *ohash,
valblock = g_string_free (buf, FALSE);
valp = valblock + keylen + 1;
ot_ordered_hash_replace_key_take (ohash, valblock, valp);
_ostree_ordered_hash_replace_key_take (ohash, valblock, valp);
}

View File

@ -27,17 +27,17 @@ G_BEGIN_DECLS
typedef struct {
GPtrArray *order;
GHashTable *table;
} OtOrderedHash;
} OstreeOrderedHash;
OtOrderedHash *ot_ordered_hash_new (void);
void ot_ordered_hash_free (OtOrderedHash *ohash);
void ot_ordered_hash_cleanup (void *loc);
void ot_ordered_hash_replace_key_take (OtOrderedHash *ohash,
char *key,
const char *value);
void ot_ordered_hash_replace_key (OtOrderedHash *ohash,
const char *key,
const char *val);
OstreeOrderedHash *_ostree_ordered_hash_new (void);
void _ostree_ordered_hash_free (OstreeOrderedHash *ohash);
void _ostree_ordered_hash_cleanup (void *loc);
void _ostree_ordered_hash_replace_key_take (OstreeOrderedHash *ohash,
char *key,
const char *value);
void _ostree_ordered_hash_replace_key (OstreeOrderedHash *ohash,
const char *key,
const char *val);
G_END_DECLS

View File

@ -22,13 +22,10 @@
#include "config.h"
#include "ot-admin-functions.h"
#include "ot-admin-deploy.h"
#include "ostree-sysroot-private.h"
#include "otutil.h"
#include "ostree-core.h"
#include "libgsystem.h"
/**
* copy_one_config_file:
*
@ -197,7 +194,7 @@ merge_etc_changes (GFile *orig_etc,
* /ostree/deploy/OS/deploy/${treecsum}.${deployserial}.
*/
static gboolean
checkout_deployment_tree (GFile *sysroot,
checkout_deployment_tree (OstreeSysroot *sysroot,
OstreeRepo *repo,
OstreeDeployment *deployment,
GFile **out_deployment_path,
@ -222,7 +219,7 @@ checkout_deployment_tree (GFile *sysroot,
if (!file_info)
goto out;
osdeploy_path = ot_gfile_get_child_build_path (sysroot, "ostree", "deploy",
osdeploy_path = ot_gfile_get_child_build_path (sysroot->path, "ostree", "deploy",
ostree_deployment_get_osname (deployment),
"deploy", NULL);
checkout_target_name = g_strdup_printf ("%s.%d", csum, ostree_deployment_get_deployserial (deployment));
@ -246,7 +243,7 @@ checkout_deployment_tree (GFile *sysroot,
}
static gboolean
merge_configuration (OstreeSysroot *sysroot_obj,
merge_configuration (OstreeSysroot *sysroot,
OstreeDeployment *previous_deployment,
OstreeDeployment *deployment,
GFile *deployment_path,
@ -266,7 +263,7 @@ merge_configuration (OstreeSysroot *sysroot_obj,
gs_unref_object GFile *previous_path = NULL;
OstreeBootconfigParser *previous_bootconfig;
previous_path = ostree_sysroot_get_deployment_directory (sysroot_obj, previous_deployment);
previous_path = ostree_sysroot_get_deployment_directory (sysroot, previous_deployment);
source_etc_path = g_file_resolve_relative_path (previous_path, "etc");
source_etc_pristine_path = g_file_resolve_relative_path (previous_path, "usr/etc");
@ -330,20 +327,17 @@ merge_configuration (OstreeSysroot *sysroot_obj,
}
static gboolean
write_origin_file (GFile *sysroot,
write_origin_file (OstreeSysroot *sysroot,
OstreeDeployment *deployment,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object OstreeSysroot *sysroot_obj = NULL;
GKeyFile *origin = ostree_deployment_get_origin (deployment);
sysroot_obj = ostree_sysroot_new (sysroot);
if (origin)
{
gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (sysroot_obj, deployment);
gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (sysroot, deployment);
gs_unref_object GFile *origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path);
gs_free char *contents = NULL;
gsize len;
@ -852,7 +846,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
gs_free char *version_key = NULL;
gs_free char *ostree_kernel_arg = NULL;
gs_free char *options_key = NULL;
__attribute__((cleanup(ot_ordered_hash_cleanup))) OtOrderedHash *ohash = NULL;
__attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL;
const char *val;
OstreeBootconfigParser *bootconfig;
gsize len;
@ -948,9 +942,9 @@ install_deployment_kernel (OstreeSysroot *sysroot,
ostree_kernel_arg = g_strdup_printf ("/ostree/boot.%d/%s/%s/%d",
new_bootversion, osname, bootcsum,
ostree_deployment_get_bootserial (deployment));
ohash = ot_admin_parse_kernel_args (val);
ot_ordered_hash_replace_key (ohash, "ostree", ostree_kernel_arg);
options_key = ot_admin_kernel_arg_string_serialize (ohash);
ohash = _ostree_sysroot_parse_kernel_args (val);
_ostree_ordered_hash_replace_key (ohash, "ostree", ostree_kernel_arg);
options_key = _ostree_sysroot_kernel_arg_string_serialize (ohash);
ostree_bootconfig_parser_set (bootconfig, "options", options_key);
if (!ostree_bootconfig_parser_write (ostree_deployment_get_bootconfig (deployment), bootconfpath,
@ -963,7 +957,7 @@ install_deployment_kernel (OstreeSysroot *sysroot,
}
static gboolean
swap_bootloader (GFile *sysroot,
swap_bootloader (OstreeSysroot *sysroot,
int current_bootversion,
int new_bootversion,
GCancellable *cancellable,
@ -976,7 +970,7 @@ swap_bootloader (GFile *sysroot,
g_assert ((current_bootversion == 0 && new_bootversion == 1) ||
(current_bootversion == 1 && new_bootversion == 0));
boot_loader_link = g_file_resolve_relative_path (sysroot, "boot/loader");
boot_loader_link = g_file_resolve_relative_path (sysroot->path, "boot/loader");
new_target = g_strdup_printf ("loader.%d", new_bootversion);
if (!ot_gfile_atomic_symlink_swap (boot_loader_link, new_target,
@ -989,17 +983,16 @@ swap_bootloader (GFile *sysroot,
}
gboolean
ot_admin_write_deployments (GFile *sysroot,
int current_bootversion,
int new_bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error)
ostree_sysroot_write_deployments (OstreeSysroot *sysroot,
int current_bootversion,
int new_bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
guint i;
gs_unref_object OstreeSysroot *sysroot_obj = ostree_sysroot_new (sysroot);
gs_unref_object OstreeBootloader *bootloader = ostree_sysroot_query_bootloader (sysroot_obj);
gs_unref_object OstreeBootloader *bootloader = ostree_sysroot_query_bootloader (sysroot);
if (bootloader)
g_print ("Detected bootloader: %s\n", ostree_bootloader_get_name (bootloader));
@ -1014,7 +1007,7 @@ ot_admin_write_deployments (GFile *sysroot,
goto out;
}
if (!swap_bootlinks (sysroot_obj, current_bootversion,
if (!swap_bootlinks (sysroot, current_bootversion,
new_deployments,
cancellable, error))
{
@ -1027,7 +1020,7 @@ ot_admin_write_deployments (GFile *sysroot,
for (i = 0; i < new_deployments->len; i++)
{
OstreeDeployment *deployment = new_deployments->pdata[i];
if (!install_deployment_kernel (sysroot_obj, new_bootversion,
if (!install_deployment_kernel (sysroot, new_bootversion,
deployment, new_deployments->len,
cancellable, error))
{
@ -1037,7 +1030,7 @@ ot_admin_write_deployments (GFile *sysroot,
}
/* Swap bootlinks for *new* version */
if (!swap_bootlinks (sysroot_obj, new_bootversion, new_deployments,
if (!swap_bootlinks (sysroot, new_bootversion, new_deployments,
cancellable, error))
{
g_prefix_error (error, "Generating new bootlinks: ");
@ -1071,25 +1064,24 @@ ot_admin_write_deployments (GFile *sysroot,
}
gboolean
ot_admin_deploy (GFile *sysroot,
int current_bootversion,
GPtrArray *current_deployments,
const char *osname,
const char *revision,
GKeyFile *origin,
char **add_kernel_argv,
gboolean retain,
OstreeDeployment *booted_deployment,
OstreeDeployment *provided_merge_deployment,
OstreeDeployment **out_new_deployment,
int *out_new_bootversion,
GPtrArray **out_new_deployments,
GCancellable *cancellable,
GError **error)
ostree_sysroot_deploy (OstreeSysroot *sysroot,
int current_bootversion,
GPtrArray *current_deployments,
const char *osname,
const char *revision,
GKeyFile *origin,
char **add_kernel_argv,
gboolean retain,
OstreeDeployment *booted_deployment,
OstreeDeployment *provided_merge_deployment,
OstreeDeployment **out_new_deployment,
int *out_new_bootversion,
GPtrArray **out_new_deployments,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
OstreeDeployment *new_deployment;
gs_unref_object OstreeSysroot *sysroot_obj = NULL;
gs_unref_object OstreeDeployment *merge_deployment = NULL;
gs_unref_object OstreeRepo *repo = NULL;
gs_unref_object GFile *commit_root = NULL;
@ -1101,9 +1093,7 @@ ot_admin_deploy (GFile *sysroot,
gs_unref_ptrarray GPtrArray *new_deployments = NULL;
int new_bootversion;
sysroot_obj = ostree_sysroot_new (sysroot);
if (!ostree_sysroot_get_repo (sysroot_obj, &repo, cancellable, error))
if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
goto out;
/* Here we perform cleanup of any leftover data from previous
@ -1113,7 +1103,7 @@ ot_admin_deploy (GFile *sysroot,
* TODO: Add /ostree/transaction file, and only do this cleanup if
* we find it.
*/
if (!ostree_sysroot_cleanup (sysroot_obj, cancellable, error))
if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
{
g_prefix_error (error, "Performing initial cleanup: ");
goto out;
@ -1144,8 +1134,8 @@ ot_admin_deploy (GFile *sysroot,
if (provided_merge_deployment != NULL)
merge_deployment = g_object_ref (provided_merge_deployment);
else
merge_deployment = ot_admin_get_merge_deployment (current_deployments, osname,
booted_deployment);
merge_deployment = ostree_sysroot_get_merge_deployment (current_deployments, osname,
booted_deployment);
compute_new_deployment_list (current_bootversion,
current_deployments, osname,
@ -1179,7 +1169,7 @@ ot_admin_deploy (GFile *sysroot,
bootconfig = ostree_bootconfig_parser_new ();
ostree_deployment_set_bootconfig (new_deployment, bootconfig);
if (!merge_configuration (sysroot_obj, merge_deployment, new_deployment,
if (!merge_configuration (sysroot, merge_deployment, new_deployment,
new_deployment_path,
cancellable, error))
{
@ -1197,25 +1187,25 @@ ot_admin_deploy (GFile *sysroot,
if (add_kernel_argv)
{
char **strviter;
__attribute__((cleanup(ot_ordered_hash_cleanup))) OtOrderedHash *ohash = NULL;
__attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *ohash = NULL;
gs_free char *new_options = NULL;
ohash = ot_admin_parse_kernel_args (ostree_bootconfig_parser_get (bootconfig, "options"));
ohash = _ostree_sysroot_parse_kernel_args (ostree_bootconfig_parser_get (bootconfig, "options"));
for (strviter = add_kernel_argv; *strviter; strviter++)
{
char *karg = g_strdup (*strviter);
const char *val = ot_admin_util_split_keyeq (karg);
const char *val = _ostree_sysroot_split_keyeq (karg);
ot_ordered_hash_replace_key_take (ohash, karg, val);
_ostree_ordered_hash_replace_key_take (ohash, karg, val);
}
new_options = ot_admin_kernel_arg_string_serialize (ohash);
new_options = _ostree_sysroot_kernel_arg_string_serialize (ohash);
ostree_bootconfig_parser_set (bootconfig, "options", new_options);
}
if (!ot_admin_write_deployments (sysroot, current_bootversion, new_bootversion,
new_deployments, cancellable, error))
if (!ostree_sysroot_write_deployments (sysroot, current_bootversion, new_bootversion,
new_deployments, cancellable, error))
goto out;
g_print ("Transaction complete, performing cleanup\n");
@ -1226,7 +1216,7 @@ ot_admin_deploy (GFile *sysroot,
* done from the host.
*/
{
gs_unref_object GFile *osdir = ot_gfile_resolve_path_printf (sysroot, "ostree/deploy/%s", ostree_deployment_get_osname (new_deployment));
gs_unref_object GFile *osdir = ot_gfile_resolve_path_printf (sysroot->path, "ostree/deploy/%s", ostree_deployment_get_osname (new_deployment));
gs_unref_object GFile *os_current_path = g_file_get_child (osdir, "current");
gs_free char *target = g_file_get_relative_path (osdir, new_deployment_path);
g_assert (target != NULL);
@ -1237,7 +1227,7 @@ ot_admin_deploy (GFile *sysroot,
/* And finally, cleanup of any leftover data.
*/
if (!ostree_sysroot_cleanup (sysroot_obj, cancellable, error))
if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
{
g_prefix_error (error, "Performing final cleanup: ");
goto out;

View File

@ -21,6 +21,7 @@
#pragma once
#include "ostree.h"
#include "ostree-ordered-hash.h"
G_BEGIN_DECLS
@ -53,5 +54,11 @@ _ostree_sysroot_get_devino (GFile *path,
char *_ostree_sysroot_join_lines (GPtrArray *lines);
char *_ostree_sysroot_split_keyeq (char *str);
OstreeOrderedHash *_ostree_sysroot_parse_kernel_args (const char *options);
char * _ostree_sysroot_kernel_arg_string_serialize (OstreeOrderedHash *ohash);
G_END_DECLS

View File

@ -839,3 +839,243 @@ _ostree_sysroot_join_lines (GPtrArray *lines)
}
return g_string_free (buf, FALSE);
}
static gboolean
parse_kernel_commandline (OstreeOrderedHash **out_args,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFile *proc_cmdline = g_file_new_for_path ("/proc/cmdline");
gs_free char *contents = NULL;
gsize len;
if (!g_file_load_contents (proc_cmdline, cancellable, &contents, &len, NULL,
error))
goto out;
ret = TRUE;
*out_args = _ostree_sysroot_parse_kernel_args (contents);;
out:
return ret;
}
/**
* ostree_sysroot_find_booted_deployment:
* @target_sysroot: Root directory
* @deployments: (element-type OstreeDeployment): Loaded deployments
* @out_deployment: (out): The currently booted deployment
* @cancellable:
* @error:
*
* If the system is currently booted into a deployment in
* @deployments, set @out_deployment. Note that if @target_sysroot is
* not equal to "/", @out_deployment will always be set to %NULL.
*/
gboolean
ostree_sysroot_find_booted_deployment (OstreeSysroot *self,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFile *active_root = g_file_new_for_path ("/");
gs_unref_object OstreeSysroot *active_deployment_root = ostree_sysroot_new_default ();
gs_unref_object OstreeDeployment *ret_deployment = NULL;
if (g_file_equal (active_root, self->path))
{
guint i;
const char *bootlink_arg;
__attribute__((cleanup(_ostree_ordered_hash_cleanup))) OstreeOrderedHash *kernel_args = NULL;
guint32 root_device;
guint64 root_inode;
if (!_ostree_sysroot_get_devino (active_root, &root_device, &root_inode,
cancellable, error))
goto out;
if (!parse_kernel_commandline (&kernel_args, cancellable, error))
goto out;
bootlink_arg = g_hash_table_lookup (kernel_args->table, "ostree");
if (bootlink_arg)
{
for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (active_deployment_root, deployment);
guint32 device;
guint64 inode;
if (!_ostree_sysroot_get_devino (deployment_path, &device, &inode,
cancellable, error))
goto out;
if (device == root_device && inode == root_inode)
{
ret_deployment = g_object_ref (deployment);
break;
}
}
if (ret_deployment == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unexpected state: ostree= kernel argument found, but / is not a deployment root");
goto out;
}
}
else
{
/* Not an ostree system */
}
}
ret = TRUE;
ot_transfer_out_value (out_deployment, &ret_deployment);
out:
return ret;
}
gboolean
ostree_sysroot_require_deployment_or_osname (OstreeSysroot *sysroot,
GPtrArray *deployments,
const char *osname,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object OstreeDeployment *ret_deployment = NULL;
if (!ostree_sysroot_find_booted_deployment (sysroot, deployments, &ret_deployment,
cancellable, error))
goto out;
if (ret_deployment == NULL && osname == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Not currently booted into an OSTree system and no --os= argument given");
goto out;
}
ret = TRUE;
ot_transfer_out_value (out_deployment, &ret_deployment);
out:
return ret;
}
OstreeOrderedHash *
_ostree_sysroot_parse_kernel_args (const char *options)
{
OstreeOrderedHash *ret;
char **args;
char **iter;
ret = _ostree_ordered_hash_new ();
if (!options)
return ret;
args = g_strsplit (options, " ", -1);
for (iter = args; *iter; iter++)
{
char *arg = *iter;
char *val;
val = _ostree_sysroot_split_keyeq (arg);
g_ptr_array_add (ret->order, arg);
g_hash_table_insert (ret->table, arg, val);
}
return ret;
}
/*
* Modify @arg which should be of the form key=value to make @arg just
* contain key. Return a pointer to the start of value.
*/
char *
_ostree_sysroot_split_keyeq (char *arg)
{
char *eq;
eq = strchr (arg, '=');
if (eq)
{
/* Note key/val are in one malloc block,
* so we don't free val...
*/
*eq = '\0';
return eq+1;
}
else
{
/* ...and this allows us to insert a constant
* string.
*/
return "";
}
}
char *
_ostree_sysroot_kernel_arg_string_serialize (OstreeOrderedHash *ohash)
{
guint i;
GString *buf = g_string_new ("");
gboolean first = TRUE;
for (i = 0; i < ohash->order->len; i++)
{
const char *key = ohash->order->pdata[i];
const char *val = g_hash_table_lookup (ohash->table, key);
g_assert (val != NULL);
if (first)
first = FALSE;
else
g_string_append_c (buf, ' ');
if (*val)
g_string_append_printf (buf, "%s=%s", key, val);
else
g_string_append (buf, key);
}
return g_string_free (buf, FALSE);
}
OstreeDeployment *
ostree_sysroot_get_merge_deployment (GPtrArray *deployments,
const char *osname,
OstreeDeployment *booted_deployment)
{
g_return_val_if_fail (osname != NULL || booted_deployment != NULL, NULL);
if (osname == NULL)
osname = ostree_deployment_get_osname (booted_deployment);
if (booted_deployment &&
g_strcmp0 (ostree_deployment_get_osname (booted_deployment), osname) == 0)
{
return g_object_ref (booted_deployment);
}
else
{
guint i;
for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;
return g_object_ref (deployment);
}
}
return NULL;
}

View File

@ -73,5 +73,46 @@ gboolean ostree_sysroot_get_repo (OstreeSysroot *self,
OstreeBootloader *ostree_sysroot_query_bootloader (OstreeSysroot *sysroot);
gboolean ostree_sysroot_find_booted_deployment (OstreeSysroot *sysroot,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error);
gboolean ostree_sysroot_require_deployment_or_osname (OstreeSysroot *sysroot,
GPtrArray *deployment_list,
const char *osname,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error);
gboolean ostree_sysroot_write_deployments (OstreeSysroot *sysroot,
int current_bootversion,
int new_bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error);
gboolean ostree_sysroot_deploy (OstreeSysroot *sysroot,
int current_bootversion,
GPtrArray *current_deployments,
const char *osname,
const char *revision,
GKeyFile *origin,
char **add_kernel_argv,
gboolean retain,
OstreeDeployment *booted_deployment,
OstreeDeployment *merge_deployment,
OstreeDeployment **out_new_deployment,
int *out_new_bootversion,
GPtrArray **out_new_deployments,
GCancellable *cancellable,
GError **error);
OstreeDeployment *ostree_sysroot_get_merge_deployment (GPtrArray *deployment_list,
const char *osname,
OstreeDeployment *booted_deployment);
G_END_DECLS

View File

@ -24,8 +24,6 @@
#include "ot-admin-builtins.h"
#include "ot-admin-functions.h"
#include "ot-admin-deploy.h"
#include "ot-ordered-hash.h"
#include "ostree.h"
#include "otutil.h"
@ -90,10 +88,10 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancell
/* Find the currently booted deployment, if any; we will ensure it
* is present in the new deployment list.
*/
if (!ot_admin_require_deployment_or_osname (ostree_sysroot_get_path (sysroot), current_deployments,
opt_osname,
&booted_deployment,
cancellable, error))
if (!ostree_sysroot_require_deployment_or_osname (sysroot, current_deployments,
opt_osname,
&booted_deployment,
cancellable, error))
{
g_prefix_error (error, "Looking for booted deployment: ");
goto out;
@ -114,12 +112,12 @@ ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancell
if (!ostree_repo_resolve_rev (repo, refspec, FALSE, &revision, error))
goto out;
if (!ot_admin_deploy (ostree_sysroot_get_path (sysroot), current_bootversion, current_deployments,
opt_osname, revision, origin,
opt_kernel_argv, opt_retain,
booted_deployment, NULL,
&new_deployment, &new_bootversion, &new_deployments,
cancellable, error))
if (!ostree_sysroot_deploy (sysroot, current_bootversion, current_deployments,
opt_osname, revision, origin,
opt_kernel_argv, opt_retain,
booted_deployment, NULL,
&new_deployment, &new_bootversion, &new_deployments,
cancellable, error))
goto out;
ret = TRUE;

View File

@ -68,14 +68,14 @@ ot_admin_builtin_diff (int argc, char **argv, OstreeSysroot *sysroot, GCancellab
goto out;
}
if (!ot_admin_require_deployment_or_osname (ostree_sysroot_get_path (sysroot), deployments,
opt_osname, &deployment,
cancellable, error))
if (!ostree_sysroot_require_deployment_or_osname (sysroot, deployments,
opt_osname, &deployment,
cancellable, error))
goto out;
if (deployment != NULL)
opt_osname = (char*)ostree_deployment_get_osname (deployment);
if (deployment == NULL)
deployment = ot_admin_get_merge_deployment (deployments, opt_osname, deployment);
deployment = ostree_sysroot_get_merge_deployment (deployments, opt_osname, deployment);
if (deployment == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND,

View File

@ -57,9 +57,9 @@ ot_admin_builtin_status (int argc, char **argv, OstreeSysroot *sysroot, GCancell
goto out;
}
if (!ot_admin_find_booted_deployment (ostree_sysroot_get_path (sysroot), deployments,
&booted_deployment,
cancellable, error))
if (!ostree_sysroot_find_booted_deployment (sysroot, deployments,
&booted_deployment,
cancellable, error))
goto out;
if (deployments->len == 0)

View File

@ -24,8 +24,6 @@
#include "ot-admin-builtins.h"
#include "ot-admin-functions.h"
#include "ot-admin-deploy.h"
#include "ot-ordered-hash.h"
#include "ostree.h"
#include "otutil.h"
@ -68,8 +66,8 @@ ot_admin_builtin_undeploy (int argc, char **argv, OstreeSysroot *sysroot, GCance
goto out;
}
if (!ot_admin_find_booted_deployment (ostree_sysroot_get_path (sysroot), current_deployments, &booted_deployment,
cancellable, error))
if (!ostree_sysroot_find_booted_deployment (sysroot, current_deployments, &booted_deployment,
cancellable, error))
goto out;
if (deploy_index < 0)
@ -95,9 +93,9 @@ ot_admin_builtin_undeploy (int argc, char **argv, OstreeSysroot *sysroot, GCance
g_ptr_array_remove_index (current_deployments, deploy_index);
if (!ot_admin_write_deployments (ostree_sysroot_get_path (sysroot), current_bootversion,
current_bootversion ? 0 : 1, current_deployments,
cancellable, error))
if (!ostree_sysroot_write_deployments (sysroot, current_bootversion,
current_bootversion ? 0 : 1, current_deployments,
cancellable, error))
goto out;
g_print ("Deleted deployment %s.%d\n", ostree_deployment_get_csum (target_deployment),

View File

@ -24,7 +24,6 @@
#include "ot-admin-builtins.h"
#include "ot-admin-functions.h"
#include "ot-admin-deploy.h"
#include "ostree.h"
#include "otutil.h"
#include "libgsystem.h"
@ -78,15 +77,15 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeSysroot *sysroot, GCancel
goto out;
}
if (!ot_admin_require_deployment_or_osname (ostree_sysroot_get_path (sysroot), current_deployments,
opt_osname,
&booted_deployment,
cancellable, error))
if (!ostree_sysroot_require_deployment_or_osname (sysroot, current_deployments,
opt_osname,
&booted_deployment,
cancellable, error))
goto out;
if (!opt_osname)
opt_osname = (char*)ostree_deployment_get_osname (booted_deployment);
merge_deployment = ot_admin_get_merge_deployment (current_deployments, opt_osname,
booted_deployment);
merge_deployment = ostree_sysroot_get_merge_deployment (current_deployments, opt_osname,
booted_deployment);
deployment_path = ostree_sysroot_get_deployment_directory (sysroot, merge_deployment);
deployment_origin_path = ostree_sysroot_get_deployment_origin_path (deployment_path);
@ -135,13 +134,13 @@ ot_admin_builtin_upgrade (int argc, char **argv, OstreeSysroot *sysroot, GCancel
else
{
gs_unref_object GFile *real_sysroot = g_file_new_for_path ("/");
if (!ot_admin_deploy (ostree_sysroot_get_path (sysroot),
current_bootversion, current_deployments,
opt_osname, new_revision, origin,
NULL, FALSE,
booted_deployment, merge_deployment,
&new_deployment, &new_bootversion, &new_deployments,
cancellable, error))
if (!ostree_sysroot_deploy (sysroot,
current_bootversion, current_deployments,
opt_osname, new_revision, origin,
NULL, FALSE,
booted_deployment, merge_deployment,
&new_deployment, &new_bootversion, &new_deployments,
cancellable, error))
goto out;
if (opt_reboot && g_file_equal (ostree_sysroot_get_path (sysroot), real_sysroot))

View File

@ -1,55 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2012 Colin Walters <walters@verbum.org>
*
* 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.
*
* Author: Colin Walters <walters@verbum.org>
*/
#pragma once
#include <gio/gio.h>
#include <ostree.h>
#include "ot-ordered-hash.h"
G_BEGIN_DECLS
gboolean ot_admin_write_deployments (GFile *sysroot,
int current_bootversion,
int new_bootversion,
GPtrArray *new_deployments,
GCancellable *cancellable,
GError **error);
gboolean ot_admin_deploy (GFile *sysroot,
int current_bootversion,
GPtrArray *current_deployments,
const char *osname,
const char *revision,
GKeyFile *origin,
char **add_kernel_argv,
gboolean retain,
OstreeDeployment *booted_deployment,
OstreeDeployment *merge_deployment,
OstreeDeployment **out_new_deployment,
int *out_new_bootversion,
GPtrArray **out_new_deployments,
GCancellable *cancellable,
GError **error);
G_END_DECLS

View File

@ -27,240 +27,6 @@
#include "ostree.h"
#include "libgsystem.h"
OtOrderedHash *
ot_admin_parse_kernel_args (const char *options)
{
OtOrderedHash *ret;
char **args;
char **iter;
ret = ot_ordered_hash_new ();
if (!options)
return ret;
args = g_strsplit (options, " ", -1);
for (iter = args; *iter; iter++)
{
char *arg = *iter;
char *val;
val = ot_admin_util_split_keyeq (arg);
g_ptr_array_add (ret->order, arg);
g_hash_table_insert (ret->table, arg, val);
}
return ret;
}
char *
ot_admin_kernel_arg_string_serialize (OtOrderedHash *ohash)
{
guint i;
GString *buf = g_string_new ("");
gboolean first = TRUE;
for (i = 0; i < ohash->order->len; i++)
{
const char *key = ohash->order->pdata[i];
const char *val = g_hash_table_lookup (ohash->table, key);
g_assert (val != NULL);
if (first)
first = FALSE;
else
g_string_append_c (buf, ' ');
if (*val)
g_string_append_printf (buf, "%s=%s", key, val);
else
g_string_append (buf, key);
}
return g_string_free (buf, FALSE);
}
gboolean
ot_admin_check_os (GFile *sysroot,
const char *osname,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFile *osdir = NULL;
osdir = ot_gfile_resolve_path_printf (sysroot, "ostree/deploy/%s/var", osname);
if (!g_file_query_exists (osdir, NULL))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"No such OS '%s', use os-init to create it", osname);
goto out;
}
ret = TRUE;
out:
return ret;
}
static gboolean
parse_kernel_commandline (OtOrderedHash **out_args,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFile *proc_cmdline = g_file_new_for_path ("/proc/cmdline");
gs_free char *contents = NULL;
gsize len;
if (!g_file_load_contents (proc_cmdline, cancellable, &contents, &len, NULL,
error))
goto out;
ret = TRUE;
*out_args = ot_admin_parse_kernel_args (contents);;
out:
return ret;
}
/**
* ot_admin_find_booted_deployment:
* @target_sysroot: Root directory
* @deployments: (element-type OstreeDeployment): Loaded deployments
* @out_deployment: (out): The currently booted deployment
* @cancellable:
* @error:
*
* If the system is currently booted into a deployment in
* @deployments, set @out_deployment. Note that if @target_sysroot is
* not equal to "/", @out_deployment will always be set to %NULL.
*/
gboolean
ot_admin_find_booted_deployment (GFile *target_sysroot,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFile *active_root = g_file_new_for_path ("/");
gs_unref_object OstreeSysroot *active_deployment_root = ostree_sysroot_new_default ();
gs_unref_object OstreeDeployment *ret_deployment = NULL;
if (g_file_equal (active_root, target_sysroot))
{
guint i;
const char *bootlink_arg;
__attribute__((cleanup(ot_ordered_hash_cleanup))) OtOrderedHash *kernel_args = NULL;
guint32 root_device;
guint64 root_inode;
if (!ot_admin_util_get_devino (active_root, &root_device, &root_inode,
cancellable, error))
goto out;
if (!parse_kernel_commandline (&kernel_args, cancellable, error))
goto out;
bootlink_arg = g_hash_table_lookup (kernel_args->table, "ostree");
if (bootlink_arg)
{
for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
gs_unref_object GFile *deployment_path = ostree_sysroot_get_deployment_directory (active_deployment_root, deployment);
guint32 device;
guint64 inode;
if (!ot_admin_util_get_devino (deployment_path, &device, &inode,
cancellable, error))
goto out;
if (device == root_device && inode == root_inode)
{
ret_deployment = g_object_ref (deployment);
break;
}
}
if (ret_deployment == NULL)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unexpected state: ostree= kernel argument found, but / is not a deployment root");
goto out;
}
}
else
{
/* Not an ostree system */
}
}
ret = TRUE;
ot_transfer_out_value (out_deployment, &ret_deployment);
out:
return ret;
}
gboolean
ot_admin_require_deployment_or_osname (GFile *sysroot,
GPtrArray *deployments,
const char *osname,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object OstreeDeployment *ret_deployment = NULL;
if (!ot_admin_find_booted_deployment (sysroot, deployments, &ret_deployment,
cancellable, error))
goto out;
if (ret_deployment == NULL && osname == NULL)
{
g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Not currently booted into an OSTree system and no --os= argument given");
goto out;
}
ret = TRUE;
ot_transfer_out_value (out_deployment, &ret_deployment);
out:
return ret;
}
OstreeDeployment *
ot_admin_get_merge_deployment (GPtrArray *deployments,
const char *osname,
OstreeDeployment *booted_deployment)
{
g_return_val_if_fail (osname != NULL || booted_deployment != NULL, NULL);
if (osname == NULL)
osname = ostree_deployment_get_osname (booted_deployment);
if (booted_deployment &&
g_strcmp0 (ostree_deployment_get_osname (booted_deployment), osname) == 0)
{
return g_object_ref (booted_deployment);
}
else
{
guint i;
for (i = 0; i < deployments->len; i++)
{
OstreeDeployment *deployment = deployments->pdata[i];
if (strcmp (ostree_deployment_get_osname (deployment), osname) != 0)
continue;
return g_object_ref (deployment);
}
}
return NULL;
}
GKeyFile *
ot_origin_new_from_refspec (const char *refspec)
{

View File

@ -24,56 +24,9 @@
#include <gio/gio.h>
#include <ostree.h>
#include "ot-ordered-hash.h"
G_BEGIN_DECLS
char *ot_admin_util_split_keyeq (char *str);
gboolean ot_admin_util_get_devino (GFile *path,
guint32 *out_device,
guint64 *out_inode,
GCancellable *cancellable,
GError **error);
gboolean ot_admin_ensure_initialized (GFile *ostree_dir,
GCancellable *cancellable,
GError **error);
gboolean ot_admin_check_os (GFile *sysroot,
const char *osname,
GCancellable *cancellable,
GError **error);
OtOrderedHash *ot_admin_parse_kernel_args (const char *options);
char * ot_admin_kernel_arg_string_serialize (OtOrderedHash *ohash);
gboolean ot_admin_find_booted_deployment (GFile *sysroot,
GPtrArray *deployments,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error);
gboolean ot_admin_require_booted_deployment (GFile *sysroot,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error);
gboolean ot_admin_require_deployment_or_osname (GFile *sysroot,
GPtrArray *deployment_list,
const char *osname,
OstreeDeployment **out_deployment,
GCancellable *cancellable,
GError **error);
OstreeDeployment *ot_admin_get_merge_deployment (GPtrArray *deployment_list,
const char *osname,
OstreeDeployment *booted_deployment);
gboolean ot_admin_get_default_ostree_dir (GFile **out_ostree_dir,
GCancellable *cancellable,
GError **error);
GKeyFile *ot_origin_new_from_refspec (const char *refspec);
G_END_DECLS

View File

@ -1,78 +0,0 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
*
* Copyright (C) 2012 Colin Walters <walters@verbum.org>
*
* 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.
*
* Author: Colin Walters <walters@verbum.org>
*/
#include "config.h"
#include "ot-admin-functions.h"
#include "otutil.h"
#include "ostree-core.h"
#include "libgsystem.h"
/*
* Modify @arg which should be of the form key=value to make @arg just
* contain key. Return a pointer to the start of value.
*/
char *
ot_admin_util_split_keyeq (char *arg)
{
char *eq;
eq = strchr (arg, '=');
if (eq)
{
/* Note key/val are in one malloc block,
* so we don't free val...
*/
*eq = '\0';
return eq+1;
}
else
{
/* ...and this allows us to insert a constant
* string.
*/
return "";
}
}
gboolean
ot_admin_util_get_devino (GFile *path,
guint32 *out_device,
guint64 *out_inode,
GCancellable *cancellable,
GError **error)
{
gboolean ret = FALSE;
gs_unref_object GFileInfo *finfo = g_file_query_info (path, "unix::device,unix::inode",
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
cancellable, error);
if (!finfo)
goto out;
ret = TRUE;
*out_device = g_file_info_get_attribute_uint32 (finfo, "unix::device");
*out_inode = g_file_info_get_attribute_uint64 (finfo, "unix::inode");
out:
return ret;
}