예제 #1
0
static void
meta_fetch_on_complete (GObject           *object,
                        GAsyncResult      *result,
                        gpointer           user_data)
{
  FetchObjectData *fetch_data = user_data;
  OtPullData *pull_data = fetch_data->pull_data;
  gs_unref_variant GVariant *metadata = NULL;
  const char *checksum;
  OstreeObjectType objtype;
  GError *local_error = NULL;
  GError **error = &local_error;

  ostree_object_name_deserialize (fetch_data->object, &checksum, &objtype);
  g_debug ("fetch of %s complete", ostree_object_to_string (checksum, objtype));

  fetch_data->temp_path = ostree_fetcher_request_uri_with_partial_finish ((OstreeFetcher*)object, result, error);
  if (!fetch_data->temp_path)
    {
      if (!g_error_matches (local_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND))
        goto out;
      else if (fetch_data->is_detached_meta)
        {
          /* There isn't any detached metadata, just fetch the commit */
          g_clear_error (&local_error);
          enqueue_one_object_request (pull_data, fetch_data->object, FALSE);
        }

      goto out;
    }

  if (fetch_data->is_detached_meta)
    {
      if (!ot_util_variant_map (fetch_data->temp_path, G_VARIANT_TYPE ("a{sv}"),
                                FALSE, &metadata, error))
        goto out;
      if (!ostree_repo_write_commit_detached_metadata (pull_data->repo, checksum, metadata,
                                                       pull_data->cancellable, error))
        goto out;

      enqueue_one_object_request (pull_data, fetch_data->object, FALSE);
    }
  else
    {
      if (!ot_util_variant_map (fetch_data->temp_path, ostree_metadata_variant_type (objtype),
                                FALSE, &metadata, error))
        goto out;
      
      ostree_repo_write_metadata_async (pull_data->repo, objtype, checksum, metadata,
                                        pull_data->cancellable,
                                        on_metadata_writed, fetch_data);
      pull_data->n_outstanding_metadata_write_requests++;
    }

 out:
  pull_data->n_outstanding_metadata_fetches--;
  pull_data->n_fetched_metadata++;
  throw_async_error (pull_data, local_error);
  if (local_error)
    {
      g_variant_unref (fetch_data->object);
      g_free (fetch_data);
    }
}
static gboolean
dispatch_open_splice_and_close (OstreeRepo                 *repo,
                                StaticDeltaExecutionState  *state,
                                GCancellable               *cancellable,  
                                GError                    **error)
{
  gboolean ret = FALSE;

  if (!open_output_target (state, cancellable, error))
    goto out;

  if (OSTREE_OBJECT_TYPE_IS_META (state->output_objtype))
    {
      g_autoptr(GVariant) metadata = NULL;
      guint64 offset;
      guint64 length;

      if (!read_varuint64 (state, &length, error))
        goto out;
      if (!read_varuint64 (state, &offset, error))
        goto out;
      if (!validate_ofs (state, offset, length, error))
        goto out;

      if (state->stats_only)
        {
          ret = TRUE;
          goto out;
        }
      
      metadata = g_variant_new_from_data (ostree_metadata_variant_type (state->output_objtype),
                                          state->payload_data + offset, length, TRUE, NULL, NULL);

      {
        g_autofree guchar *actual_csum = NULL;

        if (!ostree_repo_write_metadata (state->repo, state->output_objtype,
                                         state->checksum,
                                         metadata, &actual_csum,
                                         cancellable,
                                         error))
          goto out;
      }
    }
  else
    {
      guint64 content_offset;
      guint64 objlen;
      g_autoptr(GInputStream) object_input = NULL;
      g_autoptr(GInputStream) memin = NULL;
      
      if (!do_content_open_generic (repo, state, cancellable, error))
        goto out;

      if (!read_varuint64 (state, &state->content_size, error))
        goto out;
      if (!read_varuint64 (state, &content_offset, error))
        goto out;
      if (!validate_ofs (state, content_offset, state->content_size, error))
        goto out;
      
      if (state->stats_only)
        {
          ret = TRUE;
          goto out;
        }

      /* Fast path for regular files to bare repositories */
      if (S_ISREG (state->mode) && 
          (repo->mode == OSTREE_REPO_MODE_BARE ||
           repo->mode == OSTREE_REPO_MODE_BARE_USER))
        {
          if (!_ostree_repo_open_content_bare (repo, state->checksum,
                                               state->content_size,
                                               &state->barecommitstate,
                                               &state->content_out,
                                               &state->have_obj,
                                               cancellable, error))
            goto out;

          if (!state->have_obj)
            {
              if (!handle_untrusted_content_checksum (repo, state, cancellable, error))
                goto out;

              if (!content_out_write (repo, state,
                                      state->payload_data + content_offset,
                                      state->content_size,
                                      cancellable, error))
                goto out;
            }
        }
      else
        {
          /* Slower path, for symlinks and unpacking deltas into archive-z2 */
          g_autoptr(GFileInfo) finfo = NULL;
      
          finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid);

          if (S_ISLNK (state->mode))
            {
              g_autofree char *nulterminated_target =
                g_strndup ((char*)state->payload_data + content_offset, state->content_size);
              g_file_info_set_symlink_target (finfo, nulterminated_target);
            }
          else
            {
              g_assert (S_ISREG (state->mode));
              g_file_info_set_size (finfo, state->content_size);
              memin = g_memory_input_stream_new_from_data (state->payload_data + content_offset, state->content_size, NULL);
            }

          if (!ostree_raw_file_to_content_stream (memin, finfo, state->xattrs,
                                                  &object_input, &objlen,
                                                  cancellable, error))
            goto out;

          {
            g_autofree guchar *actual_csum = NULL;
            if (!ostree_repo_write_content (state->repo,
                                            state->checksum,
                                            object_input,
                                            objlen,
                                            &actual_csum,
                                            cancellable,
                                            error))
              goto out;
          }
        }
    }

  if (!dispatch_close (repo, state, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (state->stats_only)
    (void) dispatch_close (repo, state, cancellable, NULL);
  if (!ret)
    g_prefix_error (error, "opcode open-splice-and-close: ");
  return ret;
}