static void _ostree_bootloader_syslinux_finalize (GObject *object) { OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (object); g_clear_object (&self->sysroot); G_OBJECT_CLASS (_ostree_bootloader_syslinux_parent_class)->finalize (object); }
static gboolean _ostree_bootloader_syslinux_query (OstreeBootloader *bootloader, gboolean *out_is_active, GCancellable *cancellable, GError **error) { OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader); *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 gboolean _ostree_bootloader_syslinux_query (OstreeBootloader *bootloader, gboolean *out_is_active, GCancellable *cancellable, GError **error) { OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader); struct stat stbuf; if (!glnx_fstatat_allow_noent (self->sysroot->sysroot_fd, syslinux_config_path, &stbuf, AT_SYMLINK_NOFOLLOW, error)) return FALSE; *out_is_active = (errno == 0); return TRUE; }
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; }
static gboolean _ostree_bootloader_syslinux_write_config (OstreeBootloader *bootloader, int bootversion, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; OstreeBootloaderSyslinux *self = OSTREE_BOOTLOADER_SYSLINUX (bootloader); gs_unref_object GFile *new_config_path = NULL; gs_free char *config_contents = NULL; gs_free char *new_config_contents = NULL; gs_unref_ptrarray GPtrArray *new_lines = NULL; gs_unref_ptrarray GPtrArray *tmp_lines = NULL; gs_free char *kernel_arg = NULL; gboolean saw_default = FALSE; gboolean regenerate_default = FALSE; gboolean parsing_label = FALSE; char **lines = NULL; char **iter; guint i; new_config_path = ot_gfile_resolve_path_printf (self->sysroot->path, "boot/loader.%d/syslinux.cfg", bootversion); /* This should follow the symbolic link to the current bootversion. */ config_contents = gs_file_load_contents_utf8 (self->config_path, cancellable, error); if (!config_contents) goto out; lines = g_strsplit (config_contents, "\n", -1); new_lines = g_ptr_array_new_with_free_func (g_free); tmp_lines = g_ptr_array_new_with_free_func (g_free); /* 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. */ iter = lines; while (TRUE) { char *line = *iter; gboolean skip = FALSE; if (parsing_label && (line == NULL || !g_str_has_prefix (line, "\t"))) { parsing_label = FALSE; if (kernel_arg == NULL) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "No KERNEL argument found after LABEL"); goto out; } /* If this is a non-ostree kernel, just emit the lines * we saw. */ if (!g_str_has_prefix (kernel_arg, "/ostree/")) { for (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) { g_free (line); } else { if (parsing_label) { g_ptr_array_add (tmp_lines, line); } else { g_ptr_array_add (new_lines, line); } } /* Transfer ownership */ *iter = NULL; iter++; } if (!saw_default) regenerate_default = TRUE; if (!append_config_from_boostree_loader_entries (self, regenerate_default, bootversion, new_lines, cancellable, error)) goto out; new_config_contents = _ostree_sysroot_join_lines (new_lines); { gs_unref_bytes GBytes *new_config_contents_bytes = g_bytes_new_static (new_config_contents, strlen (new_config_contents)); if (!ot_gfile_replace_contents_fsync (new_config_path, new_config_contents_bytes, cancellable, error)) goto out; } ret = TRUE; out: g_free (lines); /* Note we freed elements individually */ return ret; }