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

📄 marshal.c

📁 subversion-1.4.3-1.tar.gz 配置svn的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * marshal.c :  Marshalling routines for Subversion protocol * * ==================================================================== * Copyright (c) 2000-2004 CollabNet.  All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution.  The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals.  For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */#include <assert.h>#include <stdlib.h>#define APR_WANT_STRFUNC#include <apr_want.h>#include <apr_general.h>#include <apr_lib.h>#include <apr_strings.h>#include <apr_network_io.h>#include <apr_poll.h>#include "svn_types.h"#include "svn_string.h"#include "svn_error.h"#include "svn_pools.h"#include "svn_ra_svn.h"#include "svn_private_config.h"#include "ra_svn.h"#define svn_iswhitespace(c) ((c) == ' ' || (c) == '\n')/* --- CONNECTION INITIALIZATION --- */svn_ra_svn_conn_t *svn_ra_svn_create_conn(apr_socket_t *sock,                                          apr_file_t *in_file,                                          apr_file_t *out_file,                                          apr_pool_t *pool){  svn_ra_svn_conn_t *conn = apr_palloc(pool, sizeof(*conn));  assert((sock && !in_file && !out_file) || (!sock && in_file && out_file));  conn->sock = sock;  conn->in_file = in_file;  conn->out_file = out_file;  conn->read_ptr = conn->read_buf;  conn->read_end = conn->read_buf;  conn->write_pos = 0;  conn->block_handler = NULL;  conn->block_baton = NULL;  conn->capabilities = apr_hash_make(pool);  conn->pool = pool;  return conn;}svn_error_t *svn_ra_svn_set_capabilities(svn_ra_svn_conn_t *conn,                                         apr_array_header_t *list){  int i;  svn_ra_svn_item_t *item;  const char *word;  for (i = 0; i < list->nelts; i++)    {      item = &APR_ARRAY_IDX(list, i, svn_ra_svn_item_t);      if (item->kind != SVN_RA_SVN_WORD)        return svn_error_create(SVN_ERR_RA_SVN_MALFORMED_DATA, NULL,                                _("Capability entry is not a word"));      word = apr_pstrdup(conn->pool, item->u.word);      apr_hash_set(conn->capabilities, word, APR_HASH_KEY_STRING, word);    }  return SVN_NO_ERROR;}svn_boolean_t svn_ra_svn_has_capability(svn_ra_svn_conn_t *conn,                                        const char *capability){  return (apr_hash_get(conn->capabilities, capability,                       APR_HASH_KEY_STRING) != NULL);}voidsvn_ra_svn__set_block_handler(svn_ra_svn_conn_t *conn,                              ra_svn_block_handler_t handler,                              void *baton){  apr_interval_time_t interval = (handler) ? 0 : -1;  conn->block_handler = handler;  conn->block_baton = baton;  if (conn->sock)    apr_socket_timeout_set(conn->sock, interval);  else    apr_file_pipe_timeout_set(conn->out_file, interval);}svn_boolean_t svn_ra_svn__input_waiting(svn_ra_svn_conn_t *conn,                                        apr_pool_t *pool){  apr_pollfd_t pfd;  int n;  if (conn->sock)    {      pfd.desc_type = APR_POLL_SOCKET;      pfd.desc.s = conn->sock;    }  else    {      pfd.desc_type = APR_POLL_FILE;      pfd.desc.f = conn->in_file;    }  pfd.p = pool;  pfd.reqevents = APR_POLLIN;#ifndef AS400  return ((apr_poll(&pfd, 1, &n, 0) == APR_SUCCESS) && n);#else  /* OS400 requires a pool argument for apr_poll(). */  return ((apr_poll(&pfd, 1, &n, 0, pool) == APR_SUCCESS) && n);#endif}/* --- WRITE BUFFER MANAGEMENT --- *//* Write bytes into the write buffer until either the write buffer is * full or we reach END. */static const char *writebuf_push(svn_ra_svn_conn_t *conn, const char *data,                                 const char *end){  apr_ssize_t buflen, copylen;  buflen = sizeof(conn->write_buf) - conn->write_pos;  copylen = (buflen < end - data) ? buflen : end - data;  memcpy(conn->write_buf + conn->write_pos, data, copylen);  conn->write_pos += copylen;  return data + copylen;}/* Write data to socket or output file as appropriate. */static svn_error_t *writebuf_output(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                    const char *data, apr_size_t len){  const char *end = data + len;  apr_status_t status;  apr_size_t count;  apr_pool_t *subpool = NULL;  while (data < end)    {      count = end - data;      if (conn->sock)        status = apr_socket_send(conn->sock, data, &count);      else        status = apr_file_write(conn->out_file, data, &count);      if (status)        return svn_error_wrap_apr(status, _("Can't write to connection"));      if (count == 0)        {          if (!subpool)            subpool = svn_pool_create(pool);          else            apr_pool_clear(subpool);          SVN_ERR(conn->block_handler(conn, subpool, conn->block_baton));        }      data += count;    }  if (subpool)    apr_pool_destroy(subpool);  return SVN_NO_ERROR;}/* Write data from the write buffer out to the socket. */static svn_error_t *writebuf_flush(svn_ra_svn_conn_t *conn, apr_pool_t *pool){  int write_pos = conn->write_pos;  /* Clear conn->write_pos first in case the block handler does a read. */  conn->write_pos = 0;  SVN_ERR(writebuf_output(conn, pool, conn->write_buf, write_pos));  return SVN_NO_ERROR;}static svn_error_t *writebuf_write(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                   const char *data, apr_size_t len){  const char *end = data + len;  if (conn->write_pos > 0 && conn->write_pos + len > sizeof(conn->write_buf))    {      /* Fill and then empty the write buffer. */      data = writebuf_push(conn, data, end);      SVN_ERR(writebuf_flush(conn, pool));    }  if (end - data > (apr_ssize_t)sizeof(conn->write_buf))    SVN_ERR(writebuf_output(conn, pool, data, end - data));  else    writebuf_push(conn, data, end);  return SVN_NO_ERROR;}static svn_error_t *writebuf_printf(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                    const char *fmt, ...)  __attribute__ ((format(printf, 3, 4)));static svn_error_t *writebuf_printf(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                    const char *fmt, ...){  va_list ap;  char *str;  va_start(ap, fmt);  str = apr_pvsprintf(pool, fmt, ap);  va_end(ap);  return writebuf_write(conn, pool, str, strlen(str));}/* --- READ BUFFER MANAGEMENT --- *//* Read bytes into DATA until either the read buffer is empty or * we reach END. */static char *readbuf_drain(svn_ra_svn_conn_t *conn, char *data, char *end){  apr_ssize_t buflen, copylen;  buflen = conn->read_end - conn->read_ptr;  copylen = (buflen < end - data) ? buflen : end - data;  memcpy(data, conn->read_ptr, copylen);  conn->read_ptr += copylen;  return data + copylen;}/* Read data from socket or input file as appropriate. */static svn_error_t *readbuf_input(svn_ra_svn_conn_t *conn, char *data,                                  apr_size_t *len){  apr_status_t status;  /* Always block for reading. */  if (conn->sock && conn->block_handler)    apr_socket_timeout_set(conn->sock, -1);  if (conn->sock)    status = apr_socket_recv(conn->sock, data, len);  else    status = apr_file_read(conn->in_file, data, len);  if (conn->sock && conn->block_handler)    apr_socket_timeout_set(conn->sock, 0);  if (status && !APR_STATUS_IS_EOF(status))    return svn_error_wrap_apr(status, _("Can't read from connection"));  if (*len == 0)    return svn_error_create(SVN_ERR_RA_SVN_CONNECTION_CLOSED, NULL,                            _("Connection closed unexpectedly"));  return SVN_NO_ERROR;}/* Read data from the socket into the read buffer, which must be empty. */static svn_error_t *readbuf_fill(svn_ra_svn_conn_t *conn, apr_pool_t *pool){  apr_size_t len;  assert(conn->read_ptr == conn->read_end);  SVN_ERR(writebuf_flush(conn, pool));  len = sizeof(conn->read_buf);  SVN_ERR(readbuf_input(conn, conn->read_buf, &len));  conn->read_ptr = conn->read_buf;  conn->read_end = conn->read_buf + len;  return SVN_NO_ERROR;}static svn_error_t *readbuf_getchar(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                    char *result){  if (conn->read_ptr == conn->read_end)    SVN_ERR(readbuf_fill(conn, pool));  *result = *conn->read_ptr++;  return SVN_NO_ERROR;}static svn_error_t *readbuf_getchar_skip_whitespace(svn_ra_svn_conn_t *conn,                                                    apr_pool_t *pool,                                                    char *result){  do    SVN_ERR(readbuf_getchar(conn, pool, result));  while (svn_iswhitespace(*result));  return SVN_NO_ERROR;}static svn_error_t *readbuf_read(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                 char *data, apr_size_t len){  char *end = data + len;  apr_size_t count;  /* Copy in an appropriate amount of data from the buffer. */  data = readbuf_drain(conn, data, end);  /* Read large chunks directly into buffer. */  while (end - data > (apr_ssize_t)sizeof(conn->read_buf))    {      SVN_ERR(writebuf_flush(conn, pool));      count = end - data;      SVN_ERR(readbuf_input(conn, data, &count));      data += count;    }  while (end > data)    {      /* The remaining amount to read is small; fill the buffer and       * copy from that. */      SVN_ERR(readbuf_fill(conn, pool));      data = readbuf_drain(conn, data, end);    }  return SVN_NO_ERROR;}static svn_error_t *readbuf_skip_leading_garbage(svn_ra_svn_conn_t *conn){  char buf[256];  /* Must be smaller than sizeof(conn->read_buf) - 1. */  const char *p, *end;  apr_size_t len;  svn_boolean_t lparen = FALSE;  assert(conn->read_ptr == conn->read_end);  while (1)    {      /* Read some data directly from the connection input source. */      len = sizeof(buf);      SVN_ERR(readbuf_input(conn, buf, &len));      end = buf + len;      /* Scan the data for '(' WS with a very simple state machine. */      for (p = buf; p < end; p++)        {          if (lparen && svn_iswhitespace(*p))            break;          else            lparen = (*p == '(');        }      if (p < end)        break;    }  /* p now points to the whitespace just after the left paren.  Fake   * up the left paren and then copy what we have into the read   * buffer. */  conn->read_buf[0] = '(';  memcpy(conn->read_buf + 1, p, end - p);  conn->read_ptr = conn->read_buf;  conn->read_end = conn->read_buf + 1 + (end - p);  return SVN_NO_ERROR;}/* --- WRITING DATA ITEMS --- */ svn_error_t *svn_ra_svn_write_number(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                     apr_uint64_t number){  return writebuf_printf(conn, pool, "%" APR_UINT64_T_FMT " ", number);}svn_error_t *svn_ra_svn_write_string(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                     const svn_string_t *str){  SVN_ERR(writebuf_printf(conn, pool, "%" APR_SIZE_T_FMT ":", str->len));  SVN_ERR(writebuf_write(conn, pool, str->data, str->len));  SVN_ERR(writebuf_write(conn, pool, " ", 1));  return SVN_NO_ERROR;}svn_error_t *svn_ra_svn_write_cstring(svn_ra_svn_conn_t *conn,                                      apr_pool_t *pool, const char *s){  return writebuf_printf(conn, pool, "%" APR_SIZE_T_FMT ":%s ", strlen(s), s);}svn_error_t *svn_ra_svn_write_word(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                   const char *word){  return writebuf_printf(conn, pool, "%s ", word);}svn_error_t *svn_ra_svn_start_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool){  return writebuf_write(conn, pool, "( ", 2);}svn_error_t *svn_ra_svn_end_list(svn_ra_svn_conn_t *conn, apr_pool_t *pool){  return writebuf_write(conn, pool, ") ", 2);}svn_error_t *svn_ra_svn_flush(svn_ra_svn_conn_t *conn, apr_pool_t *pool){  return writebuf_flush(conn, pool);}/* --- WRITING TUPLES --- */static svn_error_t *vwrite_tuple(svn_ra_svn_conn_t *conn, apr_pool_t *pool,                                 const char *fmt, va_list ap){  svn_boolean_t opt = FALSE;  svn_revnum_t rev;  const char *cstr;  const svn_string_t *str;  if (*fmt == '!')    fmt++;  else    SVN_ERR(svn_ra_svn_start_list(conn, pool));  for (; *fmt; fmt++)    {      if (*fmt == 'n' && !opt)        SVN_ERR(svn_ra_svn_write_number(conn, pool, va_arg(ap, apr_uint64_t)));      else if (*fmt == 'r')        {          rev = va_arg(ap, svn_revnum_t);          assert(opt || SVN_IS_VALID_REVNUM(rev));          if (SVN_IS_VALID_REVNUM(rev))            SVN_ERR(svn_ra_svn_write_number(conn, pool, rev));        }      else if (*fmt == 's')        {          str = va_arg(ap, const svn_string_t *);          assert(opt || str);          if (str)            SVN_ERR(svn_ra_svn_write_string(conn, pool, str));        }      else if (*fmt == 'c')        {          cstr = va_arg(ap, const char *);          assert(opt || cstr);          if (cstr)            SVN_ERR(svn_ra_svn_write_cstring(conn, pool, cstr));        }      else if (*fmt == 'w')        {          cstr = va_arg(ap, const char *);          assert(opt || cstr);          if (cstr)            SVN_ERR(svn_ra_svn_write_word(conn, pool, cstr));        }      else if (*fmt == 'b' && !opt)        {          cstr = va_arg(ap, svn_boolean_t) ? "true" : "false";          SVN_ERR(svn_ra_svn_write_word(conn, pool, cstr));        }

⌨️ 快捷键说明

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