Example #1
0
/**
 * ot_gfile_ensure_unlinked:
 *
 * Like gs_file_unlink(), but return successfully if the file doesn't
 * exist.
 */
gboolean
ot_gfile_ensure_unlinked (GFile         *path,
                          GCancellable  *cancellable,
                          GError       **error)
{
  gboolean ret = FALSE;
  GError *temp_error = NULL;

  if (!gs_file_unlink (path, cancellable, &temp_error))
    {
      if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
        {
          g_clear_error (&temp_error);
        }
      else
        {
          g_propagate_error (error, temp_error);
          goto out;
        }
    }
  
  ret = TRUE;
 out:
  return ret;
}
Example #2
0
/**
 * ostree_repo_checkout_gc:
 * @self: Repo
 * @cancellable: Cancellable
 * @error: Error
 *
 * Call this after finishing a succession of checkout operations; it
 * will delete any currently-unused uncompressed objects from the
 * cache.
 */
gboolean
ostree_repo_checkout_gc (OstreeRepo        *self,
                         GCancellable      *cancellable,
                         GError           **error)
{
  gboolean ret = FALSE;
  g_autoptr(GHashTable) to_clean_dirs = NULL;
  GHashTableIter iter;
  gpointer key, value;

  g_mutex_lock (&self->cache_lock);
  to_clean_dirs = self->updated_uncompressed_dirs;
  self->updated_uncompressed_dirs = g_hash_table_new (NULL, NULL);
  g_mutex_unlock (&self->cache_lock);

  if (to_clean_dirs)
    g_hash_table_iter_init (&iter, to_clean_dirs);
  while (to_clean_dirs && g_hash_table_iter_next (&iter, &key, &value))
    {
      g_autoptr(GFile) objdir = NULL;
      g_autoptr(GFileEnumerator) enumerator = NULL;
      g_autofree char *objdir_name = NULL;

      objdir_name = g_strdup_printf ("%02x", GPOINTER_TO_UINT (key));
      objdir = g_file_get_child (self->uncompressed_objects_dir, objdir_name);

      enumerator = g_file_enumerate_children (objdir, "standard::name,standard::type,unix::inode,unix::nlink", 
                                              G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                              cancellable, 
                                              error);
      if (!enumerator)
        goto out;
  
      while (TRUE)
        {
          GFileInfo *file_info;
          guint32 nlinks;

          if (!gs_file_enumerator_iterate (enumerator, &file_info, NULL,
                                           cancellable, error))
            goto out;
          if (file_info == NULL)
            break;
          
          nlinks = g_file_info_get_attribute_uint32 (file_info, "unix::nlink");
          if (nlinks == 1)
            {
              g_autoptr(GFile) objpath = NULL;
              objpath = g_file_get_child (objdir, g_file_info_get_name (file_info));
              if (!gs_file_unlink (objpath, cancellable, error))
                goto out;
            }
        }
    }

  ret = TRUE;
 out:
  return ret;
}
Example #3
0
static void
on_metadata_writed (GObject           *object,
                    GAsyncResult      *result,
                    gpointer           user_data)
{
  FetchObjectData *fetch_data = user_data;
  OtPullData *pull_data = fetch_data->pull_data;
  GError *local_error = NULL;
  GError **error = &local_error;
  const char *expected_checksum;
  OstreeObjectType objtype;
  gs_free char *checksum = NULL;
  gs_free guchar *csum = NULL;

  if (!ostree_repo_write_metadata_finish ((OstreeRepo*)object, result, 
                                          &csum, error))
    goto out;

  checksum = ostree_checksum_from_bytes (csum);

  ostree_object_name_deserialize (fetch_data->object, &expected_checksum, &objtype);
  g_assert (OSTREE_OBJECT_TYPE_IS_META (objtype));

  g_debug ("write of %s complete", ostree_object_to_string (checksum, objtype));

  if (strcmp (checksum, expected_checksum) != 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Corrupted metadata object; checksum expected='%s' actual='%s'",
                   expected_checksum, checksum);
      goto out;
    }

  pull_data->metadata_scan_idle = FALSE;
  ot_waitable_queue_push (pull_data->metadata_objects_to_scan,
                          pull_worker_message_new (PULL_MSG_SCAN,
                                                  g_variant_ref (fetch_data->object)));
 out:
  pull_data->n_outstanding_metadata_write_requests--;
  (void) gs_file_unlink (fetch_data->temp_path, NULL, NULL);
  g_object_unref (fetch_data->temp_path);
  g_variant_unref (fetch_data->object);
  g_free (fetch_data);

  check_outstanding_requests_handle_error (pull_data, local_error);
}
Example #4
0
gboolean      
_ostree_repo_write_ref (OstreeRepo    *self,
                        const char    *remote,
                        const char    *ref,
                        const char    *rev,
                        GCancellable  *cancellable,
                        GError       **error)
{
  gboolean ret = FALSE;
  gs_unref_object GFile *dir = NULL;

  if (remote == NULL)
    dir = g_object_ref (self->local_heads_dir);
  else
    {
      dir = g_file_get_child (self->remote_heads_dir, remote);
      
      if (rev != NULL)
        {
          if (!gs_file_ensure_directory (dir, FALSE, cancellable, error))
            goto out;
        }
    }

  if (rev == NULL)
    {
      gs_unref_object GFile *child = g_file_resolve_relative_path (dir, ref);

      if (g_file_query_exists (child, cancellable))
        {
          if (!gs_file_unlink (child, cancellable, error))
            goto out;
        }
    }
  else
    {
      if (!write_checksum_file (dir, ref, rev, cancellable, error))
        goto out;
    }

  ret = TRUE;
 out:
  return ret;
}
Example #5
0
static void
content_fetch_on_write_complete (GObject        *object,
                                 GAsyncResult   *result,
                                 gpointer        user_data)
{
  FetchObjectData *fetch_data = user_data;
  OtPullData *pull_data = fetch_data->pull_data;
  GError *local_error = NULL;
  GError **error = &local_error;
  OstreeObjectType objtype;
  const char *expected_checksum;
  gs_free guchar *csum = NULL;
  gs_free char *checksum = NULL;

  if (!ostree_repo_write_content_finish ((OstreeRepo*)object, result, 
                                         &csum, error))
    goto out;

  checksum = ostree_checksum_from_bytes (csum);

  ostree_object_name_deserialize (fetch_data->object, &expected_checksum, &objtype);
  g_assert (objtype == OSTREE_OBJECT_TYPE_FILE);

  g_debug ("write of %s complete", ostree_object_to_string (checksum, objtype));

  if (strcmp (checksum, expected_checksum) != 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Corrupted content object; checksum expected='%s' actual='%s'",
                   expected_checksum, checksum);
      goto out;
    }

  pull_data->n_fetched_content++;
 out:
  pull_data->n_outstanding_content_write_requests--;
  check_outstanding_requests_handle_error (pull_data, local_error);
  (void) gs_file_unlink (fetch_data->temp_path, NULL, NULL);
  g_object_unref (fetch_data->temp_path);
  g_variant_unref (fetch_data->object);
  g_free (fetch_data);
}
Example #6
0
static gboolean
migrate_rpm_and_yumdb (GFile          *targetroot,
                       GFile          *yumroot,
                       GCancellable   *cancellable,
                       GError        **error)

