admin: Don't delete the running deployment
https://bugzilla.gnome.org/show_bug.cgi?id=694762
This commit is contained in:
parent
dba406bb8f
commit
30d46f9a02
|
|
@ -35,67 +35,6 @@ static GOptionEntry options[] = {
|
|||
{ NULL }
|
||||
};
|
||||
|
||||
static gboolean
|
||||
list_deployments (GFile *from_dir,
|
||||
GPtrArray *inout_deployments,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GError *temp_error = NULL;
|
||||
ot_lobj GFileEnumerator *dir_enum = NULL;
|
||||
ot_lobj GFileInfo *file_info = NULL;
|
||||
|
||||
dir_enum = g_file_enumerate_children (from_dir, OSTREE_GIO_FAST_QUERYINFO,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
NULL, error);
|
||||
if (!dir_enum)
|
||||
goto out;
|
||||
|
||||
while ((file_info = g_file_enumerator_next_file (dir_enum, cancellable, error)) != NULL)
|
||||
{
|
||||
const char *name;
|
||||
ot_lobj GFile *child = NULL;
|
||||
ot_lobj GFile *possible_etc = NULL;
|
||||
ot_lobj GFile *possible_usr = NULL;
|
||||
|
||||
name = g_file_info_get_name (file_info);
|
||||
|
||||
if (g_str_has_suffix (name, "-etc"))
|
||||
goto next;
|
||||
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
|
||||
goto next;
|
||||
|
||||
child = g_file_get_child (from_dir, name);
|
||||
|
||||
possible_etc = ot_gfile_get_child_strconcat (from_dir, name, "-etc", NULL);
|
||||
/* Bit of a hack... */
|
||||
possible_usr = g_file_get_child (child, "usr");
|
||||
|
||||
if (g_file_query_exists (possible_etc, cancellable))
|
||||
g_ptr_array_add (inout_deployments, g_file_get_child (from_dir, name));
|
||||
else if (g_file_query_exists (possible_usr, cancellable))
|
||||
goto next;
|
||||
else
|
||||
{
|
||||
if (!list_deployments (child, inout_deployments,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
next:
|
||||
g_clear_object (&file_info);
|
||||
}
|
||||
if (temp_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, temp_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ot_admin_builtin_prune (int argc, char **argv, OtAdminBuiltinOpts *admin_opts, GError **error)
|
||||
|
|
@ -109,7 +48,9 @@ ot_admin_builtin_prune (int argc, char **argv, OtAdminBuiltinOpts *admin_opts, G
|
|||
ot_lobj GFile *deploy_dir = NULL;
|
||||
ot_lobj GFile *current_deployment = NULL;
|
||||
ot_lobj GFile *previous_deployment = NULL;
|
||||
ot_lobj GFile *active_deployment = NULL;
|
||||
ot_lptrarray GPtrArray *deployments = NULL;
|
||||
gs_free char *active_osname = NULL;
|
||||
__attribute__((unused)) GCancellable *cancellable = NULL;
|
||||
|
||||
context = g_option_context_new ("OSNAME - Delete untagged deployments and repository objects");
|
||||
|
|
@ -127,16 +68,16 @@ ot_admin_builtin_prune (int argc, char **argv, OtAdminBuiltinOpts *admin_opts, G
|
|||
|
||||
osname = argv[1];
|
||||
|
||||
deploy_dir = ot_gfile_get_child_build_path (ostree_dir, "deploy", osname, NULL);
|
||||
|
||||
deployments = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
|
||||
if (!list_deployments (deploy_dir, deployments, cancellable, error))
|
||||
if (!ot_admin_list_deployments (ostree_dir, osname, &deployments,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (!ot_admin_get_current_deployment (ostree_dir, osname, ¤t_deployment,
|
||||
cancellable, error));
|
||||
if (!ot_admin_get_previous_deployment (ostree_dir, osname, &previous_deployment,
|
||||
cancellable, error));
|
||||
if (!ot_admin_get_active_deployment (ostree_dir, &active_osname, &active_deployment,
|
||||
cancellable, error));
|
||||
|
||||
for (i = 0; i < deployments->len; i++)
|
||||
{
|
||||
|
|
@ -145,7 +86,8 @@ ot_admin_builtin_prune (int argc, char **argv, OtAdminBuiltinOpts *admin_opts, G
|
|||
ot_lobj GFile *parent = NULL;
|
||||
|
||||
if ((current_deployment && g_file_equal (deployment, current_deployment))
|
||||
|| (previous_deployment && g_file_equal (deployment, previous_deployment)))
|
||||
|| (previous_deployment && g_file_equal (deployment, previous_deployment))
|
||||
|| (active_deployment && g_file_equal (deployment, active_deployment)))
|
||||
continue;
|
||||
|
||||
parent = g_file_get_parent (deployment);
|
||||
|
|
|
|||
|
|
@ -181,6 +181,257 @@ ot_admin_get_previous_deployment (GFile *ostree_dir,
|
|||
cancellable, error);
|
||||
}
|
||||
|
||||
/*
|
||||
static gboolean
|
||||
ot_admin_list_osnames (GFile *ostree_dir,
|
||||
GPtrArray **out_osnames,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
ot_lobj GFileEnumerator *dir_enum = NULL;
|
||||
ot_lobj GFileInfo *file_info = NULL;
|
||||
ot_lobj GFile *deploy_dir = NULL;
|
||||
ot_lptrarray GPtrArray *ret_osnames = NULL;
|
||||
GError *temp_error = NULL;
|
||||
|
||||
deploy_dir = g_file_get_child (ostree_dir, "deploy");
|
||||
|
||||
dir_enum = g_file_enumerate_children (deploy_dir, OSTREE_GIO_FAST_QUERYINFO,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
NULL, error);
|
||||
if (!dir_enum)
|
||||
goto out;
|
||||
|
||||
while ((file_info = g_file_enumerator_next_file (dir_enum, NULL, error)) != NULL)
|
||||
{
|
||||
if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY)
|
||||
{
|
||||
char *name = g_strdup (g_file_info_get_name (file_info));
|
||||
g_ptr_array_add (ret_osnames, name);
|
||||
}
|
||||
g_clear_object (&file_info);
|
||||
}
|
||||
|
||||
if (temp_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, temp_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_osnames, &ret_osnames);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
static gboolean
|
||||
list_deployments_internal (GFile *from_dir,
|
||||
GPtrArray *inout_deployments,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
GError *temp_error = NULL;
|
||||
ot_lobj GFileEnumerator *dir_enum = NULL;
|
||||
ot_lobj GFileInfo *file_info = NULL;
|
||||
|
||||
dir_enum = g_file_enumerate_children (from_dir, OSTREE_GIO_FAST_QUERYINFO,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
NULL, error);
|
||||
if (!dir_enum)
|
||||
goto out;
|
||||
|
||||
while ((file_info = g_file_enumerator_next_file (dir_enum, cancellable, error)) != NULL)
|
||||
{
|
||||
const char *name;
|
||||
ot_lobj GFile *child = NULL;
|
||||
ot_lobj GFile *possible_etc = NULL;
|
||||
ot_lobj GFile *possible_usr = NULL;
|
||||
|
||||
name = g_file_info_get_name (file_info);
|
||||
|
||||
if (g_str_has_suffix (name, "-etc"))
|
||||
goto next;
|
||||
if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
|
||||
goto next;
|
||||
|
||||
child = g_file_get_child (from_dir, name);
|
||||
|
||||
possible_etc = ot_gfile_get_child_strconcat (from_dir, name, "-etc", NULL);
|
||||
/* Bit of a hack... */
|
||||
possible_usr = g_file_get_child (child, "usr");
|
||||
|
||||
if (g_file_query_exists (possible_etc, cancellable))
|
||||
g_ptr_array_add (inout_deployments, g_file_get_child (from_dir, name));
|
||||
else if (g_file_query_exists (possible_usr, cancellable))
|
||||
goto next;
|
||||
else
|
||||
{
|
||||
if (!list_deployments_internal (child, inout_deployments,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
}
|
||||
|
||||
next:
|
||||
g_clear_object (&file_info);
|
||||
}
|
||||
if (temp_error != NULL)
|
||||
{
|
||||
g_propagate_error (error, temp_error);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ot_admin_list_deployments (GFile *ostree_dir,
|
||||
const char *osname,
|
||||
GPtrArray **out_deployments,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
ot_lobj GFileEnumerator *dir_enum = NULL;
|
||||
ot_lobj GFileInfo *file_info = NULL;
|
||||
ot_lobj GFile *osdir = NULL;
|
||||
ot_lptrarray GPtrArray *ret_deployments = NULL;
|
||||
|
||||
osdir = ot_gfile_get_child_build_path (ostree_dir, "deploy", osname, NULL);
|
||||
ret_deployments = g_ptr_array_new_with_free_func (g_object_unref);
|
||||
|
||||
if (!list_deployments_internal (osdir, ret_deployments, cancellable, error))
|
||||
goto out;
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_deployments, &ret_deployments);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ot_admin_get_booted_os (char **out_osname,
|
||||
char **out_tree,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
gs_free char *ret_osname = NULL;
|
||||
gs_free char *ret_tree = NULL;
|
||||
gs_free char *cmdline_contents = NULL;
|
||||
const char *iter;
|
||||
gsize len;
|
||||
|
||||
if (!g_file_get_contents ("/proc/cmdline", &cmdline_contents, &len,
|
||||
error))
|
||||
goto out;
|
||||
|
||||
iter = cmdline_contents;
|
||||
do
|
||||
{
|
||||
const char *next = strchr (iter, ' ');
|
||||
if (next)
|
||||
next += 1;
|
||||
if (g_str_has_prefix (iter, "ostree="))
|
||||
{
|
||||
const char *slash = strchr (iter, '/');
|
||||
if (slash)
|
||||
{
|
||||
const char *start = iter + strlen ("ostree=");
|
||||
ret_osname = g_strndup (start, slash - start);
|
||||
if (next)
|
||||
ret_tree = g_strndup (slash + 1, next - slash - 1);
|
||||
else
|
||||
ret_tree = g_strdup (slash + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
iter = next;
|
||||
}
|
||||
while (iter != NULL);
|
||||
|
||||
ret = TRUE;
|
||||
out:
|
||||
ot_transfer_out_value (out_osname, &ret_osname);
|
||||
ot_transfer_out_value (out_tree, &ret_tree);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ot_admin_get_active_deployment (GFile *ostree_dir,
|
||||
char **out_osname,
|
||||
GFile **out_deployment,
|
||||
GCancellable *cancellable,
|
||||
GError **error)
|
||||
{
|
||||
gboolean ret = FALSE;
|
||||
ot_lptrarray GPtrArray *osnames = NULL;
|
||||
ot_lptrarray GPtrArray *deployments = NULL;
|
||||
gs_free char *ret_osname = NULL;
|
||||
gs_unref_object GFile *ret_deployment = NULL;
|
||||
|
||||
if (!ot_admin_get_booted_os (&ret_osname, NULL, cancellable, error))
|
||||
goto out;
|
||||
|
||||
if (ret_osname != NULL)
|
||||
{
|
||||
gs_unref_object GFile *rootfs_path = NULL;
|
||||
gs_unref_object GFileInfo *rootfs_info = NULL;
|
||||
guint32 root_dev;
|
||||
guint64 root_inode;
|
||||
guint i;
|
||||
|
||||
rootfs_path = g_file_new_for_path ("/");
|
||||
rootfs_info = g_file_query_info (rootfs_path, OSTREE_GIO_FAST_QUERYINFO,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
cancellable, error);
|
||||
if (!rootfs_info)
|
||||
goto out;
|
||||
|
||||
root_dev = g_file_info_get_attribute_uint32 (rootfs_info, "unix::device");
|
||||
root_inode = g_file_info_get_attribute_uint64 (rootfs_info, "unix::inode");
|
||||
|
||||
if (!ot_admin_list_deployments (ostree_dir, ret_osname, &deployments,
|
||||
cancellable, error))
|
||||
goto out;
|
||||
|
||||
for (i = 0; i < deployments->len; i++)
|
||||
{
|
||||
GFile *deployment = deployments->pdata[i];
|
||||
gs_unref_object GFileInfo *deployment_info = NULL;
|
||||
guint32 deploy_dev;
|
||||
guint64 deploy_inode;
|
||||
|
||||
deployment_info = g_file_query_info (rootfs_path, OSTREE_GIO_FAST_QUERYINFO,
|
||||
G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
|
||||
cancellable, error);
|
||||
if (!deployment_info)
|
||||
goto out;
|
||||
|
||||
deploy_dev = g_file_info_get_attribute_uint32 (deployment_info, "unix::device");
|
||||
deploy_inode = g_file_info_get_attribute_uint64 (deployment_info, "unix::inode");
|
||||
|
||||
if (root_dev == deploy_dev && root_inode == deploy_inode)
|
||||
{
|
||||
ret_deployment = g_object_ref (deployment);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_assert (ret_deployment != NULL);
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
ot_transfer_out_value (out_osname, &ret_osname);
|
||||
ot_transfer_out_value (out_deployment, &ret_deployment);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ot_admin_get_default_ostree_dir (GFile **out_ostree_dir,
|
||||
GCancellable *cancellable,
|
||||
|
|
|
|||
|
|
@ -42,6 +42,18 @@ gboolean ot_admin_get_previous_deployment (GFile *ostree_dir,
|
|||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean ot_admin_list_deployments (GFile *ostree_dir,
|
||||
const char *osname,
|
||||
GPtrArray **out_deployments,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean ot_admin_get_active_deployment (GFile *ostree_dir,
|
||||
char **out_osname,
|
||||
GFile **out_deployment,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
||||
gboolean ot_admin_get_default_ostree_dir (GFile **out_ostree_dir,
|
||||
GCancellable *cancellable,
|
||||
GError **error);
|
||||
|
|
|
|||
Loading…
Reference in New Issue