[ostree/wip/grub2-efi: 3/3] WIP: GRUB2+EFI



commit fbeccb95fd0a694a296bfc576b9893afb50b65fa
Author: Colin Walters <walters verbum org>
Date:   Fri Oct 17 20:30:33 2014 -0400

    WIP: GRUB2+EFI

 src/libostree/ostree-bootloader-grub2.c    |   52 +++++++++++++++++++++++----
 src/libostree/ostree-bootloader-syslinux.c |    8 +++-
 src/libostree/ostree-bootloader-uboot.c    |    8 +++-
 src/libostree/ostree-bootloader.c          |    7 +++-
 src/libostree/ostree-bootloader.h          |   10 ++++-
 src/libostree/ostree-sysroot-deploy.c      |    5 ++-
 src/libostree/ostree-sysroot-private.h     |    5 ++-
 src/libostree/ostree-sysroot.c             |   53 ++++++++++++++++++----------
 8 files changed, 111 insertions(+), 37 deletions(-)
---
diff --git a/src/libostree/ostree-bootloader-grub2.c b/src/libostree/ostree-bootloader-grub2.c
index 02a9a9f..faeaa66 100644
--- a/src/libostree/ostree-bootloader-grub2.c
+++ b/src/libostree/ostree-bootloader-grub2.c
@@ -36,7 +36,10 @@ struct _OstreeBootloaderGrub2
   OstreeSysroot  *sysroot;
   GFile          *config_path_bios;
   GFile          *config_path_efi_marker;
+  GFile          *config_path_efi_dir;
   GFile          *config_path_efi_dest;
+  GFile          *config_path_efi_new;
+  GFile          *config_path_efi_old;
   gboolean        is_efi;
 };
 
@@ -47,14 +50,22 @@ G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderGrub2, _ostree_bootloader_grub2, G_TYPE
                          G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, 
_ostree_bootloader_grub2_bootloader_iface_init));
 
 static gboolean