{
    gboolean ret = FALSE;
    gs_unref_object GFile *usrbin_rpm =
        g_file_resolve_relative_path (targetroot, "usr/bin/rpm");
    gs_unref_object GFile *legacyrpm_path =
        g_file_resolve_relative_path (yumroot, "var/lib/rpm");
    gs_unref_object GFile *newrpm_path =
        g_file_resolve_relative_path (targetroot, "usr/share/rpm");
    gs_unref_object GFile *src_yum_rpmdb_indexes =
        g_file_resolve_relative_path (yumroot, "var/lib/yum");
    gs_unref_object GFile *target_yum_rpmdb_indexes =
        g_file_resolve_relative_path (targetroot, "usr/share/yumdb");
    gs_unref_object GFile *yumroot_yumlib =
        g_file_get_child (yumroot, "var/lib/yum");
    gs_unref_object GFileEnumerator *direnum = NULL;

    direnum = g_file_enumerate_children (legacyrpm_path, "standard::name",
                                         G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                         cancellable, error);
    if (!direnum)
        goto out;

    while (TRUE)
    {
        const char *name;
        GFileInfo *file_info;
        GFile *child;

        if (!gs_file_enumerator_iterate (direnum, &file_info, &child,
                                         cancellable, error))
            goto out;
        if (!file_info)
            break;

        name = g_file_info_get_name (file_info);

        if (g_str_has_prefix (name, "__db.") ||
                strcmp (name, ".dbenv.lock") == 0 ||
                strcmp (name, ".rpm.lock") == 0)
        {
            if (!gs_file_unlink (child, cancellable, error))
                goto out;
        }
    }

    (void) g_file_enumerator_close (direnum, cancellable, error);

    g_print ("Placing RPM db in /usr/share/rpm\n");
    if (!gs_file_rename (legacyrpm_path, newrpm_path, cancellable, error))
        goto out;

    /* Remove /var/lib/yum; we don't want it here. */
    if (!gs_shutil_rm_rf (yumroot_yumlib, cancellable, error))
        goto out;

    ret = TRUE;
out:
    return ret;
}
Example #7
0
gboolean
rpmostree_treefile_postprocessing (GFile         *yumroot,
                                   GFile         *context_directory,
                                   GBytes        *serialized_treefile,
                                   JsonObject    *treefile,
                                   GCancellable  *cancellable,
                                   GError       **error)
{
    gboolean ret = FALSE;
    guint i, len;
    JsonArray *units = NULL;
    JsonArray *remove = NULL;
    const char *default_target = NULL;
    const char *postprocess_script = NULL;

    if (json_object_has_member (treefile, "units"))
        units = json_object_get_array_member (treefile, "units");

    if (units)
        len = json_array_get_length (units);
    else
        len = 0;

    {
        gs_unref_object GFile *multiuser_wants_dir =
            g_file_resolve_relative_path (yumroot, "etc/systemd/system/multi-user.target.wants");

        if (!gs_file_ensure_directory (multiuser_wants_dir, TRUE, cancellable, error))
            goto out;

        for (i = 0; i < len; i++)
        {
            const char *unitname = _rpmostree_jsonutil_array_require_string_element (units, i, error);
            gs_unref_object GFile *unit_link_target = NULL;
            gs_free char *symlink_target = NULL;

            if (!unitname)
                goto out;

            symlink_target = g_strconcat ("/usr/lib/systemd/system/", unitname, NULL);
            unit_link_target = g_file_get_child (multiuser_wants_dir, unitname);

            if (g_file_query_file_type (unit_link_target, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL) == G_FILE_TYPE_SYMBOLIC_LINK)
                continue;

            g_print ("Adding %s to multi-user.target.wants\n", unitname);

            if (!g_file_make_symbolic_link (unit_link_target, symlink_target,
                                            cancellable, error))
                goto out;
        }
    }

    {
        gs_unref_object GFile *target_treefile_dir_path =
            g_file_resolve_relative_path (yumroot, "usr/share/rpm-ostree");
        gs_unref_object GFile *target_treefile_path =
            g_file_get_child (target_treefile_dir_path, "treefile.json");
        const guint8 *buf;
        gsize len;

        if (!gs_file_ensure_directory (target_treefile_dir_path, TRUE,
                                       cancellable, error))
            goto out;

        g_print ("Writing '%s'\n", gs_file_get_path_cached (target_treefile_path));
        buf = g_bytes_get_data (serialized_treefile, &len);

        if (!g_file_replace_contents (target_treefile_path, (char*)buf, len,
                                      NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION,
                                      NULL, cancellable, error))
            goto out;
    }

    if (!_rpmostree_jsonutil_object_get_optional_string_member (treefile, "default_target",
            &default_target, error))
        goto out;

    if (default_target != NULL)
    {
        gs_unref_object GFile *default_target_path =
            g_file_resolve_relative_path (yumroot, "etc/systemd/system/default.target");
        gs_free char *dest_default_target_path =
            g_strconcat ("/usr/lib/systemd/system/", default_target, NULL);

        (void) gs_file_unlink (default_target_path, NULL, NULL);

        if (!g_file_make_symbolic_link (default_target_path, dest_default_target_path,
                                        cancellable, error))
            goto out;
    }

    if (json_object_has_member (treefile, "remove-files"))
    {
        remove = json_object_get_array_member (treefile, "remove-files");
        len = json_array_get_length (remove);
    }
    else
        len = 0;

    for (i = 0; i < len; i++)
    {
        const char *val = _rpmostree_jsonutil_array_require_string_element (remove, i, error);
        gs_unref_object GFile *child = NULL;

        if (!val)
            return FALSE;
        if (g_path_is_absolute (val))
        {
            g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                         "'remove' elements must be relative");
            goto out;
        }

        child = g_file_resolve_relative_path (yumroot, val);

        if (g_file_query_exists (child, NULL))
        {
            g_print ("Removing '%s'\n", val);
            if (!gs_shutil_rm_rf (child, cancellable, error))
                goto out;
        }
        else
        {
            g_printerr ("warning: Targeted path for remove-files does not exist: %s\n",
                        gs_file_get_path_cached (child));
        }
    }

    if (json_object_has_member (treefile, "remove-from-packages"))
    {
        g_autoptr(RpmOstreeRefSack) refsack = NULL;
        _cleanup_hypackagelist_ HyPackageList pkglist = NULL;
        guint i;

        remove = json_object_get_array_member (treefile, "remove-from-packages");
        len = json_array_get_length (remove);

        if (!rpmostree_get_pkglist_for_root (AT_FDCWD, gs_file_get_path_cached (yumroot),
                                             &refsack, &pkglist,
                                             cancellable, error))
        {
            g_prefix_error (error, "Reading package set: ");
            goto out;
        }

        for (i = 0; i < len; i++)
        {
            JsonArray *elt = json_array_get_array_element (remove, i);
            if (!handle_remove_files_from_package (yumroot, refsack, elt, cancellable, error))
                goto out;
        }
    }

    if (!_rpmostree_jsonutil_object_get_optional_string_member (treefile, "postprocess-script",
            &postprocess_script, error))
        goto out;

    if (postprocess_script)
    {
        const char *yumroot_path = gs_file_get_path_cached (yumroot);
        gs_unref_object GFile *src = g_file_resolve_relative_path (context_directory, postprocess_script);
        const char *bn = gs_file_get_basename_cached (src);
        gs_free char *binpath = g_strconcat ("/usr/bin/rpmostree-postprocess-", bn, NULL);
        gs_free char *destpath = g_strconcat (yumroot_path, binpath, NULL);
        gs_unref_object GFile *dest = g_file_new_for_path (destpath);
        /* Clone all the things */

        if (!g_file_copy (src, dest, 0, cancellable, NULL, NULL, error))
        {
            g_prefix_error (error, "Copying postprocess-script '%s' into target: ", bn);
            goto out;
        }

        g_print ("Executing postprocessing script '%s'\n", bn);

        {
            char *child_argv[] = { binpath, NULL };
            if (!run_sync_in_root (yumroot, binpath, child_argv, error))
            {
                g_prefix_error (error, "While executing postprocessing script '%s': ", bn);
                goto out;
            }
        }

        g_print ("Finished postprocessing script '%s'\n", bn);
    }

    ret = TRUE;
