lib/bootconfig: Add support for multiple initrd keys
authorJonathan Lebon <jonathan@jlebon.com>
Mon, 17 Aug 2020 13:48:16 +0000 (09:48 -0400)
committerJonathan Lebon <jonathan@jlebon.com>
Wed, 30 Sep 2020 17:29:32 +0000 (13:29 -0400)
Prep for actually teaching the rest of the codebase about this.

We keep the primary initrd in the `options` hash table for backwards
compatibility.

apidoc/ostree-sections.txt
src/libostree/libostree-devel.sym
src/libostree/ostree-bootconfig-parser.c
src/libostree/ostree-bootconfig-parser.h

index 66b42233011e0b2e31538fafdbd984ef0942f4e0..c57d7045e70aad71a33af18d6a521ede176be1f8 100644 (file)
@@ -37,6 +37,8 @@ ostree_bootconfig_parser_write
 ostree_bootconfig_parser_write_at
 ostree_bootconfig_parser_set
 ostree_bootconfig_parser_get
+ostree_bootconfig_parser_set_overlay_initrds
+ostree_bootconfig_parser_get_overlay_initrds
 <SUBSECTION Standard>
 OSTREE_BOOTCONFIG_PARSER
 OSTREE_IS_BOOTCONFIG_PARSER
index f74f0e006fde5c3a62d2f621a35fec6dd1de4634..e2d319948c8f9c19c8dd23edd541b5dfd1b01708 100644 (file)
@@ -24,6 +24,8 @@ global:
    */
   ostree_repo_static_delta_execute_offline_with_signature;
   ostree_repo_static_delta_verify_signature;
+  ostree_bootconfig_parser_get_overlay_initrds;
+  ostree_bootconfig_parser_set_overlay_initrds;
 } LIBOSTREE_2020.4;
 
 /* Stub section for the stable release *after* this development one; don't
index 67f9fb5896f993c4c9c9aaf624713706c6e6999c..a36a4118af28d4214fc5d92a354878fb06207241 100644 (file)
@@ -30,6 +30,9 @@ struct _OstreeBootconfigParser
   const char   *separators;
 
   GHashTable   *options;
+
+  /* Additional initrds; the primary initrd is in options. */
+  char        **overlay_initrds;
 };
 
 typedef GObjectClass OstreeBootconfigParserClass;
@@ -50,6 +53,8 @@ ostree_bootconfig_parser_clone (OstreeBootconfigParser *self)
   GLNX_HASH_TABLE_FOREACH_KV (self->options, const char*, k, const char*, v)
     g_hash_table_replace (parser->options, g_strdup (k), g_strdup (v));
 
+  parser->overlay_initrds = g_strdupv (self->overlay_initrds);
+
   return parser;
 }
 
@@ -76,6 +81,8 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser  *self,
   if (!contents)
     return FALSE;
 
+  g_autoptr(GPtrArray) overlay_initrds = NULL;
+
   g_auto(GStrv) lines = g_strsplit (contents, "\n", -1);
   for (char **iter = lines; *iter; iter++)
     {
@@ -87,8 +94,19 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser  *self,
           items = g_strsplit_set (line, self->separators, 2);
           if (g_strv_length (items) == 2 && items[0][0] != '\0')
             {
-              g_hash_table_insert (self->options, items[0], items[1]);
-              g_free (items); /* Transfer ownership */
+              if (g_str_equal (items[0], "initrd") &&
+                  g_hash_table_contains (self->options, "initrd"))
+                {
+                  if (!overlay_initrds)
+                    overlay_initrds = g_ptr_array_new_with_free_func (g_free);
+                  g_ptr_array_add (overlay_initrds, items[1]);
+                  g_free (items[0]);
+                }
+              else
+                {
+                  g_hash_table_insert (self->options, items[0], items[1]);
+                }
+              g_free (items); /* Free container; we stole the elements */
             }
           else
             {
@@ -97,6 +115,12 @@ ostree_bootconfig_parser_parse_at (OstreeBootconfigParser  *self,
         }
     }
 
+  if (overlay_initrds)
+    {
+      g_ptr_array_add (overlay_initrds, NULL);
+      self->overlay_initrds = (char**)g_ptr_array_free (g_steal_pointer (&overlay_initrds), FALSE);
+    }
+
   self->parsed = TRUE;
 
   return TRUE;
@@ -127,6 +151,41 @@ ostree_bootconfig_parser_get (OstreeBootconfigParser  *self,
   return g_hash_table_lookup (self->options, key);
 }
 
+/**
+ * ostree_bootconfig_parser_set_overlay_initrds:
+ * @self: Parser
+ * @initrds: (array zero-terminated=1) (transfer none) (allow-none): Array of overlay
+ *    initrds or %NULL to unset.
+ *
+ * These are rendered as additional `initrd` keys in the final bootloader configs. The
+ * base initrd is part of the primary keys.
+ *
+ * Since: 2020.7
+ */
+void
+ostree_bootconfig_parser_set_overlay_initrds (OstreeBootconfigParser  *self,
+                                              char                   **initrds)
+{
+  g_assert (g_hash_table_contains (self->options, "initrd"));
+  g_strfreev (self->overlay_initrds);
+  self->overlay_initrds = g_strdupv (initrds);
+}
+
+/**
+ * ostree_bootconfig_parser_get_overlay_initrds:
+ * @self: Parser
+ *
+ * Returns: (array zero-terminated=1) (transfer none) (nullable): Array of initrds or %NULL
+ * if none are set.
+ *
+ * Since: 2020.7
+ */
+char**
+ostree_bootconfig_parser_get_overlay_initrds (OstreeBootconfigParser  *self)
+{
+  return self->overlay_initrds;
+}
+
 static void
 write_key (OstreeBootconfigParser    *self,
            GString                   *buf,
@@ -165,6 +224,15 @@ ostree_bootconfig_parser_write_at (OstreeBootconfigParser   *self,
         }
     }
 
+  /* Write overlay initrds */
+  if (self->overlay_initrds && (g_strv_length (self->overlay_initrds) > 0))
+    {
+      /* we should've written the primary initrd already */
+      g_assert (g_hash_table_contains (keys_written, "initrd"));
+      for (char **it = self->overlay_initrds; it && *it; it++)
+        write_key (self, buf, "initrd", *it);
+    }
+
   /* Write unknown fields */
   GLNX_HASH_TABLE_FOREACH_KV (self->options, const char*, k, const char*, v)
     {
@@ -197,6 +265,7 @@ ostree_bootconfig_parser_finalize (GObject *object)
 {
   OstreeBootconfigParser *self = OSTREE_BOOTCONFIG_PARSER (object);
 
+  g_strfreev (self->overlay_initrds);
   g_hash_table_unref (self->options);
 
   G_OBJECT_CLASS (ostree_bootconfig_parser_parent_class)->finalize (object);
index aec0753581b195e793e70f7c34bf4aa595b6bea6..d03c931c55d5d20ad87d975af17bf7c3914292eb 100644 (file)
@@ -73,5 +73,11 @@ _OSTREE_PUBLIC
 const char *ostree_bootconfig_parser_get (OstreeBootconfigParser  *self,
                                           const char      *key);
 
+_OSTREE_PUBLIC
+void ostree_bootconfig_parser_set_overlay_initrds (OstreeBootconfigParser  *self,
+                                                   char                   **initrds);
+
+_OSTREE_PUBLIC
+char** ostree_bootconfig_parser_get_overlay_initrds (OstreeBootconfigParser  *self);
 
 G_END_DECLS