[ostree] admin: Don't delete the running deployment



commit 30d46f9a022f7688796d6c3342f19d8e7186e551
Author: Colin Walters <walters verbum org>
Date:   Mon Mar 4 18:00:23 2013 -0500

    admin: Don't delete the running deployment
    
    https://bugzilla.gnome.org/show_bug.cgi?id=694762

 src/ostree/ot-admin-builtin-prune.c |   74 +---------
 src/ostree/ot-admin-functions.c     |  251 +++++++++++++++++++++++++++++++++++
 src/ostree/ot-admin-functions.h     |   12 ++
 3 files changed, 271 insertions(+), 66 deletions(-)
---
diff --git a/src/ostree/ot-admin-builtin-prune.c b/src/ostree/ot-admin-builtin-prune.c
index 2a3c42f..4d60099 100644
--- a/src/ostree/ot-admin-builtin-prune.c
+++ b/src/ostree/ot-admin-builtin-prune.c
@@ -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, &current_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);
diff --git a/src/ostree/ot-admin-functions.c b/src/ostree/ot-admin-functions.c
index 6cc4ff0..c642ab8 100644
--- a/src/ostree/ot-admin-functions.c
+++ b/src/ostree/ot-admin-functions.c
@@ -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,
diff --git a/src/ostree/ot-admin-functions.h b/src/ostree/ot-admin-functions.h
index c189b24..d74d768 100644
--- a/src/ostree/ot-admin-functions.h
+++ b/src/ostree/ot-admin-functions.h
@@ -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);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]