-_ostree_bootloader_grub2_query (OstreeBootloader *bootloader)
+_ostree_bootloader_grub2_query (OstreeBootloader *bootloader,
+                                gboolean         *out_is_active,
+                                GCancellable     *cancellable,
+                                GError          **error)
 {
+  gboolean ret = FALSE;
   OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
   gs_unref_object GFile *marker_parent = NULL;
   gs_unref_object GFileInfo *file_info = NULL;
 
   if (g_file_query_exists (self->config_path_bios, NULL))
-    return TRUE;
+    {
+      *out_is_active = TRUE;
+      ret = TRUE;
+      goto out;
+    }
 
   marker_parent = g_file_get_parent (self->config_path_efi_marker);
   if (!ot_gfile_query_info_allow_noent (self->config_path_efi_marker, "standard::symlink-target",
@@ -67,10 +78,17 @@ _ostree_bootloader_grub2_query (OstreeBootloader *bootloader)
       const char *target = g_file_info_get_symlink_target (file_info);
       self->is_efi = TRUE;
       self->config_path_efi_dest = g_file_resolve_relative_path (marker_parent, target);
-      return TRUE;
+      self->config_path_efi_dir = g_file_get_parent (self->config_path_efi_dest);
+      self->config_path_efi_new = g_file_get_child (self->config_path_efi_dir, "grub.cfg.new");
+      self->config_path_efi_old = g_file_get_child (self->config_path_efi_dir, "grub.cfg.old");
+      *out_is_active = TRUE;
     }
+  else
+    *out_is_active = FALSE;
 
-  return FALSE;
+  ret = TRUE;
+ out:
+  return ret;
 }
 
 static const char *
@@ -197,6 +215,7 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader      *bootloader,
   OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
   gboolean ret = FALSE;
   gs_unref_object GFile *efi_new_config_temp = NULL;
+  gs_unref_object GFile *efi_orig_config = NULL;
   gs_unref_object GFile *new_config_path = NULL;
   gs_unref_object GSSubprocessContext *procctx = NULL;
   gs_unref_object GSSubprocess *proc = NULL;
@@ -205,8 +224,9 @@ _ostree_bootloader_grub2_write_config (OstreeBootloader      *bootloader,
 
   if (self->is_efi)
     {
-      new_config_path = ot_gfile_resolve_path_printf (self->sysroot->path, "boot/loader.%d/grub.cfg",
-                                                      bootversion);
+      if (!ot_gfile_ensure_unlinked (self->config_path_efi_new, cancellable, error))
+        goto out;
+      new_config_path = g_object_ref (self->config_path_efi_new);
     }
   else
     {
@@ -246,8 +266,23 @@ rm -f ${grub_cfg}.new
 
   if (self->is_efi)
     {
-      gs_unref_object GFile *config_efi_dest_dir = g_file_get_parent (self->config_path_efi_dest);
-      gs_unref_object GFile *config_efi_tmp = g_file_get_child (config_efi_dest_dir, "
+      /* copy current to old */
+      if (!ot_gfile_ensure_unlinked (self->config_path_efi_old, cancellable, error))
+        goto out;
+      if (!g_file_copy (self->config_path_efi_dest, self->config_path_efi_old,
+                        G_FILE_COPY_OVERWRITE, cancellable, NULL, NULL, error))
+        goto out;
+      if (!ot_gfile_ensure_unlinked (self->config_path_efi_old, cancellable, error))
+        goto out;
+
+      /* NOTE: NON-ATOMIC REPLACEMENT; WE can't do anything else on FAT;
+       * see https://bugzilla.gnome.org/show_bug.cgi?id=724246
+       */
+      if (!ot_gfile_ensure_unlinked (self->config_path_efi_dest, cancellable, error))
+        goto out;
+      if (!gs_file_rename (self->config_path_efi_new, self->config_path_efi_dest,
+                           cancellable, error))
+        goto out;
     }
   
   ret = TRUE;
@@ -258,6 +293,7 @@ rm -f ${grub_cfg}.new
 static gboolean
 _ostree_bootloader_grub2_is_atomic (OstreeBootloader      *bootloader) 
 {
+  OstreeBootloaderGrub2 *self = OSTREE_BOOTLOADER_GRUB2 (bootloader);
   return !self->is_efi;
 }
 
diff --git a/src/libostree/ostree-bootloader-syslinux.c b/src/libostree/ostree-bootloader-syslinux.c
index 0934bb8..86b66fa 100644
--- a/src/libostree/ostree-bootloader-syslinux.c
+++ b/src/libostree/ostree-bootloader-syslinux.c
@@ -42,11 +42,15 @@ G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderSyslinux, _ostree_bootloader_syslinux,
                          G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, 
_ostree_bootloader_syslinux_bootloader_iface_init));
 
 static gboolean
-_ostree_bootloader_syslinux_query (OstreeBootloader *bootloader)
+_ostree_bootloader_syslinux_query (OstreeBootloader *bootloader,
+                                   gboolean         *out_is_active,
+                                   GCancellable     *cancellable,
+                                   GError          **error)
 {
   OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader);
 
-  return g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == 
G_FILE_TYPE_SYMBOLIC_LINK;
+  *out_is_active = g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == 
G_FILE_TYPE_SYMBOLIC_LINK;
+  return TRUE;
 }
 
 static const char *
diff --git a/src/libostree/ostree-bootloader-uboot.c b/src/libostree/ostree-bootloader-uboot.c
index cd25e56..84c5cdd 100644
--- a/src/libostree/ostree-bootloader-uboot.c
+++ b/src/libostree/ostree-bootloader-uboot.c
@@ -46,11 +46,15 @@ G_DEFINE_TYPE_WITH_CODE (OstreeBootloaderUboot, _ostree_bootloader_uboot, G_TYPE
                          G_IMPLEMENT_INTERFACE (OSTREE_TYPE_BOOTLOADER, 
_ostree_bootloader_uboot_bootloader_iface_init));
 
 static gboolean
-_ostree_bootloader_uboot_query (OstreeBootloader *bootloader)
+_ostree_bootloader_uboot_query (OstreeBootloader *bootloader,
+                                gboolean         *out_is_active,
+                                GCancellable     *cancellable,
+                                GError          **error) 
 {
   OstreeBootloaderUboot *self = OSTREE_BOOTLOADER_UBOOT (bootloader);
 
-  return g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == 
G_FILE_TYPE_SYMBOLIC_LINK;
+  *out_is_active = g_file_query_file_type (self->config_path, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == 
G_FILE_TYPE_SYMBOLIC_LINK;
+  return TRUE;
 }
 
 static const char *
diff --git a/src/libostree/ostree-bootloader.c b/src/libostree/ostree-bootloader.c
index 3721999..c95674c 100644
--- a/src/libostree/ostree-bootloader.c
+++ b/src/libostree/ostree-bootloader.c
@@ -30,11 +30,14 @@ _ostree_bootloader_default_init (OstreeBootloaderInterface *iface)
 }
 
 gboolean
-_ostree_bootloader_query (OstreeBootloader  *self)
+_ostree_bootloader_query (OstreeBootloader *self,
+                          gboolean         *out_is_active,
+                          GCancellable     *cancellable,
+                          GError          **error)
 {
   g_return_val_if_fail (OSTREE_IS_BOOTLOADER (self), FALSE);
 
-  return OSTREE_BOOTLOADER_GET_IFACE (self)->query (self);
+  return OSTREE_BOOTLOADER_GET_IFACE (self)->query (self, out_is_active, cancellable, error);
 }
 
 /**
diff --git a/src/libostree/ostree-bootloader.h b/src/libostree/ostree-bootloader.h
index a84ce6b..cbb25aa 100644
--- a/src/libostree/ostree-bootloader.h
+++ b/src/libostree/ostree-bootloader.h
@@ -37,7 +37,10 @@ struct _OstreeBootloaderInterface
   GTypeInterface g_iface;
 
   /* virtual functions */
-  gboolean             (* query)                  (OstreeBootloader  *self);
+  gboolean             (* query)                  (OstreeBootloader *bootloader,
+                                                   gboolean         *out_is_active,
+                                                   GCancellable     *cancellable,
+                                                   GError          **error);
   const char *         (* get_name)               (OstreeBootloader  *self);
   gboolean             (* write_config)           (OstreeBootloader  *self,
                                                    int            bootversion,
@@ -48,7 +51,10 @@ struct _OstreeBootloaderInterface
 
 GType _ostree_bootloader_get_type (void) G_GNUC_CONST;
 
-gboolean _ostree_bootloader_query (OstreeBootloader *self);
+gboolean _ostree_bootloader_query (OstreeBootloader *bootloader,
+                                   gboolean         *out_is_active,
+                                   GCancellable     *cancellable,
+                                   GError          **error);
 
 const char *_ostree_bootloader_get_name (OstreeBootloader  *self);
 
diff --git a/src/libostree/ostree-sysroot-deploy.c b/src/libostree/ostree-sysroot-deploy.c
index 9934e0f..8d9fe0c 100644
--- a/src/libostree/ostree-sysroot-deploy.c
+++ b/src/libostree/ostree-sysroot-deploy.c
@@ -1598,9 +1598,12 @@ ostree_sysroot_write_deployments (OstreeSysroot     *self,
   else
     {
       int new_bootversion = self->bootversion ? 0 : 1;
-      gs_unref_object OstreeBootloader *bootloader = _ostree_sysroot_query_bootloader (self);
+      gs_unref_object OstreeBootloader *bootloader = NULL;
       gs_unref_object GFile *new_loader_entries_dir = NULL;
 
+      if (!_ostree_sysroot_query_bootloader (self, &bootloader, cancellable, error))
+        goto out;
+
       new_loader_entries_dir = ot_gfile_resolve_path_printf (self->path, "boot/loader.%d/entries",
                                                              new_bootversion);
       if (!gs_shutil_rm_rf (new_loader_entries_dir, cancellable, error))
diff --git a/src/libostree/ostree-sysroot-private.h b/src/libostree/ostree-sysroot-private.h
index 0857e4c..28b0feb 100644
--- a/src/libostree/ostree-sysroot-private.h
+++ b/src/libostree/ostree-sysroot-private.h
@@ -75,7 +75,10 @@ _ostree_sysroot_get_devino (GFile         *path,
 
 char *_ostree_sysroot_join_lines (GPtrArray  *lines);
 
-OstreeBootloader *_ostree_sysroot_query_bootloader (OstreeSysroot         *sysroot);
+gboolean _ostree_sysroot_query_bootloader (OstreeSysroot     *sysroot,
+                                           OstreeBootloader **out_bootloader,
+                                           GCancellable      *cancellable,
+                                           GError           **error);
 
 G_END_DECLS
 
diff --git a/src/libostree/ostree-sysroot.c b/src/libostree/ostree-sysroot.c
index 160fc07..60d5cb6 100644
--- a/src/libostree/ostree-sysroot.c
+++ b/src/libostree/ostree-sysroot.c
@@ -846,29 +846,44 @@ ostree_sysroot_get_repo (OstreeSysroot         *self,
 /**
  * ostree_sysroot_query_bootloader:
  * @sysroot: Sysroot
- *
- * Returns: (transfer full): Currently active bootloader in @sysroot
+ * @out_bootloader: (out) (transfer full) (allow-none): Return location for bootloader, may be %NULL
+ * @cancellable: Cancellable
+ * @error: Error
  */
-OstreeBootloader *
-_ostree_sysroot_query_bootloader (OstreeSysroot *self)
+gboolean
+_ostree_sysroot_query_bootloader (OstreeSysroot     *sysroot,
+                                  OstreeBootloader **out_bootloader,
+                                  GCancellable      *cancellable,
+                                  GError           **error)
 {
-  OstreeBootloaderSyslinux *syslinux;
-  OstreeBootloaderUboot    *uboot;
-  OstreeBootloaderGrub2    *grub2;
-
-  syslinux = _ostree_bootloader_syslinux_new (self);
-  if (_ostree_bootloader_query ((OstreeBootloader*)syslinux))
-    return (OstreeBootloader*) (syslinux);
-
-  grub2 = _ostree_bootloader_grub2_new (self);
-  if (_ostree_bootloader_query ((OstreeBootloader*)grub2))
-    return (OstreeBootloader*) (grub2);
+  gboolean ret = FALSE;
+  gboolean is_active;
+  gs_unref_object OstreeBootloader *ret_loader = NULL;
 
-  uboot = _ostree_bootloader_uboot_new (self);
-  if (_ostree_bootloader_query ((OstreeBootloader*)uboot))
-    return (OstreeBootloader*) (uboot);
+  ret_loader = (OstreeBootloader*)_ostree_bootloader_syslinux_new (sysroot);
+  if (!_ostree_bootloader_query (ret_loader, &is_active,
+                                 cancellable, error))
+    goto out;
+  if (!is_active)
+    {
+      g_object_unref (ret_loader);
+      ret_loader = (OstreeBootloader*)_ostree_bootloader_grub2_new (sysroot);
+      if (!_ostree_bootloader_query (ret_loader, &is_active,
+                                     cancellable, error))
+        goto out;
+    }
+  if (!is_active)
+    {
+      g_object_unref (ret_loader);
+      ret_loader = (OstreeBootloader*)_ostree_bootloader_uboot_new (sysroot);
+      if (!_ostree_bootloader_query (ret_loader, &is_active, cancellable, error))
+        goto out;
+    }
 
-  return NULL;
+  ret = TRUE;
+  gs_transfer_out_value (out_bootloader, &ret_loader);
+ out:
+  return ret;
 }
 
 char *


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