static gboolean
open_output_target (StaticDeltaExecutionState   *state,
                    GCancellable                *cancellable,
                    GError                     **error)
{
  gboolean ret = FALSE;
  guint8 *objcsum;

  g_assert (state->checksums != NULL);
  g_assert (state->output_target == NULL);
  g_assert (state->checksum_index < state->n_checksums);

  objcsum = (guint8*)state->checksums + (state->checksum_index * OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN);

  if (G_UNLIKELY(!ostree_validate_structureof_objtype (*objcsum, error)))
    goto out;

  state->output_objtype = (OstreeObjectType) *objcsum;
  state->output_target = objcsum + 1;

  ostree_checksum_inplace_from_bytes (state->output_target, state->checksum);

  ret = TRUE;
 out:
  return ret;
}
Ejemplo n.º 2
0
static void
dump_summary_ref (const char   *ref_name,
                  guint64       commit_size,
                  GVariant     *csum_v,
                  GVariantIter *metadata)
{
  const guchar *csum_bytes;
  GError *csum_error = NULL;
  g_autofree char *size = NULL;
  GVariant *value;
  char *key;

  g_print ("* %s\n", ref_name);

  size = g_format_size (commit_size);
  g_print ("    Latest Commit (%s):\n", size);

  csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, &csum_error);
  if (csum_error == NULL)
    {
      char csum[OSTREE_SHA256_STRING_LEN+1];

      ostree_checksum_inplace_from_bytes (csum_bytes, csum);
      g_print ("      %s\n", csum);
    }
  else
    {
      g_print ("      %s\n", csum_error->message);
      g_clear_error (&csum_error);
    }

  while (g_variant_iter_loop (metadata, "{sv}", &key, &value))
    {
      g_autofree gchar *value_str = NULL;
      const gchar *pretty_key = NULL;

      if (g_strcmp0 (key, OSTREE_COMMIT_TIMESTAMP) == 0)
        {
          pretty_key = "Timestamp";
          value_str = uint64_secs_to_iso8601 (GUINT64_FROM_BE (g_variant_get_uint64 (value)));
        }
      else
        {
          value_str = g_variant_print (value, FALSE);
        }

      /* Print out. */
      if (pretty_key != NULL)
        g_print ("    %s (%s): %s\n", pretty_key, key, value_str);
      else
        g_print ("    %s: %s\n", key, value_str);
    }
}
Ejemplo n.º 3
0
/**
 * ostree_repo_commit_traverse_iter_init_commit:
 * @iter: An iter
 * @repo: A repo
 * @commit: Variant of type %OSTREE_OBJECT_TYPE_COMMIT
 * @flags: Flags
 * @error: Error
 *
 * Initialize (in place) an iterator over the root of a commit object.
 */