out:
    return ret;
}
gboolean
rpmostree_compose_builtin_sign (int            argc,
                                char         **argv,
                                GCancellable  *cancellable,
                                GError       **error)
{
  gboolean ret = FALSE;
  GOptionContext *context = g_option_context_new ("- Use rpm-sign to sign an OSTree commit");
  gs_unref_object GFile *repopath = NULL;
  gs_unref_object OstreeRepo *repo = NULL;
  gs_unref_object GFile *tmp_commitdata_file = NULL;
  gs_unref_object GFileIOStream *tmp_sig_stream = NULL;
  gs_unref_object GFile *tmp_sig_file = NULL;
  gs_unref_object GFileIOStream *tmp_commitdata_stream = NULL;
  GOutputStream *tmp_commitdata_output = NULL;
  gs_unref_object GInputStream *commit_data = NULL;
  gs_free char *checksum = NULL;
  gs_unref_variant GVariant *commit_variant = NULL;
  gs_unref_bytes GBytes *commit_bytes = NULL;
  
  if (!rpmostree_option_context_parse (context, option_entries, &argc, &argv, error))
    goto out;

  if (!(opt_repo_path && opt_key_id && opt_rev))
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Missing required argument");
      goto out;
    }

  repopath = g_file_new_for_path (opt_repo_path);
  repo = ostree_repo_new (repopath);
  if (!ostree_repo_open (repo, cancellable, error))
    goto out;

  if (!ostree_repo_resolve_rev (repo, opt_rev, FALSE, &checksum, error))
    goto out;

  if (!ostree_repo_load_variant (repo, OSTREE_OBJECT_TYPE_COMMIT,
                                 checksum, &commit_variant, error))
    goto out;

  commit_bytes = g_variant_get_data_as_bytes (commit_variant);
  commit_data = (GInputStream*)g_memory_input_stream_new_from_bytes (commit_bytes);
  
  tmp_commitdata_file = g_file_new_tmp ("tmpsigXXXXXX", &tmp_commitdata_stream,
                                       error);
  if (!tmp_commitdata_file)
    goto out;

  tmp_commitdata_output = (GOutputStream*)g_io_stream_get_output_stream ((GIOStream*)tmp_commitdata_stream);
  if (g_output_stream_splice ((GOutputStream*)tmp_commitdata_output,
                              commit_data,
                              G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE |
                              G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET,
                              cancellable, error) < 0)
    goto out;

  tmp_sig_file = g_file_new_tmp ("tmpsigoutXXXXXX", &tmp_sig_stream, error);
  if (!tmp_sig_file)
    goto out;

  (void) g_io_stream_close ((GIOStream*)tmp_sig_stream, NULL, NULL);
                                  
  if (!gs_subprocess_simple_run_sync (NULL, GS_SUBPROCESS_STREAM_DISPOSITION_NULL,
                                      cancellable, error,
                                      "rpm-sign",
                                      "--key", opt_key_id,
                                      "--detachsign", gs_file_get_path_cached (tmp_commitdata_file),
                                      "--output", gs_file_get_path_cached (tmp_sig_file),
                                      NULL))
    goto out;

  {
    char *sigcontent = NULL;
    gsize len;
    gs_unref_bytes GBytes *sigbytes = NULL;

    if (!g_file_load_contents (tmp_sig_file, cancellable, &sigcontent, &len, NULL,
                               error))
      goto out;

    sigbytes = g_bytes_new_take (sigcontent, len);

    if (!ostree_repo_append_gpg_signature (repo, checksum, sigbytes,
                                           cancellable, error))
      goto out;
  }

  g_print ("Successfully signed OSTree commit=%s with key=%s\n",
           checksum, opt_key_id);
  
  ret = TRUE;
 out:
  if (tmp_commitdata_file)
    (void) gs_file_unlink (tmp_commitdata_file, NULL, NULL);
  if (tmp_sig_file)
    (void) gs_file_unlink (tmp_sig_file, NULL, NULL);
  return ret;
}
static gboolean
migrate_rpm_and_yumdb (GFile          *targetroot,
                       GFile          *yumroot,
                       GCancellable   *cancellable,
                       GError        **error)

