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

📄 svndiff.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
      if (p == NULL)        return NULL;    }  if (op->action_code != svn_txdelta_new)    {      p = decode_size(&op->offset, p, end);      if (p == NULL)        return NULL;    }  return p;}/* Count the instructions in the range [P..END-1] and make sure they   are valid for the given window lengths.  Return an error if the   instructions are invalid; otherwise set *NINST to the number of   instructions.  */static svn_error_t *count_and_verify_instructions(int *ninst,                              const unsigned char *p,                              const unsigned char *end,                              apr_size_t sview_len,                              apr_size_t tview_len,                              apr_size_t new_len){  int n = 0;  svn_txdelta_op_t op;  apr_size_t tpos = 0, npos = 0;  while (p < end)    {      p = decode_instruction(&op, p, end);      if (p == NULL || op.length <= 0 || op.length > tview_len - tpos)        {          if (p == NULL)            return svn_error_createf              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,               _("Invalid diff stream: insn %d cannot be decoded"), n);          else if (op.length <= 0)            return svn_error_createf              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,               _("Invalid diff stream: insn %d has non-positive length"), n);          else            return svn_error_createf              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,               _("Invalid diff stream: insn %d overflows the target view"), n);        }      switch (op.action_code)        {        case svn_txdelta_source:          if (op.length > sview_len - op.offset)            return svn_error_createf              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,               _("Invalid diff stream: "                 "[src] insn %d overflows the source view"), n);          break;        case svn_txdelta_target:          if (op.offset >= tpos)            return svn_error_createf              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,               _("Invalid diff stream: "                 "[tgt] insn %d starts beyond the target view position"), n);          break;        case svn_txdelta_new:          if (op.length > new_len - npos)            return svn_error_createf              (SVN_ERR_SVNDIFF_INVALID_OPS, NULL,               _("Invalid diff stream: "                 "[new] insn %d overflows the new data section"), n);          npos += op.length;          break;        }      tpos += op.length;      n++;    }  if (tpos != tview_len)    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,                            _("Delta does not fill the target window"));  if (npos != new_len)    return svn_error_create(SVN_ERR_SVNDIFF_INVALID_OPS, NULL,                            _("Delta does not contain enough new data"));  *ninst = n;  return SVN_NO_ERROR;}/* Given the five integer fields of a window header and a pointer to   the remainder of the window contents, fill in a delta window   structure *WINDOW.  New allocations will be performed in POOL;   the new_data field of *WINDOW will refer directly to memory pointed   to by DATA. */static svn_error_t *decode_window(svn_txdelta_window_t *window, svn_filesize_t sview_offset,              apr_size_t sview_len, apr_size_t tview_len, apr_size_t inslen,              apr_size_t newlen, const unsigned char *data, apr_pool_t *pool,              unsigned int version){  const unsigned char *insend;  int ninst;  apr_size_t npos;  svn_txdelta_op_t *ops, *op;  svn_string_t *new_data = apr_palloc(pool, sizeof(*new_data));  window->sview_offset = sview_offset;  window->sview_len = sview_len;  window->tview_len = tview_len;  insend = data + inslen;    if (version == 1)    {      svn_stringbuf_t *instin, *ndin;      svn_stringbuf_t *instout, *ndout;      instin = svn_stringbuf_ncreate((const char *)data, insend - data, pool);      instout = svn_stringbuf_create("", pool);      SVN_ERR(zlib_decode(instin, instout));            ndin = svn_stringbuf_ncreate((const char *)insend, newlen, pool);      ndout = svn_stringbuf_create("", pool);      SVN_ERR(zlib_decode(ndin, ndout));            newlen = ndout->len;      data = (unsigned char *)instout->data;      insend = (unsigned char *)instout->data + instout->len;      new_data->data = (const char *) ndout->data;      new_data->len = newlen;    }  else    {      new_data->data = (const char *) insend;      new_data->len = newlen;    }  /* Count the instructions and make sure they are all valid.  */   SVN_ERR(count_and_verify_instructions(&ninst, data, insend,                                         sview_len, tview_len, newlen));   /* Allocate a buffer for the instructions and decode them. */  ops = apr_palloc(pool, ninst * sizeof(*ops));  npos = 0;    window->src_ops = 0;  for (op = ops; op < ops + ninst; op++)    {      data = decode_instruction(op, data, insend);      if (op->action_code == svn_txdelta_source)        ++window->src_ops;      else if (op->action_code == svn_txdelta_new)        {          op->offset = npos;          npos += op->length;        }    }  assert(data == insend);  window->ops = ops;  window->num_ops = ninst;  window->new_data = new_data;  return SVN_NO_ERROR;}static svn_error_t *write_handler(void *baton,              const char *buffer,              apr_size_t *len){  struct decode_baton *db = (struct decode_baton *) baton;  const unsigned char *p, *end;  svn_filesize_t sview_offset;  apr_size_t sview_len, tview_len, inslen, newlen, remaining;  apr_size_t buflen = *len;  /* Chew up four bytes at the beginning for the header.  */  if (db->header_bytes < 4)    {      apr_size_t nheader = 4 - db->header_bytes;      if (nheader > buflen)        nheader = buflen;      if (memcmp(buffer, "SVN\0" + db->header_bytes, nheader) == 0)        db->version = 0;      else if (memcmp(buffer, "SVN\1" + db->header_bytes, nheader) == 0)        db->version = 1;      else        return svn_error_create(SVN_ERR_SVNDIFF_INVALID_HEADER, NULL,                                _("Svndiff has invalid header"));      buflen -= nheader;      buffer += nheader;      db->header_bytes += nheader;    }  /* Concatenate the old with the new.  */  svn_stringbuf_appendbytes(db->buffer, buffer, buflen);  /* We have a buffer of svndiff data that might be good for:     a) an integral number of windows' worth of data - this is a        trivial case.  Make windows from our data and ship them off.     b) a non-integral number of windows' worth of data - we shall        consume the integral portion of the window data, and then        somewhere in the following loop the decoding of the svndiff        data will run out of stuff to decode, and will simply return        SVN_NO_ERROR, anxiously awaiting more data.  */  while (1)    {      apr_pool_t *newpool;      svn_txdelta_window_t window;      /* Read the header, if we have enough bytes for that.  */      p = (const unsigned char *) db->buffer->data;      end = (const unsigned char *) db->buffer->data + db->buffer->len;      p = decode_file_offset(&sview_offset, p, end);      if (p == NULL)        return SVN_NO_ERROR;      p = decode_size(&sview_len, p, end);      if (p == NULL)        return SVN_NO_ERROR;      p = decode_size(&tview_len, p, end);      if (p == NULL)        return SVN_NO_ERROR;      p = decode_size(&inslen, p, end);      if (p == NULL)        return SVN_NO_ERROR;      p = decode_size(&newlen, p, end);      if (p == NULL)        return SVN_NO_ERROR;      /* Check for integer overflow.  */      if (sview_offset < 0 || inslen + newlen < inslen          || sview_len + tview_len < sview_len          || sview_offset + sview_len < sview_offset)        return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,                                 _("Svndiff contains corrupt window header"));      /* Check for source windows which slide backwards.  */      if (sview_len > 0          && (sview_offset < db->last_sview_offset              || (sview_offset + sview_len                  < db->last_sview_offset + db->last_sview_len)))        return svn_error_create          (SVN_ERR_SVNDIFF_BACKWARD_VIEW, NULL,            _("Svndiff has backwards-sliding source views"));      /* Wait for more data if we don't have enough bytes for the         whole window.  */      if ((apr_size_t) (end - p) < inslen + newlen)        return SVN_NO_ERROR;      /* Decode the window and send it off. */      SVN_ERR(decode_window(&window, sview_offset, sview_len, tview_len,                            inslen, newlen, p, db->subpool,                            db->version));      SVN_ERR(db->consumer_func(&window, db->consumer_baton));      /* Make a new subpool and buffer, saving aside the remaining         data in the old buffer.  */      newpool = svn_pool_create(db->pool);      p += inslen + newlen;      remaining = db->buffer->data + db->buffer->len - (const char *) p;      db->buffer =         svn_stringbuf_ncreate((const char *) p, remaining, newpool);      /* Remember the offset and length of the source view for next time.  */      db->last_sview_offset = sview_offset;      db->last_sview_len = sview_len;      /* We've copied stuff out of the old pool. Toss that pool and use         our new pool.         ### might be nice to avoid the copy and just use svn_pool_clear         ### to get rid of whatever the "other stuff" is. future project...      */      svn_pool_destroy(db->subpool);      db->subpool = newpool;    }  /* NOTREACHED */}static svn_error_t *close_handler(void *baton){  struct decode_baton *db = (struct decode_baton *) baton;  svn_error_t *err;  /* Make sure that we're at a plausible end of stream, returning an     error if we are expected to do so.  */  if ((db->error_on_early_close)      && (db->header_bytes < 4 || db->buffer->len != 0))    return svn_error_create(SVN_ERR_SVNDIFF_UNEXPECTED_END, NULL,                            _("Unexpected end of svndiff input"));  /* Tell the window consumer that we're done, and clean up.  */  err = db->consumer_func(NULL, db->consumer_baton);  svn_pool_destroy(db->pool);  return err;}svn_stream_t *svn_txdelta_parse_svndiff(svn_txdelta_window_handler_t handler,                          void *handler_baton,                          svn_boolean_t error_on_early_close,                          apr_pool_t *pool){  apr_pool_t *subpool = svn_pool_create(pool);  struct decode_baton *db = apr_palloc(pool, sizeof(*db));  svn_stream_t *stream;  db->consumer_func = handler;  db->consumer_baton = handler_baton;  db->pool = subpool;  db->subpool = svn_pool_create(subpool);  db->buffer = svn_stringbuf_create("", db->subpool);  db->last_sview_offset = 0;  db->last_sview_len = 0;  db->header_bytes = 0;  db->error_on_early_close = error_on_early_close;  stream = svn_stream_create(db, pool);  svn_stream_set_write(stream, write_handler);  svn_stream_set_close(stream, close_handler);  return stream;}/* Routines for reading one svndiff window at a time. *//* Read one byte from STREAM into *BYTE. */static svn_error_t *read_one_byte(unsigned char *byte, svn_stream_t *stream){  char c;  apr_size_t len = 1;  SVN_ERR(svn_stream_read(stream, &c, &len));  if (len == 0)    return svn_error_create(SVN_ERR_SVNDIFF_UNEXPECTED_END, NULL,                            _("Unexpected end of svndiff input"));  *byte = (unsigned char) c;  return SVN_NO_ERROR;}/* Read and decode one integer from STREAM into *SIZE. */static svn_error_t *read_one_size(apr_size_t *size, svn_stream_t *stream){  unsigned char c;  *size = 0;  while (1)    {      SVN_ERR(read_one_byte(&c, stream));      *size = (*size << 7) | (c & 0x7f);      if (!(c & 0x80))        break;    }  return SVN_NO_ERROR;}/* Read a window header from STREAM and check it for integer overflow. */static svn_error_t *read_window_header(svn_stream_t *stream, svn_filesize_t *sview_offset,                   apr_size_t *sview_len, apr_size_t *tview_len,                   apr_size_t *inslen, apr_size_t *newlen){  unsigned char c;  /* Read the source view offset by hand, since it's not an apr_size_t. */  *sview_offset = 0;  while (1)    {      SVN_ERR(read_one_byte(&c, stream));      *sview_offset = (*sview_offset << 7) | (c & 0x7f);      if (!(c & 0x80))        break;    }  /* Read the four size fields. */  SVN_ERR(read_one_size(sview_len, stream));  SVN_ERR(read_one_size(tview_len, stream));  SVN_ERR(read_one_size(inslen, stream));  SVN_ERR(read_one_size(newlen, stream));  /* Check for integer overflow.  */  if (*sview_offset < 0 || *inslen + *newlen < *inslen      || *sview_len + *tview_len < *sview_len      || *sview_offset + *sview_len < *sview_offset)    return svn_error_create(SVN_ERR_SVNDIFF_CORRUPT_WINDOW, NULL,                             _("Svndiff contains corrupt window header"));  return SVN_NO_ERROR;}svn_error_t *svn_txdelta_read_svndiff_window(svn_txdelta_window_t **window,                                svn_stream_t *stream,                                int svndiff_version,                                apr_pool_t *pool){  svn_filesize_t sview_offset;  apr_size_t sview_len, tview_len, inslen, newlen, len;  unsigned char *buf;  SVN_ERR(read_window_header(stream, &sview_offset, &sview_len, &tview_len,                             &inslen, &newlen));  len = inslen + newlen;  buf = apr_palloc(pool, len);  SVN_ERR(svn_stream_read(stream, (char*)buf, &len));  if (len < inslen + newlen)    return svn_error_create(SVN_ERR_SVNDIFF_UNEXPECTED_END, NULL,                            _("Unexpected end of svndiff input"));  *window = apr_palloc(pool, sizeof(**window));  SVN_ERR(decode_window(*window, sview_offset, sview_len, tview_len, inslen,                        newlen, buf, pool, svndiff_version));  return SVN_NO_ERROR;}svn_error_t *svn_txdelta_skip_svndiff_window(apr_file_t *file,                                int svndiff_version,                                apr_pool_t *pool){  svn_stream_t *stream = svn_stream_from_aprfile(file, pool);  svn_filesize_t sview_offset;  apr_size_t sview_len, tview_len, inslen, newlen;  apr_off_t offset;  SVN_ERR(read_window_header(stream, &sview_offset, &sview_len, &tview_len,                             &inslen, &newlen));  offset = inslen + newlen;  return svn_io_file_seek(file, APR_CUR, &offset, pool);}

⌨️ 快捷键说明

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