コード例 #1
0
static gboolean
do_kernel_prep (GFile         *yumroot,
                JsonObject    *treefile,
                GCancellable  *cancellable,
                GError       **error)
{
  gboolean ret = FALSE;
  gs_unref_object GFile *bootdir = 
    g_file_get_child (yumroot, "boot");
  gs_unref_object GFile *kernel_path = NULL;
  gs_unref_object GFile *initramfs_path = NULL;
  const char *boot_checksum_str = NULL;
  GChecksum *boot_checksum = NULL;
  const char *kname;
  const char *kver;

  if (!find_kernel_and_initramfs_in_bootdir (bootdir, &kernel_path,
                                             &initramfs_path,
                                             cancellable, error))
    goto out;

  if (initramfs_path)
    {
      g_print ("Removing RPM-generated '%s'\n",
               gs_file_get_path_cached (initramfs_path));
      if (!gs_shutil_rm_rf (initramfs_path, cancellable, error))
        goto out;
    }

  kname = gs_file_get_basename_cached (kernel_path);
  kver = strchr (kname, '-');
  g_assert (kver);
  kver += 1;

  /* OSTree needs to own this */
  {
    gs_unref_object GFile *loaderdir = g_file_get_child (bootdir, "loader");
    if (!gs_shutil_rm_rf (loaderdir, cancellable, error))
      goto out;
  }

  {
    char *child_argv[] = { "depmod", (char*)kver, NULL };
    if (!run_sync_in_root (yumroot, "/usr/sbin/depmod", child_argv, error))
      goto out;
  }

  /* Copy of code from gnome-continuous; yes, we hardcode
     the machine id for now, because distributing pre-generated
     initramfs images with dracut/systemd at the moment
     effectively requires this.
     http://lists.freedesktop.org/archives/systemd-devel/2013-July/011770.html
  */
  g_print ("Hardcoding machine-id\n");
  {
    const char *hardcoded_machine_id = "45bb3b96146aa94f299b9eb43646eb35\n";
    gs_unref_object GFile *machineid_path =
      g_file_resolve_relative_path (yumroot, "etc/machine-id");
    if (!g_file_replace_contents (machineid_path, hardcoded_machine_id,
                                  strlen (hardcoded_machine_id),
                                  NULL, FALSE, 0, NULL,
                                  cancellable, error))
      goto out;
  }

  {
    gs_unref_ptrarray GPtrArray *dracut_argv = g_ptr_array_new ();

    g_ptr_array_add (dracut_argv, "dracut");
    g_ptr_array_add (dracut_argv, "-v");
    g_ptr_array_add (dracut_argv, "--tmpdir=/tmp");
    g_ptr_array_add (dracut_argv, "-f");
    g_ptr_array_add (dracut_argv, "/var/tmp/initramfs.img");
    g_ptr_array_add (dracut_argv, (char*)kver);

    if (json_object_has_member (treefile, "initramfs-args"))
      {
        guint i, len;
        JsonArray *initramfs_args;

        initramfs_args = json_object_get_array_member (treefile, "initramfs-args");
        len = json_array_get_length (initramfs_args);

        for (i = 0; i < len; i++)
          {
            const char *arg = _rpmostree_jsonutil_array_require_string_element (initramfs_args, i, error);
            if (!arg)
              goto out;
            g_ptr_array_add (dracut_argv, (char*)arg);
          }
      }

    g_ptr_array_add (dracut_argv, NULL);

    if (!run_sync_in_root (yumroot, "/usr/sbin/dracut", (char**)dracut_argv->pdata, error))
      goto out;
  }

  initramfs_path = g_file_resolve_relative_path (yumroot, "var/tmp/initramfs.img");
  if (!g_file_query_exists (initramfs_path, NULL))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Dracut failed to generate '%s'",
                   gs_file_get_path_cached (initramfs_path));
      goto out;
    }

  {
    gs_free char *initramfs_name = g_strconcat ("initramfs-", kver, ".img", NULL);
    gs_unref_object GFile *initramfs_dest =
      g_file_get_child (bootdir, initramfs_name);

    if (!gs_file_rename (initramfs_path, initramfs_dest,
                         cancellable, error))
      goto out;

    /* Transfer ownership */
    g_object_unref (initramfs_path);
    initramfs_path = initramfs_dest;
    initramfs_dest = NULL;
  }

  boot_checksum = g_checksum_new (G_CHECKSUM_SHA256);
  if (!_rpmostree_util_update_checksum_from_file (boot_checksum, kernel_path,
                                                  cancellable, error))
    goto out;
  if (!_rpmostree_util_update_checksum_from_file (boot_checksum, initramfs_path,
                                                  cancellable, error))
    goto out;

  boot_checksum_str = g_checksum_get_string (boot_checksum);
  
  {
    gs_free char *new_kernel_name =
      g_strconcat (gs_file_get_basename_cached (kernel_path), "-",
                   boot_checksum_str, NULL);
    gs_unref_object GFile *new_kernel_path =
      g_file_get_child (bootdir, new_kernel_name);
    gs_free char *new_initramfs_name =
      g_strconcat (gs_file_get_basename_cached (initramfs_path), "-",
                   boot_checksum_str, NULL);
    gs_unref_object GFile *new_initramfs_path =
      g_file_get_child (bootdir, new_initramfs_name);

    if (!gs_file_rename (kernel_path, new_kernel_path,
                         cancellable, error))
      goto out;
    if (!gs_file_rename (initramfs_path, new_initramfs_path,
                         cancellable, error))
      goto out;
  }

  ret = TRUE;
 out:
  if (boot_checksum) g_checksum_free (boot_checksum);
  return ret;
}
コード例 #2
0
static gboolean
do_kernel_prep (GFile         *yumroot,
                JsonObject    *treefile,
                GCancellable  *cancellable,
                GError       **error)
{
    gboolean ret = FALSE;
    gs_unref_object GFile *bootdir =
        g_file_get_child (yumroot, "boot");
    gs_unref_object GFile *kernel_path = NULL;
    gs_unref_object GFile *initramfs_path = NULL;
    const char *boot_checksum_str = NULL;
    GChecksum *boot_checksum = NULL;
    g_autofree char *kver = NULL;

    if (!find_kernel_and_initramfs_in_bootdir (bootdir, &kernel_path,
            &initramfs_path,
            cancellable, error))
        goto out;

    if (kernel_path == NULL)
    {
        gs_unref_object GFile *mod_dir = g_file_resolve_relative_path (yumroot, "usr/lib/modules");
        gs_unref_object GFile *modversion_dir = NULL;

        if (!find_ensure_one_subdirectory (mod_dir, &modversion_dir, cancellable, error))
            goto out;

        if (modversion_dir)
        {
            kver = g_file_get_basename (modversion_dir);
            if (!find_kernel_and_initramfs_in_bootdir (modversion_dir, &kernel_path,
                    &initramfs_path,
                    cancellable, error))
                goto out;
        }
    }

    if (kernel_path == NULL)
    {
        g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                     "Unable to find kernel (vmlinuz) in /boot or /usr/lib/modules");
        goto out;
    }

    if (initramfs_path)
    {
        g_print ("Removing RPM-generated '%s'\n",
                 gs_file_get_path_cached (initramfs_path));
        if (!gs_shutil_rm_rf (initramfs_path, cancellable, error))
            goto out;
    }

    if (!kver)
    {
        const char *kname = gs_file_get_basename_cached (kernel_path);
        const char *kver_p;

        kver_p = strchr (kname, '-');
        g_assert (kver_p);
        kver = g_strdup (kver_p + 1);
    }

    /* OSTree needs to own this */
    {
        gs_unref_object GFile *loaderdir = g_file_get_child (bootdir, "loader");
        if (!gs_shutil_rm_rf (loaderdir, cancellable, error))
            goto out;
    }

    {
        char *child_argv[] = { "depmod", (char*)kver, NULL };
        if (!run_sync_in_root (yumroot, "depmod", child_argv, error))
            goto out;
    }

    /* Ensure the /etc/machine-id file is present and empty. Apparently systemd
       doesn't work when the file is missing (as of systemd-219-9.fc22) but it is
       correctly populated if the file is there.  */
    g_print ("Creating empty machine-id\n");
    {
        const char *hardcoded_machine_id = "";
        gs_unref_object GFile *machineid_path =
            g_file_resolve_relative_path (yumroot, "etc/machine-id");
        if (!g_file_replace_contents (machineid_path, hardcoded_machine_id,
                                      strlen (hardcoded_machine_id),
                                      NULL, FALSE, 0, NULL,
                                      cancellable, error))
            goto out;
    }

    {
        gboolean reproducible;
        gs_unref_ptrarray GPtrArray *dracut_argv = g_ptr_array_new ();

        if (!dracut_supports_reproducible (yumroot, &reproducible, cancellable, error))
            goto out;

        g_ptr_array_add (dracut_argv, "dracut");
        g_ptr_array_add (dracut_argv, "-v");
        if (reproducible)
        {
            g_ptr_array_add (dracut_argv, "--reproducible");
            g_ptr_array_add (dracut_argv, "--gzip");
        }
        g_ptr_array_add (dracut_argv, "--tmpdir=/tmp");
        g_ptr_array_add (dracut_argv, "-f");
        g_ptr_array_add (dracut_argv, "/var/tmp/initramfs.img");
        g_ptr_array_add (dracut_argv, (char*)kver);

        if (json_object_has_member (treefile, "initramfs-args"))
        {
            guint i, len;
            JsonArray *initramfs_args;

            initramfs_args = json_object_get_array_member (treefile, "initramfs-args");
            len = json_array_get_length (initramfs_args);

            for (i = 0; i < len; i++)
            {
                const char *arg = _rpmostree_jsonutil_array_require_string_element (initramfs_args, i, error);
                if (!arg)
                    goto out;
                g_ptr_array_add (dracut_argv, (char*)arg);
            }
        }

        g_ptr_array_add (dracut_argv, NULL);

        if (!run_sync_in_root (yumroot, "dracut", (char**)dracut_argv->pdata, error))
            goto out;
    }

    initramfs_path = g_file_resolve_relative_path (yumroot, "var/tmp/initramfs.img");
    if (!g_file_query_exists (initramfs_path, NULL))
    {
        g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                     "Dracut failed to generate '%s'",
                     gs_file_get_path_cached (initramfs_path));
        goto out;
    }

    {
        gs_free char *initramfs_name = g_strconcat ("initramfs-", kver, ".img", NULL);
        gs_unref_object GFile *initramfs_dest =
            g_file_get_child (bootdir, initramfs_name);

        if (!gs_file_rename (initramfs_path, initramfs_dest,
                             cancellable, error))
            goto out;

        /* Transfer ownership */
        g_object_unref (initramfs_path);
        initramfs_path = initramfs_dest;
        initramfs_dest = NULL;
    }

    boot_checksum = g_checksum_new (G_CHECKSUM_SHA256);
    if (!_rpmostree_util_update_checksum_from_file (boot_checksum, kernel_path,
            cancellable, error))
        goto out;
    if (!_rpmostree_util_update_checksum_from_file (boot_checksum, initramfs_path,
            cancellable, error))
        goto out;

    boot_checksum_str = g_checksum_get_string (boot_checksum);

    {
        gs_free char *new_kernel_name =
            g_strconcat (gs_file_get_basename_cached (kernel_path), "-",
                         boot_checksum_str, NULL);
        gs_unref_object GFile *new_kernel_path =
            g_file_get_child (bootdir, new_kernel_name);
        gs_free char *new_initramfs_name =
            g_strconcat (gs_file_get_basename_cached (initramfs_path), "-",
                         boot_checksum_str, NULL);
        gs_unref_object GFile *new_initramfs_path =
            g_file_get_child (bootdir, new_initramfs_name);

        if (!gs_file_rename (kernel_path, new_kernel_path,
                             cancellable, error))
            goto out;
        if (!gs_file_rename (initramfs_path, new_initramfs_path,
                             cancellable, error))
            goto out;
    }

    ret = TRUE;
