static gboolean
do_content_open_generic (OstreeRepo                 *repo,
                         StaticDeltaExecutionState  *state,
                         GCancellable               *cancellable,  
                         GError                    **error)
{
  gboolean ret = FALSE;
  g_autoptr(GVariant) modev = NULL;
  guint64 mode_offset;
  guint64 xattr_offset;
  guint32 uid, gid, mode;

  if (!read_varuint64 (state, &mode_offset, error))
    goto out;
  if (!read_varuint64 (state, &xattr_offset, error))
    goto out;

  state->barecommitstate.fd = -1;

  modev = g_variant_get_child_value (state->mode_dict, mode_offset);
  g_variant_get (modev, "(uuu)", &uid, &gid, &mode);
  state->uid = GUINT32_FROM_BE (uid);
  state->gid = GUINT32_FROM_BE (gid);
  state->mode = GUINT32_FROM_BE (mode);

  state->xattrs = g_variant_get_child_value (state->xattr_dict, xattr_offset);

  ret = TRUE;
 out:
  return ret;
}
static gboolean
dispatch_bspatch (OstreeRepo                 *repo,
                  StaticDeltaExecutionState  *state,
                  GCancellable               *cancellable,
                  GError                    **error)
{
  gboolean ret = FALSE;
  guint64 offset, length;
  g_autoptr(GInputStream) in_stream = NULL;
  g_autoptr(GMappedFile) input_mfile = NULL;
  g_autofree guchar *buf = NULL;
  struct bspatch_stream stream;
  struct bzpatch_opaque_s opaque;
  gsize bytes_written;

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

  if (!state->have_obj)
    {
      input_mfile = g_mapped_file_new_from_fd (state->read_source_fd, FALSE, error);
      if (!input_mfile)
        goto out;

      buf = g_malloc0 (state->content_size);

      opaque.state = state;
      opaque.offset = offset;
      opaque.length = length;
      stream.read = bspatch_read;
      stream.opaque = &opaque;
      if (bspatch ((const guint8*)g_mapped_file_get_contents (input_mfile),
                   g_mapped_file_get_length (input_mfile),
                   buf,
                   state->content_size,
                   &stream) < 0)
        goto out;

      if (!g_output_stream_write_all (state->content_out,
                                      buf,
                                      state->content_size,
                                      &bytes_written,
                                      cancellable, error))
        goto out;

      g_assert (bytes_written == state->content_size);
    }

  ret = TRUE;
 out:
  return ret;
}
static gboolean
dispatch_set_read_source (OstreeRepo                 *repo,
                          StaticDeltaExecutionState  *state,
                          GCancellable               *cancellable,  
                          GError                    **error)
{
  gboolean ret = FALSE;
  guint64 source_offset;

  if (state->read_source_fd)
    {
      (void) close (state->read_source_fd);
      state->read_source_fd = -1;
    }

  if (!read_varuint64 (state, &source_offset, error))
    goto out;
  if (!validate_ofs (state, source_offset, 32, error))
    goto out;

  g_free (state->read_source_object);
  state->read_source_object = ostree_checksum_from_bytes (state->payload_data + source_offset);
  
  if (!_ostree_repo_read_bare_fd (repo, state->read_source_object, &state->read_source_fd,
                                  cancellable, error))
    goto out;
  
  ret = TRUE;
 out:
  if (!ret)
    g_prefix_error (error, "opcode set-read-source: ");
  return ret;
}
示例#4
0
static size_t
squash_brieflz_get_uncompressed_size (SquashCodec* codec,
                                      size_t compressed_size,
                                      const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_size)]) {
  uint64_t v;

  return read_varuint64 (compressed, compressed_size, &v) == 0 ? 0 : v;
}
static gboolean
dispatch_open (OstreeRepo                 *repo,
               StaticDeltaExecutionState  *state,
               GCancellable               *cancellable,  
               GError                    **error)
{
  gboolean ret = FALSE;

  g_assert (state->output_target == NULL);
  /* FIXME - lift this restriction */
  if (!state->stats_only)
    {
      g_assert (repo->mode == OSTREE_REPO_MODE_BARE ||
                repo->mode == OSTREE_REPO_MODE_BARE_USER ||
                repo->mode == OSTREE_REPO_MODE_BARE_USER_ONLY);
    }
  
  if (!open_output_target (state, cancellable, error))
    goto out;

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

  if (!read_varuint64 (state, &state->content_size, error))
    goto out;

  if (state->stats_only)
    {
      ret = TRUE;
      goto out;
    }
  
  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 (!handle_untrusted_content_checksum (repo, state, cancellable, error))
    goto out;

  ret = TRUE;
 out:
  if (!ret)
    g_prefix_error (error, "opcode open: ");
  return ret;
}
示例#6
0
static SquashStatus
squash_brieflz_decompress_buffer (SquashCodec* codec,
                                  size_t* decompressed_size,
                                  uint8_t decompressed[SQUASH_ARRAY_PARAM(*decompressed_size)],
                                  size_t compressed_size,
                                  const uint8_t compressed[SQUASH_ARRAY_PARAM(compressed_size)],
                                  SquashOptions* options) {
  const uint8_t *src = compressed;
  uint64_t original_size;
  size_t size;

  size = read_varuint64 (src, compressed_size, &original_size);

  if (SQUASH_UNLIKELY(size == 0)) {
    return squash_error (SQUASH_FAILED);
  }

  src += size;
  compressed_size -= size;

  if (SQUASH_UNLIKELY(original_size > *decompressed_size)) {
    return squash_error (SQUASH_BUFFER_FULL);
  }

#if ULONG_MAX < SIZE_MAX
  if (SQUASH_UNLIKELY(ULONG_MAX < compressed_size) ||
      SQUASH_UNLIKELY(ULONG_MAX < original_size))
    return squash_error (SQUASH_RANGE);
#endif

  size = blz_depack_safe (src, (unsigned long) compressed_size,
                          decompressed, (unsigned long) original_size);

  if (SQUASH_UNLIKELY(size != original_size)) {
    return squash_error (SQUASH_FAILED);
  }

#if SIZE_MAX < ULONG_MAX
  if (SQUASH_UNLIKELY(SIZE_MAX < size))
    return squash_error (SQUASH_RANGE);
#endif

  *decompressed_size = size;

  return SQUASH_OK;
}
static gboolean
dispatch_write (OstreeRepo                 *repo,
               StaticDeltaExecutionState  *state,
               GCancellable               *cancellable,  
               GError                    **error)
{
  gboolean ret = FALSE;
  guint64 content_size;
  guint64 content_offset;
      
  if (!read_varuint64 (state, &content_size, error))
    goto out;
  if (!read_varuint64 (state, &content_offset, error))
    goto out;

  if (state->stats_only)
    {
      ret = TRUE;
      goto out;
    }

  if (!state->have_obj)
    {
      if (state->read_source_fd != -1)
        {
          if (lseek (state->read_source_fd, content_offset, SEEK_SET) == -1)
            {
              glnx_set_error_from_errno (error);
              goto out;
            }
          while (content_size > 0)
            {
              char buf[4096];
              gssize bytes_read;

              do
                bytes_read = read (state->read_source_fd, buf, MIN(sizeof(buf), content_size));
              while (G_UNLIKELY (bytes_read == -1 && errno == EINTR));
              if (bytes_read == -1)
                {
                  glnx_set_error_from_errno (error);
                  goto out;
                }
              if (G_UNLIKELY (bytes_read == 0))
                {
                  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
                               "Unexpected EOF reading object %s", state->read_source_object);
                  goto out;
                }
              
              if (!content_out_write (repo, state, (guint8*)buf, bytes_read,
                                      cancellable, error))
                goto out;
              
              content_size -= bytes_read;
            }
        }
      else
        {
          if (!validate_ofs (state, content_offset, content_size, error))
            goto out;

          if (!content_out_write (repo, state, state->payload_data + content_offset, content_size,
                                  cancellable, error))
            goto out;
        }
    }
  
  ret = TRUE;
 out:
  if (!ret)
    g_prefix_error (error, "opcode open-splice-and-close: ");
  return ret;
}
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;
}