gboolean
ostree_repo_commit_traverse_iter_init_commit (OstreeRepoCommitTraverseIter   *iter,
                                              OstreeRepo                     *repo,
                                              GVariant                       *commit,
                                              OstreeRepoCommitTraverseFlags   flags,
                                              GError                        **error)
{
  struct _OstreeRepoRealCommitTraverseIter *real =
    (struct _OstreeRepoRealCommitTraverseIter*)iter;
  gboolean ret = FALSE;
  const guchar *csum;
  g_autoptr(GVariant) meta_csum_bytes = NULL;
  g_autoptr(GVariant) content_csum_bytes = NULL;

  memset (real, 0, sizeof (*real));
  real->initialized = TRUE;
  real->repo = g_object_ref (repo);
  real->commit = g_variant_ref (commit);
  real->current_dir = NULL;
  real->idx = 0;

  g_variant_get_child (commit, 6, "@ay", &content_csum_bytes);
  csum = ostree_checksum_bytes_peek_validate (content_csum_bytes, error);
  if (!csum)
    goto out;
  ostree_checksum_inplace_from_bytes (csum, real->checksum_content);

  g_variant_get_child (commit, 7, "@ay", &meta_csum_bytes);
  csum = ostree_checksum_bytes_peek_validate (meta_csum_bytes, error);
  if (!csum)
    goto out;
  ostree_checksum_inplace_from_bytes (csum, real->checksum_meta);

  ret = TRUE;
 out:
  return ret;
}
gboolean
_ostree_repo_static_delta_part_have_all_objects (OstreeRepo             *repo,
                                                 GVariant               *checksum_array,
                                                 gboolean               *out_have_all,
                                                 GCancellable           *cancellable,
                                                 GError                **error)
{
  gboolean ret = FALSE;
  guint8 *checksums_data;
  guint i,n_checksums;
  gboolean have_object = TRUE;

  if (!_ostree_static_delta_parse_checksum_array (checksum_array,
                                                  &checksums_data,
                                                  &n_checksums,
                                                  error))
    goto out;

  for (i = 0; i < n_checksums; i++)
    {
      guint8 objtype = *checksums_data;
      const guint8 *csum = checksums_data + 1;
      char tmp_checksum[OSTREE_SHA256_STRING_LEN+1];

      if (G_UNLIKELY(!ostree_validate_structureof_objtype (objtype, error)))
        goto out;

      ostree_checksum_inplace_from_bytes (csum, tmp_checksum);

      if (!ostree_repo_has_object (repo, (OstreeObjectType) objtype, tmp_checksum,
                                   &have_object, cancellable, error))
        goto out;

      if (!have_object)
        break;

      checksums_data += OSTREE_STATIC_DELTA_OBJTYPE_CSUM_LEN;
    }

  ret = TRUE;
  *out_have_all = have_object;
 out:
  return ret;
}
gboolean
_ostree_repo_static_delta_dump (OstreeRepo                    *self,
                                const char                    *delta_id,
                                GCancellable                  *cancellable,
                                GError                       **error)
{
  gboolean ret = FALSE;
  g_autofree char *from = NULL; 
  g_autofree char *to = NULL;
  g_autofree char *superblock_path = NULL;
  g_autoptr(GVariant) delta_superblock = NULL;
  guint64 total_size = 0, total_usize = 0;
  guint64 total_fallback_size = 0, total_fallback_usize = 0;
  guint i;
  OstreeDeltaEndianness endianness;
  gboolean swap_endian = FALSE;

  if (!_ostree_parse_delta_name (delta_id, &from, &to, error))
    goto out;

  superblock_path = _ostree_get_relative_static_delta_superblock_path (from, to);

  if (!ot_util_variant_map_at (self->repo_dir_fd, superblock_path,
                               (GVariantType*)OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT,
                               OT_VARIANT_MAP_TRUSTED, &delta_superblock, error))
    goto out;

  g_print ("Delta: %s\n", delta_id);
  { const char *endianness_description;
    gboolean was_heuristic;

    endianness = _ostree_delta_get_endianness (delta_superblock, &was_heuristic);

    switch (endianness)
      {
      case OSTREE_DELTA_ENDIAN_BIG:
        if (was_heuristic)
          endianness_description = "big (heuristic)";
        else
          endianness_description = "big";
        if (G_BYTE_ORDER == G_LITTLE_ENDIAN)
          swap_endian = TRUE;
        break;
      case OSTREE_DELTA_ENDIAN_LITTLE:
        if (was_heuristic)
          endianness_description = "little (heuristic)";
        else
          endianness_description = "little";
        if (G_BYTE_ORDER == G_BIG_ENDIAN)
          swap_endian = TRUE;
        break;
      case OSTREE_DELTA_ENDIAN_INVALID:
        endianness_description = "invalid";
        break;
      default:
        g_assert_not_reached ();
      }
    
    g_print ("Endianness: %s\n", endianness_description);
  }
  { guint64 ts;
    g_variant_get_child (delta_superblock, 1, "t", &ts);
    g_print ("Timestamp: %" G_GUINT64_FORMAT "\n", GUINT64_FROM_BE (ts));
  }
  { g_autoptr(GVariant) recurse = NULL;
    g_variant_get_child (delta_superblock, 5, "@ay", &recurse);
    g_print ("Number of parents: %u\n", (guint)(g_variant_get_size (recurse) / (OSTREE_SHA256_DIGEST_LEN * 2)));
  }
  { g_autoptr(GVariant) fallback = NULL;
    guint n_fallback;

    g_variant_get_child (delta_superblock, 7, "@a" OSTREE_STATIC_DELTA_FALLBACK_FORMAT, &fallback);
    n_fallback = g_variant_n_children (fallback);

    g_print ("Number of fallback entries: %u\n", n_fallback);

    for (i = 0; i < n_fallback; i++)
      {
        guint64 size, usize;
        g_autoptr(GVariant) checksum_v = NULL;
        char checksum[OSTREE_SHA256_STRING_LEN+1];
        g_variant_get_child (fallback, i, "(y@aytt)", NULL, &checksum_v, &size, &usize);
        ostree_checksum_inplace_from_bytes (ostree_checksum_bytes_peek (checksum_v), checksum);
        size = maybe_swap_endian_u64 (swap_endian, size);
        usize = maybe_swap_endian_u64 (swap_endian, usize);
        g_print ("  %s\n", checksum);
        total_fallback_size += size;
        total_fallback_usize += usize;
      }
    { g_autofree char *sizestr = g_format_size (total_fallback_size);
      g_autofree char *usizestr = g_format_size (total_fallback_usize);
      g_print ("Total Fallback Size: %" G_GUINT64_FORMAT " (%s)\n", total_fallback_size, sizestr);
      g_print ("Total Fallback Uncompressed Size: %" G_GUINT64_FORMAT " (%s)\n", total_fallback_usize, usizestr);
    }
  }
  { g_autoptr(GVariant) meta_entries = NULL;
    guint n_parts;

    g_variant_get_child (delta_superblock, 6, "@a" OSTREE_STATIC_DELTA_META_ENTRY_FORMAT, &meta_entries);
    n_parts = g_variant_n_children (meta_entries);
    g_print ("Number of parts: %u\n", n_parts);

    for (i = 0; i < n_parts; i++)
      {
        if (!show_one_part (self, swap_endian, from, to, meta_entries, i,
                            &total_size, &total_usize,
                            cancellable, error))
          goto out;
      }
  }

  { g_autofree char *sizestr = g_format_size (total_size);
    g_autofree char *usizestr = g_format_size (total_usize);
    g_print ("Total Part Size: %" G_GUINT64_FORMAT " (%s)\n", total_size, sizestr);
    g_print ("Total Part Uncompressed Size: %" G_GUINT64_FORMAT " (%s)\n", total_usize, usizestr);
  }
  { guint64 overall_size = total_size + total_fallback_size;
    guint64 overall_usize = total_usize + total_fallback_usize;
    g_autofree char *sizestr = g_format_size (overall_size);
    g_autofree char *usizestr = g_format_size (overall_usize);
    g_print ("Total Size: %" G_GUINT64_FORMAT " (%s)\n", overall_size, sizestr);
    g_print ("Total Uncompressed Size: %" G_GUINT64_FORMAT " (%s)\n", overall_usize, usizestr);
  }

  ret = TRUE;
 out:
  return ret;
}
/**
 * ostree_repo_list_static_delta_names:
 * @self: Repo
 * @out_deltas: (out) (element-type utf8) (transfer container): String name of deltas (checksum-checksum.delta)
 * @cancellable: Cancellable
 * @error: Error
 *
 * This function synchronously enumerates all static deltas in the
 * repository, returning its result in @out_deltas.
 */ 
