gboolean ostree_bootconfig_parser_write_at (OstreeBootconfigParser *self, int dfd, const char *path, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GHashTableIter hashiter; gpointer hashkey, hashvalue; GString *buf = g_string_new (""); guint i; g_autoptr(GHashTable) written_overrides = NULL; written_overrides = g_hash_table_new (g_str_hash, g_str_equal); for (i = 0; i < self->lines->len; i++) { GVariant *linedata = self->lines->pdata[i]; const char *key; const char *value; const char *line; g_variant_get (linedata, "(&s&s)", &key, &line); value = g_hash_table_lookup (self->options, key); if (value == NULL) { g_string_append (buf, line); g_string_append_c (buf, '\n'); } else { write_key (self, buf, key, value); g_hash_table_add (written_overrides, (gpointer)key); } } g_hash_table_iter_init (&hashiter, self->options); while (g_hash_table_iter_next (&hashiter, &hashkey, &hashvalue)) { if (g_hash_table_lookup (written_overrides, hashkey)) continue; write_key (self, buf, hashkey, hashvalue); } if (!glnx_file_replace_contents_at (dfd, path, (guint8*)buf->str, buf->len, GLNX_FILE_REPLACE_NODATASYNC, cancellable, error)) goto out; ret = TRUE; out: if (buf) g_string_free (buf, TRUE); return ret; }
static gboolean _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader, int bootversion, GCancellable *cancellable, GError **error) { OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader); g_autofree char *new_config_path = g_strdup_printf ("boot/loader.%d/syslinux.cfg", bootversion); /* This should follow the symbolic link to the current bootversion. */ g_autofree char *config_contents = glnx_file_get_contents_utf8_at (self->sysroot->sysroot_fd, syslinux_config_path, NULL, cancellable, error); if (!config_contents) return FALSE; g_auto(GStrv) lines = g_strsplit (config_contents, "\n", -1); g_autoptr(GPtrArray) new_lines = g_ptr_array_new_with_free_func (g_free); g_autoptr(GPtrArray) tmp_lines = g_ptr_array_new_with_free_func (g_free); g_autofree char *kernel_arg = NULL; gboolean saw_default = FALSE; gboolean regenerate_default = FALSE; gboolean parsing_label = FALSE; /* Note special iteration condition here; we want to also loop one * more time at the end where line = NULL to ensure we finish off * processing the last LABEL. */ for (char **iter = lines; iter; iter++) { const char *line = *iter; gboolean skip = FALSE; if (parsing_label && (line == NULL || !g_str_has_prefix (line, "\t"))) { parsing_label = FALSE; if (kernel_arg == NULL) return glnx_throw (error, "No KERNEL argument found after LABEL"); /* If this is a non-ostree kernel, just emit the lines * we saw. */ if (!g_str_has_prefix (kernel_arg, "/ostree/")) { for (guint i = 0; i < tmp_lines->len; i++) { g_ptr_array_add (new_lines, tmp_lines->pdata[i]); tmp_lines->pdata[i] = NULL; /* Transfer ownership */ } } else { /* Otherwise, we drop the config on the floor - it * will be regenerated. */ g_ptr_array_set_size (tmp_lines, 0); } } if (line == NULL) break; if (!parsing_label && (g_str_has_prefix (line, "LABEL "))) { parsing_label = TRUE; g_ptr_array_set_size (tmp_lines, 0); } else if (parsing_label && g_str_has_prefix (line, "\tKERNEL ")) { g_free (kernel_arg); kernel_arg = g_strdup (line + strlen ("\tKERNEL ")); } else if (!parsing_label && (g_str_has_prefix (line, "DEFAULT "))) { saw_default = TRUE; /* XXX Searching for patterns in the title is rather brittle, * but this hack is at least noted in the code that builds * the title to hopefully avoid regressions. */ if (g_str_has_prefix (line, "DEFAULT ostree:") || /* old format */ strstr (line, "(ostree") != NULL) /* new format */ regenerate_default = TRUE; skip = TRUE; } if (!skip) { if (parsing_label) g_ptr_array_add (tmp_lines, g_strdup (line)); else g_ptr_array_add (new_lines, g_strdup (line)); } } if (!saw_default) regenerate_default = TRUE; if (!append_config_from_loader_entries (self, regenerate_default, bootversion, new_lines, cancellable, error)) return FALSE; g_autofree char *new_config_contents = _ostree_sysroot_join_lines (new_lines); if (!glnx_file_replace_contents_at (self->sysroot->sysroot_fd, new_config_path, (guint8*)new_config_contents, strlen (new_config_contents), GLNX_FILE_REPLACE_DATASYNC_NEW, cancellable, error)) return FALSE; return TRUE; }