{
  gboolean ret = FALSE;
  gs_unref_object GFile *usrbin_rpm =
    g_file_resolve_relative_path (targetroot, "usr/bin/rpm");
  gs_unref_object GFile *legacyrpm_path =
    g_file_resolve_relative_path (yumroot, "var/lib/rpm");
  gs_unref_object GFile *newrpm_path =
    g_file_resolve_relative_path (targetroot, "usr/share/rpm");
  gs_unref_object GFile *src_yum_rpmdb_indexes =
    g_file_resolve_relative_path (yumroot, "var/lib/yum");
  gs_unref_object GFile *target_yum_rpmdb_indexes =
    g_file_resolve_relative_path (targetroot, "usr/share/yumdb");
  gs_unref_object GFile *yumroot_yumlib =
    g_file_get_child (yumroot, "var/lib/yum");
  gs_unref_object GFileEnumerator *direnum = NULL;

  direnum = g_file_enumerate_children (legacyrpm_path, "standard::name",
                                       G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                       cancellable, error);
  if (!direnum)
    goto out;

  while (TRUE)
    {
      const char *name;
      GFileInfo *file_info;
      GFile *child;

      if (!gs_file_enumerator_iterate (direnum, &file_info, &child,
                                       cancellable, error))
        goto out;
      if (!file_info)
        break;

      name = g_file_info_get_name (file_info);

      if (g_str_has_prefix (name, "__db.") ||
          strcmp (name, ".dbenv.lock") == 0 ||
          strcmp (name, ".rpm.lock") == 0)
        {
          if (!gs_file_unlink (child, cancellable, error))
            goto out;
        }
    }

  (void) g_file_enumerator_close (direnum, cancellable, error);
    
  g_print ("Placing RPM db in /usr/share/rpm\n");
  if (!gs_file_rename (legacyrpm_path, newrpm_path, cancellable, error))
    goto out;
    
  /* Move the yum database to usr/share/yumdb; disabled for now due
   * to bad conflict with OSTree's current
   * one-http-request-per-file.
   */
#if 0
  if (g_file_query_exists (src_yum_rpmdb_indexes, NULL))
    {
      g_print ("Moving %s to %s\n", gs_file_get_path_cached (src_yum_rpmdb_indexes),
               gs_file_get_path_cached (target_yum_rpmdb_indexes));
      if (!gs_file_rename (src_yum_rpmdb_indexes, target_yum_rpmdb_indexes,
                           cancellable, error))
        goto out;
        
      if (!clean_yumdb_extraneous_files (target_yum_rpmdb_indexes, cancellable, error))
        goto out;
    }
#endif

  /* Remove /var/lib/yum; we don't want it here. */
  if (!gs_shutil_rm_rf (yumroot_yumlib, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  return ret;
}