⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_fs.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* The buffer where we store undeltified data. */  char *buf;  apr_size_t buf_pos;  apr_size_t buf_len;    /* An MD5 context for summing the data read in order to verify it. */  struct apr_md5_ctx_t md5_context;  svn_boolean_t checksum_finalized;  /* The stored checksum of the representation we are reading, its     length, and the amount we've read so far.  Some of this     information is redundant with rs_list and src_state, but it's     convenient for the checksumming code to have it here. */  unsigned char checksum[APR_MD5_DIGESTSIZE];  svn_filesize_t len;  svn_filesize_t off;  /* Used for temporary allocations during the read. */  apr_pool_t *pool;  /* Pool used to store file handles and other data that is persistant     for the entire stream read. */  apr_pool_t *filehandle_pool;};/* Create a rep_read_baton structure for node revision NODEREV in   filesystem FS and store it in *RB_P.  Perform all allocations in   POOL.  If rep is mutable, it must be for file contents. */static svn_error_t *rep_read_get_baton(struct rep_read_baton **rb_p,                   svn_fs_t *fs,                   representation_t *rep,                   apr_pool_t *pool){  struct rep_read_baton *b;  b = apr_pcalloc(pool, sizeof(*b));  b->fs = fs;  b->chunk_index = 0;  b->buf = NULL;  apr_md5_init(&(b->md5_context));  b->checksum_finalized = FALSE;  memcpy(b->checksum, rep->checksum, sizeof(b->checksum));  b->len = rep->expanded_size;  b->off = 0;  b->pool = svn_pool_create(pool);  b->filehandle_pool = svn_pool_create(pool);    SVN_ERR(build_rep_list(&b->rs_list, &b->src_state, fs, rep,                         b->filehandle_pool));  /* Save our output baton. */  *rb_p = b;  return SVN_NO_ERROR;}/* Skip forwards to THIS_CHUNK in REP_STATE and then read the next delta   window into *NWIN. */static svn_error_t *read_window(svn_txdelta_window_t **nwin, int this_chunk, struct rep_state *rs,            apr_pool_t *pool){  svn_stream_t *stream;  assert(rs->chunk_index <= this_chunk);  /* Skip windows to reach the current chunk if we aren't there yet. */  while (rs->chunk_index < this_chunk)    {      SVN_ERR(svn_txdelta_skip_svndiff_window(rs->file, rs->ver, pool));      rs->chunk_index++;      SVN_ERR(get_file_offset(&rs->off, rs->file, pool));      if (rs->off >= rs->end)        return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                                _("Reading one svndiff window read "                                  "beyond the end of the "                                  "representation"));    }  /* Read the next window. */  stream = svn_stream_from_aprfile(rs->file, pool);  SVN_ERR(svn_txdelta_read_svndiff_window(nwin, stream, rs->ver, pool));  rs->chunk_index++;  SVN_ERR(get_file_offset(&rs->off, rs->file, pool));  if (rs->off > rs->end)    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                            _("Reading one svndiff window read beyond "                              "the end of the representation"));    return SVN_NO_ERROR;}  /* Get one delta window that is a result of combining all but the last deltas   from the current desired representation identified in *RB, to its   final base representation.  Store the window in *RESULT. */static svn_error_t *get_combined_window(svn_txdelta_window_t **result,                    struct rep_read_baton *rb){  apr_pool_t *pool, *new_pool;  int i;  svn_txdelta_window_t *window, *nwin;  struct rep_state *rs;  assert(rb->rs_list->nelts >= 2);  pool = svn_pool_create(rb->pool);  /* Read the next window from the original rep. */  rs = APR_ARRAY_IDX(rb->rs_list, 0, struct rep_state *);  SVN_ERR(read_window(&window, rb->chunk_index, rs, pool));  /* Combine in the windows from the other delta reps, if needed. */  for (i = 1; i < rb->rs_list->nelts - 1; i++)    {      if (window->src_ops == 0)        break;      rs = APR_ARRAY_IDX(rb->rs_list, i, struct rep_state *);      SVN_ERR(read_window(&nwin, rb->chunk_index, rs, pool));      /* Combine this window with the current one.  Cycles pools so that we         only need to hold three windows at a time. */      new_pool = svn_pool_create(rb->pool);      window = svn_txdelta_compose_windows(nwin, window, new_pool);      svn_pool_destroy(pool);      pool = new_pool;    }  *result = window;  return SVN_NO_ERROR;}static svn_error_t *rep_read_contents_close(void *baton){  struct rep_read_baton *rb = baton;    svn_pool_destroy(rb->pool);  svn_pool_destroy(rb->filehandle_pool);    return SVN_NO_ERROR;}/* Return the next *LEN bytes of the rep and store them in *BUF. */static svn_error_t *get_contents(struct rep_read_baton *rb,             char *buf,             apr_size_t *len){  apr_size_t copy_len, remaining = *len, tlen;  char *sbuf, *tbuf, *cur = buf;  struct rep_state *rs;  svn_txdelta_window_t *cwindow, *lwindow;  /* Special case for when there are no delta reps, only a plain     text. */  if (rb->rs_list->nelts == 0)    {      copy_len = remaining;      rs = rb->src_state;      if (((apr_off_t) copy_len) > rs->end - rs->off)        copy_len = (apr_size_t) (rs->end - rs->off);      SVN_ERR(svn_io_file_read_full(rs->file, cur, copy_len, NULL,                                    rb->pool));      rs->off += copy_len;      *len = copy_len;      return SVN_NO_ERROR;    }  while (remaining > 0)    {      /* If we have buffered data from a previous chunk, use that. */      if (rb->buf)        {          /* Determine how much to copy from the buffer. */          copy_len = rb->buf_len - rb->buf_pos;          if (copy_len > remaining)            copy_len = remaining;          /* Actually copy the data. */          memcpy(cur, rb->buf + rb->buf_pos, copy_len);          rb->buf_pos += copy_len;          cur += copy_len;          remaining -= copy_len;          /* If the buffer is all used up, clear it and empty the             local pool. */          if (rb->buf_pos == rb->buf_len)            {              svn_pool_clear(rb->pool);              rb->buf = NULL;            }        }      else        {                    rs = APR_ARRAY_IDX(rb->rs_list, 0, struct rep_state *);          if (rs->off == rs->end)            break;                    /* Get more buffered data by evaluating a chunk. */          if (rb->rs_list->nelts > 1)            SVN_ERR(get_combined_window(&cwindow, rb));          else            cwindow = NULL;          if (!cwindow || cwindow->src_ops > 0)            {              rs = APR_ARRAY_IDX(rb->rs_list, rb->rs_list->nelts - 1,                                 struct rep_state *);              /* Read window from last representation in list. */              /* We apply this window directly instead of combining it with the                 others.  We do this because vdelta is used for deltas against                 the empty stream, which will trigger quadratic behaviour in                 the delta combiner. */              SVN_ERR(read_window(&lwindow, rb->chunk_index, rs, rb->pool));              if (lwindow->src_ops > 0)                {                  if (! rb->src_state)                    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                                            _("svndiff data requested "                                              "non-existent source"));                  rs = rb->src_state;                  sbuf = apr_palloc(rb->pool, lwindow->sview_len);                  if (! ((rs->start + lwindow->sview_offset) < rs->end))                    return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                                            _("svndiff requested position "                                              "beyond end of stream"));                  if ((rs->start + lwindow->sview_offset) != rs->off)                    {                      rs->off = rs->start + lwindow->sview_offset;                      SVN_ERR(svn_io_file_seek(rs->file, APR_SET, &rs->off,                                               rb->pool));                    }                  SVN_ERR(svn_io_file_read_full(rs->file, sbuf,                                                lwindow->sview_len,                                                NULL, rb->pool));                  rs->off += lwindow->sview_len;                }              else                sbuf = NULL;              /* Apply lwindow to source. */              tlen = lwindow->tview_len;              tbuf = apr_palloc(rb->pool, tlen);              svn_txdelta_apply_instructions(lwindow, sbuf, tbuf,                                             &tlen);              if (tlen != lwindow->tview_len)                return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                                        _("svndiff window length is "                                          "corrupt"));              sbuf = tbuf;            }          else            sbuf = NULL;          rb->chunk_index++;          if (cwindow)            {              rb->buf_len = cwindow->tview_len;              rb->buf = apr_palloc(rb->pool, rb->buf_len);              svn_txdelta_apply_instructions(cwindow, sbuf, rb->buf,                                             &rb->buf_len);              if (rb->buf_len != cwindow->tview_len)                return svn_error_create(SVN_ERR_FS_CORRUPT, NULL,                                        _("svndiff window length is "                                          "corrupt"));            }          else            {              rb->buf_len = lwindow->tview_len;              rb->buf = sbuf;            }                    rb->buf_pos = 0;        }    }  *len = cur - buf;  return SVN_NO_ERROR;}/* BATON is of type `rep_read_baton'; read the next *LEN bytes of the   representation and store them in *BUF.  Sum as we read and verify   the MD5 sum at the end. */static svn_error_t *rep_read_contents(void *baton,                  char *buf,                  apr_size_t *len){  struct rep_read_baton *rb = baton;  /* Get the next block of data. */  SVN_ERR(get_contents(rb, buf, len));  /* Perform checksumming.  We want to check the checksum as soon as     the last byte of data is read, in case the caller never performs     a short read, but we don't want to finalize the MD5 context     twice. */  if (!rb->checksum_finalized)    {      apr_md5_update(&rb->md5_context, buf, *len);      rb->off += *len;      if (rb->off == rb->len)        {          unsigned char checksum[APR_MD5_DIGESTSIZE];          rb->checksum_finalized = TRUE;          apr_md5_final(checksum, &rb->md5_context);          if (! svn_md5_digests_match(checksum, rb->checksum))            return svn_error_createf              (SVN_ERR_FS_CORRUPT, NULL,               _("Checksum mismatch while reading representation:\n"                 "   expected:  %s\n"                 "     actual:  %s\n"),               svn_md5_digest_to_cstring_display(rb->checksum, rb->pool),               svn_md5_digest_to_cstring_display(checksum, rb->pool));        }    }  return SVN_NO_ERROR;}/* Return a stream in *CONTENTS_P that will read the contents of a   representation stored at the location given by REP.  Appropriate   for any kind of immutable representation, but only for file   contents (not props or directory contents) in mutable   representations.   If REP is NULL, the representation is assumed to be empty, and the   empty stream is returned.*/static svn_error_t *read_representation(svn_stream_t **contents_p,                    svn_fs_t *fs,                    representation_t *rep,                    apr_pool_t *pool){  struct rep_read_baton *rb;  if (! rep)    {      *contents_p = svn_stream_empty(pool);    }  else    {      SVN_ERR(rep_read_get_baton(&rb, fs, rep, pool));      *contents_p = svn_stream_create(rb, pool);      svn_stream_set_read(*contents_p, rep_read_contents);      svn_stream_set_close(*contents_p, rep_read_contents_close);    }    return SVN_NO_ERROR;}svn_error_t *svn_fs_fs__get_contents(svn_stream_t **contents_p,                        svn_fs_t *fs,                        node_revision_t *noderev,                        apr_pool_t *pool){  return read_representation(contents_p, fs, noderev->data_rep, pool);}/* Baton used when reading delta windows. */struct delta_read_baton{  struct rep_state *rs;  unsigned char checksum[APR_MD5_DIGESTSIZE];};/* This implements the svn_txdelta_next_window_fn_t interface. */static svn_error_t *delta_read_next_window(svn_txdelta_window_t **window, void *baton,                       apr_pool_t *pool){  struct delta_read_baton *drb = baton;  if (drb->rs->off == drb->rs->end)    {      *window = NULL;      return SVN_NO_ERROR;    }  SVN_ERR(read_window(window, drb->rs->chunk_index, drb->rs, pool));  return SVN_NO_ERROR;}/* This implements the svn_txdelta_md5_digest_fn_t interface. */static const unsigned char *delta_read_md5_digest(void *baton){  struct delta_read_baton *drb = baton;  return drb->checksum;}svn_er

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -