コード例 #1
0
ファイル: commit.c プロジェクト: DJEX93/dsploit
static svn_error_t *
close_file(void *file_baton,
           const char *text_digest,
           apr_pool_t *pool)
{
  struct file_baton *fb = file_baton;

  if (text_digest)
    {
      svn_checksum_t *checksum;
      svn_checksum_t *text_checksum;

      SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5,
                                   fb->edit_baton->txn_root, fb->path,
                                   TRUE, pool));
      SVN_ERR(svn_checksum_parse_hex(&text_checksum, svn_checksum_md5,
                                     text_digest, pool));

      if (!svn_checksum_match(text_checksum, checksum))
        return svn_checksum_mismatch_err(text_checksum, checksum, pool,
                            _("Checksum mismatch for resulting fulltext\n(%s)"),
                            fb->path);
    }

  return SVN_NO_ERROR;
}
コード例 #2
0
ファイル: dag.c プロジェクト: matthewdpklanier/alien-svn
svn_error_t *
svn_fs_fs__dag_finalize_edits(dag_node_t *file,
                              const svn_checksum_t *checksum,
                              apr_pool_t *pool)
{
    if (checksum)
    {
        svn_checksum_t *file_checksum;

        SVN_ERR(svn_fs_fs__dag_file_checksum(&file_checksum, file,
                                             checksum->kind, pool));
        if (!svn_checksum_match(checksum, file_checksum))
            return svn_error_createf(SVN_ERR_CHECKSUM_MISMATCH, NULL,
                                     _("Checksum mismatch, file '%s':\n"
                                       "   expected:  %s\n"
                                       "     actual:  %s\n"),
                                     file->created_path,
                                     svn_checksum_to_cstring_display(checksum,
                                             pool),
                                     svn_checksum_to_cstring_display(file_checksum,
                                             pool));
    }

    return SVN_NO_ERROR;
}
コード例 #3
0
/* Increment records[rep] if both are non-NULL and REP contains a sha1.
 * Allocate keys and values in RESULT_POOL.
 */
static svn_error_t *record(apr_hash_t *records,
                           representation_t *rep,
                           apr_pool_t *result_pool)
{
  struct key_t *key;
  struct value_t *value;

  /* Skip if we ignore this particular kind of reps, or if the rep doesn't
   * exist or doesn't have the checksum we are after.  (The latter case
   * often corresponds to node_rev->kind == svn_node_dir.)
   */
  if (records == NULL || rep == NULL || rep->sha1_checksum == NULL)
    return SVN_NO_ERROR;

  /* Construct the key.
   *
   * Must use calloc() because apr_hash_* pay attention to padding bytes too.
   */
  key = apr_pcalloc(result_pool, sizeof(*key));
  key->revision = rep->revision;
  key->offset = rep->offset;

  /* Update or create the value. */
  if ((value = apr_hash_get(records, key, sizeof(*key))))
    {
      /* Paranoia. */
      SVN_ERR_ASSERT(value->sha1_checksum != NULL);
      SVN_ERR_ASSERT(svn_checksum_match(value->sha1_checksum,
                                        rep->sha1_checksum));
      /* Real work. */
      value->refcount++;
    }
  else
    {
      value = apr_palloc(result_pool, sizeof(*value));
      value->sha1_checksum = svn_checksum_dup(rep->sha1_checksum, result_pool);
      value->refcount = 1;
    }

  /* Store them. */
  apr_hash_set(records, key, sizeof(*key), value);

  return SVN_NO_ERROR;
}
コード例 #4
0
ファイル: dag.c プロジェクト: geofft/subversion
svn_error_t *
svn_fs_x__dag_finalize_edits(dag_node_t *file,
                             const svn_checksum_t *checksum,
                             apr_pool_t *pool)
{
  if (checksum)
    {
      svn_checksum_t *file_checksum;

      SVN_ERR(svn_fs_x__dag_file_checksum(&file_checksum, file,
                                          checksum->kind, pool));
      if (!svn_checksum_match(checksum, file_checksum))
        return svn_checksum_mismatch_err(checksum, file_checksum, pool,
                                         _("Checksum mismatch for '%s'"),
                                         file->created_path);
    }

  return SVN_NO_ERROR;
}
コード例 #5
0
ファイル: copy_foreign.c プロジェクト: 2asoft/freebsd
static svn_error_t *
file_close(void *file_baton,
           const char *text_checksum,
           apr_pool_t *scratch_pool)
{
  struct file_baton_t *fb = file_baton;
  struct edit_baton_t *eb = fb->eb;
  struct dir_baton_t *pb = fb->pb;

  SVN_ERR(ensure_added(pb, fb->pool));

  if (text_checksum)
    {
      svn_checksum_t *expected_checksum;
      svn_checksum_t *actual_checksum;

      SVN_ERR(svn_checksum_parse_hex(&expected_checksum, svn_checksum_md5,
                                     text_checksum, fb->pool));
      actual_checksum = svn_checksum__from_digest_md5(fb->digest, fb->pool);

      if (! svn_checksum_match(expected_checksum, actual_checksum))
        return svn_error_trace(
                    svn_checksum_mismatch_err(expected_checksum,
                                              actual_checksum,
                                              fb->pool,
                                         _("Checksum mismatch for '%s'"),
                                              svn_dirent_local_style(
                                                    fb->local_abspath,
                                                    fb->pool)));
    }

  SVN_ERR(svn_wc_add_from_disk3(eb->wc_ctx, fb->local_abspath, fb->properties,
                                TRUE /* skip checks */,
                                eb->notify_func, eb->notify_baton,
                                fb->pool));

  svn_pool_destroy(fb->pool);
  SVN_ERR(maybe_done(pb));

  return SVN_NO_ERROR;
}
コード例 #6
0
ファイル: wc_editor.c プロジェクト: svn2github/subversion
static svn_error_t *
file_close(void *file_baton,
           const char *text_checksum,
           apr_pool_t *scratch_pool)
{
  struct file_baton_t *fb = file_baton;
  struct dir_baton_t *pb = fb->pb;

  if (fb->writing_file)
    SVN_ERR(svn_io_file_rename2(fb->writing_file, fb->local_abspath,
                                FALSE /*flush*/, scratch_pool));

  if (text_checksum)
    {
      svn_checksum_t *expected_checksum;
      svn_checksum_t *actual_checksum;

      SVN_ERR(svn_checksum_parse_hex(&expected_checksum, svn_checksum_md5,
                                     text_checksum, fb->pool));
      actual_checksum = svn_checksum__from_digest_md5(fb->digest, fb->pool);

      if (! svn_checksum_match(expected_checksum, actual_checksum))
        return svn_error_trace(
                    svn_checksum_mismatch_err(expected_checksum,
                                              actual_checksum,
                                              fb->pool,
                                         _("Checksum mismatch for '%s'"),
                                              svn_dirent_local_style(
                                                    fb->local_abspath,
                                                    fb->pool)));
    }

  SVN_ERR(ensure_added_file(fb, fb->pool));

  svn_pool_destroy(fb->pool);
  SVN_ERR(maybe_done(pb));

  return SVN_NO_ERROR;
}
コード例 #7
0
ファイル: load-fs-vtable.c プロジェクト: 2asoft/freebsd
/* Perform a copy or a plain add.
 *
 * For a copy, also adjust the copy-from rev, check any copy-source checksum,
 * and send a notification.
 */
static svn_error_t *
maybe_add_with_history(struct node_baton *nb,
                       struct revision_baton *rb,
                       apr_pool_t *pool)
{
  struct parse_baton *pb = rb->pb;

  if ((nb->copyfrom_path == NULL) || (! pb->use_history))
    {
      /* Add empty file or dir, without history. */
      if (nb->kind == svn_node_file)
        SVN_ERR(svn_fs_make_file(rb->txn_root, nb->path, pool));

      else if (nb->kind == svn_node_dir)
        SVN_ERR(svn_fs_make_dir(rb->txn_root, nb->path, pool));
    }
  else
    {
      /* Hunt down the source revision in this fs. */
      svn_fs_root_t *copy_root;
      svn_revnum_t copyfrom_rev;

      /* Try to find the copyfrom revision in the revision map;
         failing that, fall back to the revision offset approach. */
      copyfrom_rev = get_revision_mapping(rb->pb->rev_map, nb->copyfrom_rev);
      if (! SVN_IS_VALID_REVNUM(copyfrom_rev))
        copyfrom_rev = nb->copyfrom_rev - rb->rev_offset;

      if (! SVN_IS_VALID_REVNUM(copyfrom_rev))
        return svn_error_createf(SVN_ERR_FS_NO_SUCH_REVISION, NULL,
                                 _("Relative source revision %ld is not"
                                   " available in current repository"),
                                 copyfrom_rev);

      SVN_ERR(svn_fs_revision_root(&copy_root, pb->fs, copyfrom_rev, pool));

      if (nb->copy_source_checksum)
        {
          svn_checksum_t *checksum;
          SVN_ERR(svn_fs_file_checksum(&checksum, svn_checksum_md5, copy_root,
                                       nb->copyfrom_path, TRUE, pool));
          if (!svn_checksum_match(nb->copy_source_checksum, checksum))
            return svn_checksum_mismatch_err(nb->copy_source_checksum,
                      checksum, pool,
                      _("Copy source checksum mismatch on copy from '%s'@%ld\n"
                        "to '%s' in rev based on r%ld"),
                      nb->copyfrom_path, copyfrom_rev, nb->path, rb->rev);
        }

      SVN_ERR(svn_fs_copy(copy_root, nb->copyfrom_path,
                          rb->txn_root, nb->path, pool));

      if (pb->notify_func)
        {
          /* ### TODO: Use proper scratch pool instead of pb->notify_pool */
          svn_repos_notify_t *notify = svn_repos_notify_create(
                                            svn_repos_notify_load_copied_node,
                                            pb->notify_pool);

          pb->notify_func(pb->notify_baton, notify, pb->notify_pool);
          svn_pool_clear(pb->notify_pool);
        }
    }

  return SVN_NO_ERROR;
}
コード例 #8
0
ファイル: checksum-test.c プロジェクト: geofft/subversion
static svn_error_t *
zero_match(apr_pool_t *pool)
{
  svn_checksum_t *zero_md5;
  svn_checksum_t *zero_sha1;
  svn_checksum_t *A_md5;
  svn_checksum_t *B_md5;
  svn_checksum_t *A_sha1;
  svn_checksum_t *B_sha1;


  zero_md5 = svn_checksum_create(svn_checksum_md5, pool);
  SVN_ERR(svn_checksum_clear(zero_md5));
  SVN_ERR(svn_checksum(&A_md5, svn_checksum_md5, "A", 1, pool));
  SVN_ERR(svn_checksum(&B_md5, svn_checksum_md5, "B", 1, pool));

  zero_sha1 = svn_checksum_create(svn_checksum_sha1, pool);
  SVN_ERR(svn_checksum_clear(zero_sha1));
  SVN_ERR(svn_checksum(&A_sha1, svn_checksum_sha1, "A", 1, pool));
  SVN_ERR(svn_checksum(&B_sha1, svn_checksum_sha1, "B", 1, pool));

  /* Different non-zero don't match. */
  SVN_TEST_ASSERT(!svn_checksum_match(A_md5, B_md5));
  SVN_TEST_ASSERT(!svn_checksum_match(A_sha1, B_sha1));
  SVN_TEST_ASSERT(!svn_checksum_match(A_md5, A_sha1));
  SVN_TEST_ASSERT(!svn_checksum_match(A_md5, B_sha1));

  /* Zero matches anything of the same kind. */
  SVN_TEST_ASSERT(svn_checksum_match(A_md5, zero_md5));
  SVN_TEST_ASSERT(svn_checksum_match(zero_md5, B_md5));
  SVN_TEST_ASSERT(svn_checksum_match(A_sha1, zero_sha1));
  SVN_TEST_ASSERT(svn_checksum_match(zero_sha1, B_sha1));

  /* Zero doesn't match anything of a different kind... */
  SVN_TEST_ASSERT(!svn_checksum_match(zero_md5, A_sha1));
  SVN_TEST_ASSERT(!svn_checksum_match(zero_sha1, A_md5));
  /* ...even another zero. */
  SVN_TEST_ASSERT(!svn_checksum_match(zero_md5, zero_sha1));

  return SVN_NO_ERROR;
}
コード例 #9
0
/* Exercise the pristine text API with a simple write and read. */
static svn_error_t *
pristine_write_read(const svn_test_opts_t *opts,
                    apr_pool_t *pool)
{
  svn_wc__db_t *db;
  const char *wc_abspath;

  svn_wc__db_install_data_t *install_data;
  svn_stream_t *pristine_stream;
  apr_size_t sz;

  const char data[] = "Blah";
  svn_string_t *data_string = svn_string_create(data, pool);
  svn_checksum_t *data_sha1, *data_md5;

  SVN_ERR(create_repos_and_wc(&wc_abspath, &db,
                              "pristine_write_read", opts, pool));

  /* Write DATA into a new temporary pristine file, set PRISTINE_TMP_ABSPATH
   * to its path and set DATA_SHA1 and DATA_MD5 to its checksums. */
  SVN_ERR(svn_wc__db_pristine_prepare_install(&pristine_stream,
                                              &install_data,
                                              &data_sha1, &data_md5,
                                              db, wc_abspath,
                                              pool, pool));

  sz = strlen(data);
  SVN_ERR(svn_stream_write(pristine_stream, data, &sz));
  SVN_ERR(svn_stream_close(pristine_stream));

  /* Ensure it's not already in the store. */
  {
    svn_boolean_t present;

    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
                                      pool));
    SVN_TEST_ASSERT(! present);
  }

  /* Install the new pristine file, referenced by its checksum. */
  SVN_ERR(svn_wc__db_pristine_install(install_data,
                                      data_sha1, data_md5, pool));

  /* Ensure it is now found in the store. */
  {
    svn_boolean_t present;

    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
                                      pool));
    SVN_TEST_ASSERT(present);
  }

  /* Look up its MD-5 from its SHA-1, and check it's the same MD-5. */
  {
    const svn_checksum_t *looked_up_md5;

    SVN_ERR(svn_wc__db_pristine_get_md5(&looked_up_md5, db, wc_abspath,
                                        data_sha1, pool, pool));
    SVN_TEST_ASSERT(looked_up_md5->kind == svn_checksum_md5);
    SVN_TEST_ASSERT(svn_checksum_match(data_md5, looked_up_md5));
  }

  /* Read the pristine text back and verify it's the same content. */
  {
    svn_stream_t *data_stream = svn_stream_from_string(data_string, pool);
    svn_stream_t *data_read_back;
    svn_boolean_t same;

    SVN_ERR(svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath,
                                     data_sha1, pool, pool));
    SVN_ERR(svn_stream_contents_same2(&same, data_read_back, data_stream,
                                      pool));
    SVN_TEST_ASSERT(same);
  }

  /* Trivially test the "remove if unreferenced" API: it's not referenced
     so we should be able to remove it. */
  {
    svn_error_t *err;
    svn_stream_t *data_read_back;

    SVN_ERR(svn_wc__db_pristine_remove(db, wc_abspath, data_sha1, pool));
    err = svn_wc__db_pristine_read(&data_read_back, NULL, db, wc_abspath,
                                   data_sha1, pool, pool);
    SVN_TEST_ASSERT_ERROR(err, SVN_ERR_WC_PATH_NOT_FOUND);
  }

  /* Ensure it's no longer found in the store. */
  {
    svn_boolean_t present;

    SVN_ERR(svn_wc__db_pristine_check(&present, db, wc_abspath, data_sha1,
                                      pool));
    SVN_TEST_ASSERT(! present);
  }

  return SVN_NO_ERROR;
}
コード例 #10
0
ファイル: window-test.c プロジェクト: aosm/subversion
static svn_error_t *
stream_window_test(const char **msg,
                   svn_boolean_t msg_only,
                   svn_test_opts_t *opts,
                   apr_pool_t *pool)
{
  /* Note: put these in data segment, not the stack */
  static char source[109001];
  static char target[109001];
  int i;
  char *p = &source[9];
  svn_checksum_t *expected;
  svn_checksum_t *actual;
  svn_string_t source_str;
  svn_string_t target_str;
  svn_stream_t *source_stream;
  svn_stream_t *target_stream;
  svn_txdelta_stream_t *txstream;

  *msg = "txdelta stream and windows test";
  if (msg_only)
    return SVN_NO_ERROR;

  memcpy(source, "a\nb\nc\nd\ne", 9);
  for (i = 100; i--; )
    *p++ = '\n';
  for (i = 999; i--; p += 109)
    memcpy(p, source, 109);
  source[109000] = '\0';

  memcpy(target, source, 109001);
  for (i = 1000; i--; )
    target[i*109 + 4] = 'X';

  SVN_ERR(svn_checksum(&expected, svn_checksum_md5, target, 109000, pool));
  /* f6fd44565e14c6e44b35292719deb77e */
  printf("expected: %s\n", svn_checksum_to_cstring(expected, pool));

  source_str.data = source;
  source_str.len = 109000;
  source_stream = svn_stream_from_string(&source_str, pool);

  target_str.data = target;
  target_str.len = 109000;
  target_stream = svn_stream_from_string(&target_str, pool);

  svn_txdelta(&txstream, source_stream, target_stream, pool);

  while (1)
    {
      svn_txdelta_window_t *window;

      SVN_ERR(svn_txdelta_next_window(&window, txstream, pool));
      if (window == NULL)
        break;

      /* ### examine the window */
    }

  actual = svn_checksum__from_digest(svn_txdelta_md5_digest(txstream),
                                     svn_checksum_md5, pool);;
  printf("  actual: %s\n", svn_checksum_to_cstring(actual, pool));

  if (!svn_checksum_match(expected, actual))
    {
      return svn_error_create(SVN_ERR_TEST_FAILED, NULL,
                              "Checksums did not match.");
    }

  return SVN_NO_ERROR;
}
コード例 #11
0
ファイル: repos_diff.c プロジェクト: dtrebbien/subversion
/* An svn_delta_editor_t function.  When the file is closed we have a temporary
 * file containing a pristine version of the repository file. This can
 * be compared against the working copy.
 *
 * ### Ignore TEXT_CHECKSUM for now.  Someday we can use it to verify
 * ### the integrity of the file being diffed.  Done efficiently, this
 * ### would probably involve calculating the checksum as the data is
 * ### received, storing the final checksum in the file_baton, and
 * ### comparing against it here.
 */