gboolean
ostree_repo_list_static_delta_names (OstreeRepo                  *self,
                                     GPtrArray                  **out_deltas,
                                     GCancellable                *cancellable,
                                     GError                     **error)
{
  g_autoptr(GPtrArray) ret_deltas = g_ptr_array_new_with_free_func (g_free);

  g_auto(GLnxDirFdIterator) dfd_iter = { 0, };
  gboolean exists;
  if (!ot_dfd_iter_init_allow_noent (self->repo_dir_fd, "deltas", &dfd_iter,
                                     &exists, error))
    return FALSE;
  if (!exists)
    {
      /* Note early return */
      ot_transfer_out_value (out_deltas, &ret_deltas);
      return TRUE;
    }

  while (TRUE)
    {
      g_auto(GLnxDirFdIterator) sub_dfd_iter = { 0, };
      struct dirent *dent;

      if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&dfd_iter, &dent, cancellable, error))
        return FALSE;
      if (dent == NULL)
        break;
      if (dent->d_type != DT_DIR)
        continue;

      if (!glnx_dirfd_iterator_init_at (dfd_iter.fd, dent->d_name, FALSE,
                                        &sub_dfd_iter, error))
        return FALSE;

      while (TRUE)
        {
          struct dirent *sub_dent;
          const char *name1;
          const char *name2;
          g_autofree char *superblock_subpath = NULL;
          struct stat stbuf;

          if (!glnx_dirfd_iterator_next_dent_ensure_dtype (&sub_dfd_iter, &sub_dent,
                                                           cancellable, error))
            return FALSE;
          if (sub_dent == NULL)
            break;
          if (dent->d_type != DT_DIR)
            continue;

          name1 = dent->d_name;
          name2 = sub_dent->d_name;

          superblock_subpath = g_strconcat (name2, "/superblock", NULL);
          if (fstatat (sub_dfd_iter.fd, superblock_subpath, &stbuf, 0) < 0)
            {
              if (errno != ENOENT)
                {
                  glnx_set_error_from_errno (error);
                  return FALSE;
                }
            }
          else
            {
              g_autofree char *buf = g_strconcat (name1, name2, NULL);
              GString *out = g_string_new ("");
              char checksum[OSTREE_SHA256_STRING_LEN+1];
              guchar csum[OSTREE_SHA256_DIGEST_LEN];
              const char *dash = strchr (buf, '-');

              ostree_checksum_b64_inplace_to_bytes (buf, csum);
              ostree_checksum_inplace_from_bytes (csum, checksum);
              g_string_append (out, checksum);
              if (dash)
                {
                  g_string_append_c (out, '-');
                  ostree_checksum_b64_inplace_to_bytes (dash+1, csum);
                  ostree_checksum_inplace_from_bytes (csum, checksum);
                  g_string_append (out, checksum);
                }

              g_ptr_array_add (ret_deltas, g_string_free (out, FALSE));
            }
        }
    }

  ot_transfer_out_value (out_deltas, &ret_deltas);
  return TRUE;
}
/**
 * ostree_repo_static_delta_execute_offline:
 * @self: Repo
 * @dir_or_file: Path to a directory containing static delta data, or directly to the superblock
 * @skip_validation: If %TRUE, assume data integrity
 * @cancellable: Cancellable
 * @error: Error
 *
 * Given a directory representing an already-downloaded static delta
 * on disk, apply it, generating a new commit.  The directory must be
 * named with the form "FROM-TO", where both are checksums, and it
 * must contain a file named "superblock", along with at least one part.
 */
