static gboolean
append_config_from_boostree_loader_entries (OstreeBootloaderSyslinux  *self,
                                        gboolean               regenerate_default,
                                        int                    bootversion,
                                        GPtrArray             *new_lines,
                                        GCancellable          *cancellable,
                                        GError               **error)
{
  gboolean ret = FALSE;
  gs_unref_ptrarray GPtrArray *boostree_loader_configs = NULL;
  guint i;

  if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boostree_loader_configs,
                                                 cancellable, error))
    goto out;

  for (i = 0; i < boostree_loader_configs->len; i++)
    {
      OstreeBootconfigParser *config = boostree_loader_configs->pdata[i];
      const char *val;

      val = ostree_bootconfig_parser_get (config, "title");
      if (!val)
        val = "(Untitled)";

      if (regenerate_default && i == 0)
        {
          g_ptr_array_add (new_lines, g_strdup_printf ("DEFAULT %s", val));
        }

      g_ptr_array_add (new_lines, g_strdup_printf ("LABEL %s", val));
      
      val = ostree_bootconfig_parser_get (config, "linux");
      if (!val)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "No \"linux\" key in bootloader config");
          goto out;
        }
      g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val));

      val = ostree_bootconfig_parser_get (config, "initrd");
      if (val)
        g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val));

      val = ostree_bootconfig_parser_get (config, "options");
      if (val)
        g_ptr_array_add (new_lines, g_strdup_printf ("\tAPPEND %s", val));
    }

  ret = TRUE;
 out:
  return ret;
}
Exemple #2
0
static char *
get_ostree_kernel_arg_from_config (OstreeBootconfigParser  *config)
{
  const char *options;
  char *ret = NULL;
  char **opts, **iter;

  options = ostree_bootconfig_parser_get (config, "options");
  if (!options)
    return NULL;

  opts = g_strsplit (options, " ", -1);
  for (iter = opts; *iter; iter++)
    {
      const char *opt = *iter;
      if (g_str_has_prefix (opt, "ostree="))
        {
          ret = g_strdup (opt + strlen ("ostree="));
          break;
        }
    }
  g_strfreev (opts);

  return ret;
}
static gboolean
append_config_from_loader_entries (OstreeBootloaderSyslinux  *self,
                                   gboolean               regenerate_default,
                                   int                    bootversion,
                                   GPtrArray             *new_lines,
                                   GCancellable          *cancellable,
                                   GError               **error)
{
  g_autoptr(GPtrArray) loader_configs = NULL;
  if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &loader_configs,
                                                 cancellable, error))
    return FALSE;

  for (guint i = 0; i < loader_configs->len; i++)
    {
      OstreeBootconfigParser *config = loader_configs->pdata[i];
      const char *val = ostree_bootconfig_parser_get (config, "title");
      if (!val)
        val = "(Untitled)";

      if (regenerate_default && i == 0)
        g_ptr_array_add (new_lines, g_strdup_printf ("DEFAULT %s", val));

      g_ptr_array_add (new_lines, g_strdup_printf ("LABEL %s", val));

      val = ostree_bootconfig_parser_get (config, "linux");
      if (!val)
        return glnx_throw (error, "No \"linux\" key in bootloader config");
      g_ptr_array_add (new_lines, g_strdup_printf ("\tKERNEL %s", val));

      val = ostree_bootconfig_parser_get (config, "initrd");
      if (val)
        g_ptr_array_add (new_lines, g_strdup_printf ("\tINITRD %s", val));

      val = ostree_bootconfig_parser_get (config, "devicetree");
      if (val)
        g_ptr_array_add (new_lines, g_strdup_printf ("\tDEVICETREE %s", val));

      val = ostree_bootconfig_parser_get (config, "options");
      if (val)
        g_ptr_array_add (new_lines, g_strdup_printf ("\tAPPEND %s", val));
    }

  return TRUE;
}
Exemple #4
0
static gint
compare_boot_loader_configs (OstreeBootconfigParser     *a,
                             OstreeBootconfigParser     *b)
{
  const char *a_version = ostree_bootconfig_parser_get (a, "version");
  const char *b_version = ostree_bootconfig_parser_get (b, "version");

  if (a_version && b_version)
    {
      int r = strverscmp (a_version, b_version);
      /* Reverse */
      return -r;
    }
  else if (a_version)
    return -1;
  else
    return 1;
}
static gboolean
create_config_from_boot_loader_entries (OstreeBootloaderUboot     *self,
                                        int                    bootversion,
                                        GPtrArray             *new_lines,
                                        GCancellable          *cancellable,
                                        GError               **error)
{
  g_autoptr(GPtrArray) boot_loader_configs = NULL;
  OstreeBootconfigParser *config;
  const char *val;
  g_autofree char *bootdir = NULL;

  if (!_ostree_sysroot_read_boot_loader_configs (self->sysroot, bootversion, &boot_loader_configs,
                                                 cancellable, error))
    return FALSE;

  /* U-Boot doesn't support a menu so just pick the first one since the list is ordered */
  config = boot_loader_configs->pdata[0];

  val = ostree_bootconfig_parser_get (config, "linux");
  if (!val)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "No \"linux\" key in bootloader config");
      return FALSE;
    }
  g_ptr_array_add (new_lines, g_strdup_printf ("kernel_image=%s", val));
  bootdir = strndup (val, strrchr(val, '/') - val);
  g_ptr_array_add (new_lines, g_strdup_printf ("bootdir=%s/", bootdir));

  val = ostree_bootconfig_parser_get (config, "initrd");
  if (val)
    g_ptr_array_add (new_lines, g_strdup_printf ("ramdisk_image=%s", val));

  val = ostree_bootconfig_parser_get (config, "options");
  if (val)
    g_ptr_array_add (new_lines, g_strdup_printf ("bootargs=%s", val));

  return TRUE;
}
Exemple #6
0
static gint
compare_deployments_by_boot_loader_version_reversed (gconstpointer     a_pp,
                                                     gconstpointer     b_pp)
{
  OstreeDeployment *a = *((OstreeDeployment**)a_pp);
  OstreeDeployment *b = *((OstreeDeployment**)b_pp);
  OstreeBootconfigParser *a_bootconfig = ostree_deployment_get_bootconfig (a);
  OstreeBootconfigParser *b_bootconfig = ostree_deployment_get_bootconfig (b);
  const char *a_version = ostree_bootconfig_parser_get (a_bootconfig, "version");
  const char *b_version = ostree_bootconfig_parser_get (b_bootconfig, "version");
  
  if (a_version && b_version)
    {
      int r = strverscmp (a_version, b_version);
      /* Reverse */
      return -r;
    }
  else if (a_version)
    return -1;
  else
    return 1;
}
gboolean
ot_admin_instutil_builtin_set_kargs (int argc, char **argv, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  guint i;
  g_autoptr(GPtrArray) deployments = NULL;
  OstreeDeployment *first_deployment = NULL;
  GOptionContext *context = NULL;
  glnx_unref_object OstreeSysroot *sysroot = NULL;
  __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL;

  context = g_option_context_new ("ARGS - set new kernel command line arguments");

  if (!ostree_admin_option_context_parse (context, options, &argc, &argv,
                                          OSTREE_ADMIN_BUILTIN_FLAG_SUPERUSER | OSTREE_ADMIN_BUILTIN_FLAG_UNLOCKED,
                                          &sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  deployments = ostree_sysroot_get_deployments (sysroot);
  if (deployments->len == 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Unable to find a deployment in sysroot");
      goto out;
    }
  first_deployment = deployments->pdata[0];

  kargs = _ostree_kernel_args_new ();

  /* If they want the current kernel's args, they very likely don't
   * want the ones from the merge.
   */
  if (opt_proc_cmdline)
    {
      if (!_ostree_kernel_args_append_proc_cmdline (kargs, cancellable, error))
        goto out;
    }
  else if (opt_merge)
    {
      OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (first_deployment);
      g_auto(GStrv) previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1);

      _ostree_kernel_args_append_argv (kargs, previous_args);
    }

  if (opt_replace)
    {
      _ostree_kernel_args_replace_argv (kargs, opt_replace);
    }

  if (opt_append)
    {
      _ostree_kernel_args_append_argv (kargs, opt_append);
    }

  for (i = 1; i < argc; i++)
    _ostree_kernel_args_append (kargs, argv[i]);

  {
    g_auto(GStrv) kargs_strv = _ostree_kernel_args_to_strv (kargs);

    if (!ostree_sysroot_deployment_set_kargs (sysroot, first_deployment,
                                              kargs_strv,
                                              cancellable, error))
      goto out;
  }

  ret = TRUE;
 out:
  if (context)
    g_option_context_free (context);
  return ret;
}
gboolean
_ostree_bootloader_grub2_generate_config (OstreeSysroot                 *sysroot,
                                          int                            bootversion,
                                          int                            target_fd,
                                          GCancellable                  *cancellable,
                                          GError                       **error)
{
  gboolean ret = FALSE;
  GString *output = g_string_new ("");
  gs_unref_object GOutputStream *out_stream = NULL;
  gs_unref_ptrarray GPtrArray *loader_configs = NULL;
  guint i;
  gsize bytes_written;
  gboolean is_efi;
  /* So... yeah.  Just going to hardcode these. */
  static const char hardcoded_video[] = "load_video\n"
    "set gfxpayload=keep\n";
  static const char hardcoded_insmods[] = "insmod gzio\n";
  const char *grub2_boot_device_id =
    g_getenv ("GRUB2_BOOT_DEVICE_ID");
  const char *grub2_prepare_root_cache =
    g_getenv ("GRUB2_PREPARE_ROOT_CACHE");

  /* We must have been called via the wrapper script */
  g_assert (grub2_boot_device_id != NULL);
  g_assert (grub2_prepare_root_cache != NULL);

  /* Passed from the parent */
  is_efi = g_getenv ("_OSTREE_GRUB2_IS_EFI") != NULL;

  out_stream = g_unix_output_stream_new (target_fd, FALSE);

  if (!_ostree_sysroot_read_boot_loader_configs (sysroot, bootversion,
                                                 &loader_configs,
                                                 cancellable, error))
    goto out;

  for (i = 0; i < loader_configs->len; i++)
    {
      OstreeBootconfigParser *config = loader_configs->pdata[i];
      const char *title;
      const char *options;
      const char *kernel;
      const char *initrd;
      char *quoted_title = NULL;
      char *uuid = NULL;
      char *quoted_uuid = NULL;

      title = ostree_bootconfig_parser_get (config, "title");
      if (!title)
        title = "(Untitled)";

      kernel = ostree_bootconfig_parser_get (config, "linux");

      quoted_title = g_shell_quote (title);
      uuid = g_strdup_printf ("ostree-%u-%s", (guint)i, grub2_boot_device_id);
      quoted_uuid = g_shell_quote (uuid);
      g_string_append_printf (output, "menuentry %s --class gnu-linux --class gnu --class os --unrestricted %s {\n", quoted_title, quoted_uuid);
      g_free (uuid);
      g_free (quoted_title);
      g_free (quoted_uuid);

      /* Hardcoded sections */
      g_string_append (output, hardcoded_video);
      g_string_append (output, hardcoded_insmods);
      g_string_append (output, grub2_prepare_root_cache);
      g_string_append_c (output, '\n');
      
      if (!kernel)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "No \"linux\" key in bootloader config");
          goto out;
        }
      if (is_efi)
        g_string_append (output, "linuxefi ");
      else
        g_string_append (output, "linux16 ");
      g_string_append (output, kernel);

      options = ostree_bootconfig_parser_get (config, "options");
      if (options)
        {
          g_string_append_c (output, ' ');
          g_string_append (output, options);
        }
      g_string_append_c (output, '\n');

      initrd = ostree_bootconfig_parser_get (config, "initrd");
      if (initrd)
        {
          if (is_efi)
            g_string_append (output, "initrdefi ");
          else
            g_string_append (output, "initrd16 ");
          g_string_append (output, initrd);
          g_string_append_c (output, '\n');
        }

      g_string_append (output, "}\n");
    }

  if (!g_output_stream_write_all (out_stream, output->str, output->len,
                                  &bytes_written, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (output)
    g_string_free (output, TRUE);
  return ret;
}
gboolean
ot_admin_builtin_deploy (int argc, char **argv, OstreeSysroot *sysroot, GCancellable *cancellable, GError **error)
{
  gboolean ret = FALSE;
  const char *refspec;
  GOptionContext *context;
  GKeyFile *origin = NULL;
  gs_unref_object OstreeRepo *repo = NULL;
  gs_unref_ptrarray GPtrArray *new_deployments = NULL;
  gs_unref_object OstreeDeployment *new_deployment = NULL;
  gs_unref_object OstreeDeployment *merge_deployment = NULL;
  gs_free char *revision = NULL;
  __attribute__((cleanup(_ostree_kernel_args_cleanup))) OstreeKernelArgs *kargs = NULL;

  context = g_option_context_new ("REFSPEC - Checkout revision REFSPEC as the new default deployment");

  g_option_context_add_main_entries (context, options, NULL);

  if (!g_option_context_parse (context, &argc, &argv, error))
    goto out;

  if (argc < 2)
    {
      ot_util_usage_error (context, "REF/REV must be specified", error);
      goto out;
    }

  refspec = argv[1];

  if (!ostree_sysroot_load (sysroot, cancellable, error))
    goto out;

  if (!ostree_sysroot_get_repo (sysroot, &repo, cancellable, error))
    goto out;

  /* Find the currently booted deployment, if any; we will ensure it
   * is present in the new deployment list.
   */
  if (!ot_admin_require_booted_deployment_or_osname (sysroot, opt_osname,
                                                     cancellable, error))
    {
      g_prefix_error (error, "Looking for booted deployment: ");
      goto out;
    }

  if (opt_origin_path)
    {
      origin = g_key_file_new ();
      
      if (!g_key_file_load_from_file (origin, opt_origin_path, 0, error))
        goto out;
    }
  else
    {
      origin = ostree_sysroot_origin_new_from_refspec (sysroot, refspec);
    }

  if (!ostree_repo_resolve_rev (repo, refspec, FALSE, &revision, error))
    goto out;

  merge_deployment = ostree_sysroot_get_merge_deployment (sysroot, opt_osname);

  /* Here we perform cleanup of any leftover data from previous
   * partial failures.  This avoids having to call gs_shutil_rm_rf()
   * at random points throughout the process.
   *
   * TODO: Add /ostree/transaction file, and only do this cleanup if
   * we find it.
   */
  if (!ostree_sysroot_cleanup (sysroot, cancellable, error))
    {
      g_prefix_error (error, "Performing initial cleanup: ");
      goto out;
    }

  kargs = _ostree_kernel_args_new ();

  /* If they want the current kernel's args, they very likely don't
   * want the ones from the merge.
   */
  if (opt_kernel_proc_cmdline)
    {
      gs_unref_object GFile *proc_cmdline_path = g_file_new_for_path ("/proc/cmdline");
      gs_free char *proc_cmdline = NULL;
      gsize proc_cmdline_len = 0;
      gs_strfreev char **proc_cmdline_args = NULL;

      if (!g_file_load_contents (proc_cmdline_path, cancellable,
                                 &proc_cmdline, &proc_cmdline_len,
                                 NULL, error))
        goto out;

      g_strchomp (proc_cmdline);

      proc_cmdline_args = g_strsplit (proc_cmdline, " ", -1);
      _ostree_kernel_args_replace_argv (kargs, proc_cmdline_args);
    }
  else if (merge_deployment)
    {
      OstreeBootconfigParser *bootconfig = ostree_deployment_get_bootconfig (merge_deployment);
      gs_strfreev char **previous_args = g_strsplit (ostree_bootconfig_parser_get (bootconfig, "options"), " ", -1);

      _ostree_kernel_args_replace_argv (kargs, previous_args);
    }

  if (opt_kernel_argv)
    {
      _ostree_kernel_args_replace_argv (kargs, opt_kernel_argv);
    }

  if (opt_kernel_argv_append)
    {
      _ostree_kernel_args_append_argv (kargs, opt_kernel_argv_append);
    }

  {
    gs_strfreev char **kargs_strv = _ostree_kernel_args_to_strv (kargs);

    if (!ostree_sysroot_deploy_tree (sysroot,
                                     opt_osname, revision, origin,
                                     merge_deployment, kargs_strv,
                                     &new_deployment,
                                     cancellable, error))
      goto out;
  }

  if (!ostree_sysroot_simple_write_deployment (sysroot, opt_osname,
                                               new_deployment, merge_deployment,
                                               opt_retain ? OSTREE_SYSROOT_SIMPLE_WRITE_DEPLOYMENT_FLAGS_RETAIN : 0,
                                               cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (origin)
    g_key_file_unref (origin);
  if (context)
    g_option_context_free (context);
  return ret;
}