static svn_error_t *
close_file(void *file_baton,
           const char *expected_md5_digest,
           apr_pool_t *pool)
{
  struct file_baton *b = file_baton;
  struct edit_baton *eb = b->edit_baton;
  svn_wc_notify_state_t content_state = svn_wc_notify_state_unknown;
  svn_wc_notify_state_t prop_state = svn_wc_notify_state_unknown;
  apr_pool_t *scratch_pool;

  /* Skip *everything* within a newly tree-conflicted directory. */
  if (b->skip)
    {
      svn_pool_destroy(b->pool);
      return SVN_NO_ERROR;
    }

  scratch_pool = b->pool;

  if (expected_md5_digest && eb->text_deltas)
    {
      svn_checksum_t *expected_md5_checksum;

      SVN_ERR(svn_checksum_parse_hex(&expected_md5_checksum, svn_checksum_md5,
                                     expected_md5_digest, scratch_pool));

      if (!svn_checksum_match(expected_md5_checksum, b->result_md5_checksum))
        return svn_error_trace(svn_checksum_mismatch_err(
                                      expected_md5_checksum,
                                      b->result_md5_checksum,
                                      pool,
                                      _("Checksum mismatch for '%s'"),
                                      b->path));
    }

  if (!b->added && b->propchanges->nelts > 0)
    {
      if (!b->pristine_props)
        {
          /* We didn't receive a text change, so we have no pristine props.
             Retrieve just the props now. */
          SVN_ERR(get_file_from_ra(b, TRUE, scratch_pool));
        }

      remove_non_prop_changes(b->pristine_props, b->propchanges);
    }

  if (b->path_end_revision || b->propchanges->nelts > 0)
    {
      const char *mimetype1, *mimetype2;
      get_file_mime_types(&mimetype1, &mimetype2, b);


      if (b->added)
        SVN_ERR(eb->diff_callbacks->file_added(
                 &content_state, &prop_state, &b->tree_conflicted,
                 b->path,
                 b->path_end_revision ? b->path_start_revision : NULL,
                 b->path_end_revision,
                 0,
                 b->edit_baton->target_revision,
                 mimetype1, mimetype2,
                 NULL, SVN_INVALID_REVNUM,
                 b->propchanges, b->pristine_props,
                 b->edit_baton->diff_cmd_baton,
                 scratch_pool));
      else
        SVN_ERR(eb->diff_callbacks->file_changed(
                 &content_state, &prop_state,
                 &b->tree_conflicted, b->path,
                 b->path_end_revision ? b->path_start_revision : NULL,
                 b->path_end_revision,
                 b->edit_baton->revision,
                 b->edit_baton->target_revision,
                 mimetype1, mimetype2,
                 b->propchanges, b->pristine_props,
                 b->edit_baton->diff_cmd_baton,
                 scratch_pool));
    }


  if (eb->notify_func)
    {
      deleted_path_notify_t *dpn;
      svn_wc_notify_t *notify;
      svn_wc_notify_action_t action;
      svn_node_kind_t kind = svn_node_file;

      /* Find out if a pending delete notification for this path is
       * still around. */
      dpn = apr_hash_get(eb->deleted_paths, b->path, APR_HASH_KEY_STRING);
      if (dpn)
        {
          /* If any was found, we will handle the pending 'deleted path
           * notification' (DPN) here. Remove it from the list. */
          apr_hash_set(eb->deleted_paths, b->path,
                       APR_HASH_KEY_STRING, NULL);

          /* the pending delete might be on a different node kind. */
          kind = dpn->kind;
          content_state = prop_state = dpn->state;
        }

      /* Determine what the notification (ACTION) should be.
       * In case of a pending 'delete', this might become a 'replace'. */
      if (b->tree_conflicted)
        action = svn_wc_notify_tree_conflict;
      else if (dpn)
        {
          if (dpn->action == svn_wc_notify_update_delete
              && b->added)
            action = svn_wc_notify_update_replace;
          else
            /* Note: dpn->action might be svn_wc_notify_tree_conflict */
            action = dpn->action;
        }
      else if ((content_state == svn_wc_notify_state_missing)
                || (content_state == svn_wc_notify_state_obstructed))
        action = svn_wc_notify_skip;
      else if (b->added)
        action = svn_wc_notify_update_add;
      else
        action = svn_wc_notify_update_update;

      notify = svn_wc_create_notify(b->path, action, scratch_pool);
      notify->kind = kind;
      notify->content_state = content_state;
      notify->prop_state = prop_state;
      (*eb->notify_func)(eb->notify_baton, notify, scratch_pool);
    }

  svn_pool_destroy(b->pool); /* Destroy file and scratch pool */

  return SVN_NO_ERROR;
}
コード例 #12
0
ファイル: repos_diff.c プロジェクト: dtrebbien/subversion
/* An svn_delta_editor_t function.  */
static svn_error_t *
apply_textdelta(void *file_baton,
                const char *base_md5_digest,
                apr_pool_t *pool,
                svn_txdelta_window_handler_t *handler,
                void **handler_baton)
{
  struct file_baton *b = file_baton;
  svn_stream_t *src_stream;
  svn_stream_t *result_stream;
  apr_pool_t *scratch_pool = b->pool;

  /* Skip *everything* within a newly tree-conflicted directory. */
  if (b->skip)
    {
      *handler = svn_delta_noop_window_handler;
      *handler_baton = NULL;
      return SVN_NO_ERROR;
    }

  /* If we're not sending file text, then ignore any that we receive. */
  if (! b->edit_baton->text_deltas)
    {
      /* Supply valid paths to indicate there is a text change. */
      SVN_ERR(get_empty_file(b->edit_baton, &b->path_start_revision));
      SVN_ERR(get_empty_file(b->edit_baton, &b->path_end_revision));

      *handler = svn_delta_noop_window_handler;
      *handler_baton = NULL;

      return SVN_NO_ERROR;
    }

  /* We need the expected pristine file, so go get it */
  if (!b->added)
    SVN_ERR(get_file_from_ra(b, FALSE, scratch_pool));
  else
    SVN_ERR(get_empty_file(b->edit_baton, &(b->path_start_revision)));

  SVN_ERR_ASSERT(b->path_start_revision != NULL);

  if (base_md5_digest != NULL)
    {
      svn_checksum_t *base_md5_checksum;

      SVN_ERR(svn_checksum_parse_hex(&base_md5_checksum, svn_checksum_md5,
                                     base_md5_digest, scratch_pool));

      if (!svn_checksum_match(base_md5_checksum, b->start_md5_checksum))
        return svn_error_trace(svn_checksum_mismatch_err(
                                      base_md5_checksum,
                                      b->start_md5_checksum,
                                      scratch_pool,
                                      _("Base checksum mismatch for '%s'"),
                                      b->path));
    }

  /* Open the file to be used as the base for second revision */
  SVN_ERR(svn_stream_open_readonly(&src_stream, b->path_start_revision,
                                   scratch_pool, scratch_pool));

  /* Open the file that will become the second revision after applying the
     text delta, it starts empty */
  SVN_ERR(svn_stream_open_unique(&result_stream, &b->path_end_revision, NULL,
                                 svn_io_file_del_on_pool_cleanup,
                                 scratch_pool, scratch_pool));

  svn_txdelta_apply(src_stream,
                    result_stream,
                    b->result_digest,
                    b->path, b->pool,
                    &(b->apply_handler), &(b->apply_baton));

  *handler = window_handler;
  *handler_baton = file_baton;

  return SVN_NO_ERROR;
}