gboolean
ostree_repo_static_delta_execute_offline (OstreeRepo                    *self,
                                          GFile                         *dir_or_file,
                                          gboolean                       skip_validation,
                                          GCancellable                  *cancellable,
                                          GError                      **error)
{
  gboolean ret = FALSE;
  guint i, n;
  const char *dir_or_file_path = NULL;
  glnx_fd_close int meta_fd = -1;
  glnx_fd_close int dfd = -1;
  g_autoptr(GVariant) meta = NULL;
  g_autoptr(GVariant) headers = NULL;
  g_autoptr(GVariant) metadata = NULL;
  g_autoptr(GVariant) fallback = NULL;
  g_autofree char *to_checksum = NULL;
  g_autofree char *from_checksum = NULL;
  g_autofree char *basename = NULL;

  dir_or_file_path = gs_file_get_path_cached (dir_or_file);

  /* First, try opening it as a directory */
  dfd = glnx_opendirat_with_errno (AT_FDCWD, dir_or_file_path, TRUE);
  if (dfd < 0)
    {
      if (errno != ENOTDIR)
        {
          glnx_set_error_from_errno (error);
          goto out;
        }
      else
        {
          g_autofree char *dir = dirname (g_strdup (dir_or_file_path));
          basename = g_path_get_basename (dir_or_file_path);

          if (!glnx_opendirat (AT_FDCWD, dir, TRUE, &dfd, error))
            goto out;
        }
    }
  else
    basename = g_strdup ("superblock");

  meta_fd = openat (dfd, basename, O_RDONLY | O_CLOEXEC);
  if (meta_fd < 0)
    {
      glnx_set_error_from_errno (error);
      goto out;
    }
  
  if (!ot_util_variant_map_fd (meta_fd, 0, G_VARIANT_TYPE (OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT),
                               FALSE, &meta, error))
    goto out;

  /* Parsing OSTREE_STATIC_DELTA_SUPERBLOCK_FORMAT */

  metadata = g_variant_get_child_value (meta, 0);

  /* Write the to-commit object */
  {
    g_autoptr(GVariant) to_csum_v = NULL;
    g_autoptr(GVariant) from_csum_v = NULL;
    g_autoptr(GVariant) to_commit = NULL;
    gboolean have_to_commit;
    gboolean have_from_commit;

    to_csum_v = g_variant_get_child_value (meta, 3);
    if (!ostree_validate_structureof_csum_v (to_csum_v, error))
      goto out;
    to_checksum = ostree_checksum_from_bytes_v (to_csum_v);

    from_csum_v = g_variant_get_child_value (meta, 2);
    if (g_variant_n_children (from_csum_v) > 0)
      {
        if (!ostree_validate_structureof_csum_v (from_csum_v, error))
          goto out;
        from_checksum = ostree_checksum_from_bytes_v (from_csum_v);

        if (!ostree_repo_has_object (self, OSTREE_OBJECT_TYPE_COMMIT, from_checksum,
                                     &have_from_commit, cancellable, error))
          goto out;

        if (!have_from_commit)
          {
            g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                         "Commit %s, which is the delta source, is not in repository", from_checksum);
            goto out;
          }
      }

    if (!ostree_repo_has_object (self, OSTREE_OBJECT_TYPE_COMMIT, to_checksum,
                                 &have_to_commit, cancellable, error))
      goto out;
    
    if (!have_to_commit)
      {
        g_autofree char *detached_path = _ostree_get_relative_static_delta_path (from_checksum, to_checksum, "commitmeta");
        g_autoptr(GVariant) detached_data = NULL;

        detached_data = g_variant_lookup_value (metadata, detached_path, G_VARIANT_TYPE("a{sv}"));
        if (detached_data && !ostree_repo_write_commit_detached_metadata (self,
                                                                          to_checksum,
                                                                          detached_data,
                                                                          cancellable,
                                                                          error))
          goto out;

        to_commit = g_variant_get_child_value (meta, 4);
        if (!ostree_repo_write_metadata (self, OSTREE_OBJECT_TYPE_COMMIT,
                                         to_checksum, to_commit, NULL,
                                         cancellable, error))
          goto out;
      }
  }

  fallback = g_variant_get_child_value (meta, 7);
  if (g_variant_n_children (fallback) > 0)
    {
      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                   "Cannot execute delta offline: contains nonempty http fallback entries");
      goto out;
    }

  headers = g_variant_get_child_value (meta, 6);
  n = g_variant_n_children (headers);
  for (i = 0; i < n; i++)
    {
      guint32 version;
      guint64 size;
      guint64 usize;
      const guchar *csum;
      char checksum[OSTREE_SHA256_STRING_LEN+1];
      gboolean have_all;
      g_autoptr(GInputStream) part_in = NULL;
      g_autoptr(GVariant) inline_part_data = NULL;
      g_autoptr(GVariant) header = NULL;
      g_autoptr(GVariant) csum_v = NULL;
      g_autoptr(GVariant) objects = NULL;
      g_autoptr(GVariant) part = NULL;
      g_autofree char *deltapart_path = NULL;
      OstreeStaticDeltaOpenFlags delta_open_flags = 
        skip_validation ? OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM : 0;

      header = g_variant_get_child_value (headers, i);
      g_variant_get (header, "(u@aytt@ay)", &version, &csum_v, &size, &usize, &objects);

      if (version > OSTREE_DELTAPART_VERSION)
        {
          g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                       "Delta part has too new version %u", version);
          goto out;
        }

      if (!_ostree_repo_static_delta_part_have_all_objects (self, objects, &have_all,
                                                            cancellable, error))
        goto out;

      /* If we already have these objects, don't bother executing the
       * static delta.
       */
      if (have_all)
        continue;

      csum = ostree_checksum_bytes_peek_validate (csum_v, error);
      if (!csum)
        goto out;
      ostree_checksum_inplace_from_bytes (csum, checksum);

      deltapart_path =
        _ostree_get_relative_static_delta_part_path (from_checksum, to_checksum, i);

      inline_part_data = g_variant_lookup_value (metadata, deltapart_path, G_VARIANT_TYPE("(yay)"));
      if (inline_part_data)
        {
          g_autoptr(GBytes) inline_part_bytes = g_variant_get_data_as_bytes (inline_part_data);
          part_in = g_memory_input_stream_new_from_bytes (inline_part_bytes);

          /* For inline parts, we don't checksum, because it's
           * included with the metadata, so we're not trying to
           * protect against MITM or such.  Non-security related
           * checksums should be done at the underlying storage layer.
           */
          delta_open_flags |= OSTREE_STATIC_DELTA_OPEN_FLAGS_SKIP_CHECKSUM;

          if (!_ostree_static_delta_part_open (part_in, inline_part_bytes, 
                                               delta_open_flags,
                                               NULL,
                                               &part,
                                               cancellable, error))
            goto out;
        }
      else
        {
          g_autofree char *relpath = g_strdup_printf ("%u", i); /* TODO avoid malloc here */
          glnx_fd_close int part_fd = openat (dfd, relpath, O_RDONLY | O_CLOEXEC);
          if (part_fd < 0)
            {
              glnx_set_error_from_errno (error);
              g_prefix_error (error, "Opening deltapart '%s': ", deltapart_path);
              goto out;
            }

          part_in = g_unix_input_stream_new (part_fd, FALSE);

          if (!_ostree_static_delta_part_open (part_in, NULL, 
                                               delta_open_flags,
                                               checksum,
                                               &part,
                                               cancellable, error))
            goto out;
        }

      if (!_ostree_static_delta_part_execute (self, objects, part, skip_validation,
                                              NULL, cancellable, error))
        {
          g_prefix_error (error, "Executing delta part %i: ", i);
          goto out;
        }
    }

  ret = TRUE;
 out:
  return ret;
}
Ejemplo n.º 8
0
/**
 * ostree_repo_commit_traverse_iter_next:
 * @iter: An iter
 * @cancellable: Cancellable
 * @error: Error
 *
 * Step the interator to the next item.  Files will be returned first,
 * then subdirectories.  Call this in a loop; upon encountering
 * %OSTREE_REPO_COMMIT_ITER_RESULT_END, there will be no more files or
 * directories.  If %OSTREE_REPO_COMMIT_ITER_RESULT_DIR is returned,
 * then call ostree_repo_commit_traverse_iter_get_dir() to retrieve
 * data for that directory.  Similarly, if
 * %OSTREE_REPO_COMMIT_ITER_RESULT_FILE is returned, call
 * ostree_repo_commit_traverse_iter_get_file().
 * 
 * If %OSTREE_REPO_COMMIT_ITER_RESULT_ERROR is returned, it is a
 * program error to call any further API on @iter except for
 * ostree_repo_commit_traverse_iter_clear().
 */