out:
    if (boot_checksum) g_checksum_free (boot_checksum);
    return ret;
}
コード例 #3
0
static gboolean
compute_checksum_from_treefile_and_goal (RpmOstreeTreeComposeContext   *self,
                                         HyGoal                         goal,
                                         GFile                         *contextdir,
                                         JsonArray                     *add_files,
                                         char                        **out_checksum,
                                         GError                      **error)
{
  gboolean ret = FALSE;
  g_autofree char *ret_checksum = NULL;
  GChecksum *checksum = g_checksum_new (G_CHECKSUM_SHA256);
  
  /* Hash in the raw treefile; this means reordering the input packages
   * or adding a comment will cause a recompose, but let's be conservative
   * here.
   */
  { gsize len;
    const guint8* buf = g_bytes_get_data (self->serialized_treefile, &len);

    g_checksum_update (checksum, buf, len);
  }

  if (add_files)
    {
      guint i, len = json_array_get_length (add_files);
      for (i = 0; i < len; i++)
        {
          g_autoptr(GFile) srcfile = NULL;
          const char *src, *dest;
          JsonArray *add_el = json_array_get_array_element (add_files, i);
          g_autoptr(GFile) child = NULL;

          if (!add_el)
            {
              g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                           "Element in add-files is not an array");
              goto out;
            }
          src = _rpmostree_jsonutil_array_require_string_element (add_el, 0, error);
          if (!src)
            goto out;

          dest = _rpmostree_jsonutil_array_require_string_element (add_el, 1, error);
          if (!dest)
            goto out;

          srcfile = g_file_resolve_relative_path (contextdir, src);

          if (!_rpmostree_util_update_checksum_from_file (checksum,
                                                          srcfile,
                                                          NULL,
                                                          error))
            goto out;

          g_checksum_update (checksum, (const guint8 *) dest, strlen (dest));
        }

    }

  /* FIXME; we should also hash the post script */

  /* Hash in each package */
  rpmostree_dnf_add_checksum_goal (checksum, goal);

  ret_checksum = g_strdup (g_checksum_get_string (checksum));

  ret = TRUE;
 out:
  gs_transfer_out_value (out_checksum, &ret_checksum);
  if (checksum) g_checksum_free (checksum);
  return ret;
}