OstreeRepoCommitIterResult
ostree_repo_commit_traverse_iter_next (OstreeRepoCommitTraverseIter *iter,
                                       GCancellable                 *cancellable,
                                       GError                      **error)
{
  struct _OstreeRepoRealCommitTraverseIter *real =
    (struct _OstreeRepoRealCommitTraverseIter*)iter;
  OstreeRepoCommitIterResult res = OSTREE_REPO_COMMIT_ITER_RESULT_ERROR;

  if (!real->current_dir)
    {
      if (!ostree_repo_load_variant (real->repo, OSTREE_OBJECT_TYPE_DIR_TREE,
                                     real->checksum_content,
                                     &real->current_dir,
                                     error))
        goto out;
      res = OSTREE_REPO_COMMIT_ITER_RESULT_DIR;
    }
  else
    {
      guint nfiles;
      guint ndirs;
      guint idx;
      const guchar *csum;
      g_autoptr(GVariant) content_csum_v = NULL;
      g_autoptr(GVariant) meta_csum_v = NULL;
      g_autoptr(GVariant) files_variant = NULL;
      g_autoptr(GVariant) dirs_variant = NULL;

      files_variant = g_variant_get_child_value (real->current_dir, 0);
      dirs_variant = g_variant_get_child_value (real->current_dir, 1);

      nfiles = g_variant_n_children (files_variant);
      ndirs = g_variant_n_children (dirs_variant);
      if (real->idx < nfiles)
        {
          idx = real->idx;
          g_variant_get_child (files_variant, idx, "(&s@ay)",
                               &real->name,
                               &content_csum_v);

          csum = ostree_checksum_bytes_peek_validate (content_csum_v, error);
          if (!csum)
            goto out;
          ostree_checksum_inplace_from_bytes (csum, real->checksum_content);

          res = OSTREE_REPO_COMMIT_ITER_RESULT_FILE;

          real->idx++;
        }
      else if (real->idx < nfiles + ndirs)
        {
          idx = real->idx - nfiles;

          g_variant_get_child (dirs_variant, idx, "(&s@ay@ay)",
                               &real->name, &content_csum_v, &meta_csum_v);

          csum = ostree_checksum_bytes_peek_validate (content_csum_v, error);
          if (!csum)
            goto out;
          ostree_checksum_inplace_from_bytes (csum, real->checksum_content);

          csum = ostree_checksum_bytes_peek_validate (meta_csum_v, error);
          if (!csum)
            goto out;
          ostree_checksum_inplace_from_bytes (csum, real->checksum_meta);
          
          res = OSTREE_REPO_COMMIT_ITER_RESULT_DIR;

          real->idx++;
        }
      else
        res = OSTREE_REPO_COMMIT_ITER_RESULT_END;
    }
  
  real->state = res;
 out:
  return res;
}
Ejemplo n.º 9
0
/**
 * ostree_repo_list_static_delta_names:
 * @self: Repo
 * @out_deltas: (out) (element-type utf8) (transfer container): String name of deltas (checksum-checksum.delta)
 * @cancellable: Cancellable
 * @error: Error
 *
 * This function synchronously enumerates all static deltas in the
 * repository, returning its result in @out_deltas.
 */
gboolean
ostree_repo_list_static_delta_names (OstreeRepo                  *self,
                                     GPtrArray                  **out_deltas,
                                     GCancellable                *cancellable,
                                     GError                     **error)
{
    gboolean ret = FALSE;
    g_autoptr(GPtrArray) ret_deltas = NULL;
    g_autoptr(GFileEnumerator) dir_enum = NULL;

    ret_deltas = g_ptr_array_new_with_free_func (g_free);

    if (g_file_query_exists (self->deltas_dir, NULL))
    {
        dir_enum = g_file_enumerate_children (self->deltas_dir, OSTREE_GIO_FAST_QUERYINFO,
                                              G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                              NULL, error);
        if (!dir_enum)
            goto out;

        while (TRUE)
        {
            g_autoptr(GFileEnumerator) dir_enum2 = NULL;
            GFileInfo *file_info;
            GFile *child;

            if (!g_file_enumerator_iterate (dir_enum, &file_info, &child,
                                            NULL, error))
                goto out;
            if (file_info == NULL)
                break;

            if (g_file_info_get_file_type (file_info) != G_FILE_TYPE_DIRECTORY)
                continue;


            dir_enum2 = g_file_enumerate_children (child, OSTREE_GIO_FAST_QUERYINFO,
                                                   G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS,
                                                   NULL, error);
            if (!dir_enum2)
                goto out;

            while (TRUE)
            {
                GFileInfo *file_info2;
                GFile *child2;
                const char *name1;
                const char *name2;

                if (!g_file_enumerator_iterate (dir_enum2, &file_info2, &child2,
                                                NULL, error))
                    goto out;
                if (file_info2 == NULL)
                    break;

                if (g_file_info_get_file_type (file_info2) != G_FILE_TYPE_DIRECTORY)
                    continue;

                name1 = g_file_info_get_name (file_info);
                name2 = g_file_info_get_name (file_info2);

                {
                    g_autoptr(GFile) meta_path = g_file_get_child (child2, "superblock");

                    if (g_file_query_exists (meta_path, NULL))
                    {
                        g_autofree char *buf = g_strconcat (name1, name2, NULL);
                        GString *out = g_string_new ("");
                        char checksum[OSTREE_SHA256_STRING_LEN+1];
                        guchar csum[OSTREE_SHA256_DIGEST_LEN];
                        const char *dash = strchr (buf, '-');

                        ostree_checksum_b64_inplace_to_bytes (buf, csum);
                        ostree_checksum_inplace_from_bytes (csum, checksum);
                        g_string_append (out, checksum);
                        if (dash)
                        {
                            g_string_append_c (out, '-');
                            ostree_checksum_b64_inplace_to_bytes (dash+1, csum);
                            ostree_checksum_inplace_from_bytes (csum, checksum);
                            g_string_append (out, checksum);
                        }

                        g_ptr_array_add (ret_deltas, g_string_free (out, FALSE));
                    }
                }
            }
        }
    }

    ret = TRUE;
    if (out_deltas)
        *out_deltas = g_steal_pointer (&ret_deltas);
out:
    return ret;
}
Ejemplo n.º 10
0
/**
 * ostree_repo_remote_list_refs:
 * @self: Repo
 * @remote_name: Name of the remote.
 * @out_all_refs: (out) (element-type utf8 utf8): Mapping from ref to checksum
 * @cancellable: Cancellable
 * @error: Error
 *
 */
gboolean
ostree_repo_remote_list_refs (OstreeRepo       *self,
                              const char       *remote_name,
                              GHashTable      **out_all_refs,
                              GCancellable     *cancellable,
                              GError          **error)
{
  g_autoptr(GBytes) summary_bytes = NULL;
  g_autoptr(GHashTable) ret_all_refs = NULL;

  if (!ostree_repo_remote_fetch_summary (self, remote_name,
                                         &summary_bytes, NULL,
                                         cancellable, error))
    return FALSE;

  if (summary_bytes == NULL)
    {
      return glnx_throw (error, "Remote refs not available; server has no summary file");
    }
  else
    {
      g_autoptr(GVariant) summary = NULL;
      g_autoptr(GVariant) ref_map = NULL;
      GVariantIter iter;
      GVariant *child;
      ret_all_refs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);

      summary = g_variant_new_from_bytes (OSTREE_SUMMARY_GVARIANT_FORMAT,
                                          summary_bytes, FALSE);

      ref_map = g_variant_get_child_value (summary, 0);

      g_variant_iter_init (&iter, ref_map);
      while ((child = g_variant_iter_next_value (&iter)) != NULL)
        {
          const char *ref_name = NULL;
          g_autoptr(GVariant) csum_v = NULL;
          char tmp_checksum[OSTREE_SHA256_STRING_LEN+1];

          g_variant_get_child (child, 0, "&s", &ref_name);

          if (ref_name != NULL)
            {
              g_variant_get_child (child, 1, "(t@aya{sv})", NULL, &csum_v, NULL);

              const guchar *csum_bytes = ostree_checksum_bytes_peek_validate (csum_v, error);
              if (csum_bytes == NULL)
                return FALSE;

              ostree_checksum_inplace_from_bytes (csum_bytes, tmp_checksum);

              g_hash_table_insert (ret_all_refs,
                                   g_strdup (ref_name),
                                   g_strdup (tmp_checksum));
            }

          g_variant_unref (child);
        }
    }

  ot_transfer_out_value (out_all_refs, &ret_all_refs);
  return TRUE;
}