Exemplo n.º 1
0
svn_error_t *
svn_wc_create_tmp_file2(apr_file_t **fp,
                        const char **new_name,
                        const char *path,
                        svn_io_file_del_t delete_when,
                        apr_pool_t *pool)
{
  svn_wc__db_t *db;
  const char *local_abspath;
  const char *temp_dir;
  svn_error_t *err;

  SVN_ERR_ASSERT(fp || new_name);

  SVN_ERR(svn_wc__db_open(&db,
                          NULL /* config */,
                          TRUE /* auto_upgrade */,
                          TRUE /* enforce_empty_wq */,
                          pool, pool));

  SVN_ERR(svn_dirent_get_absolute(&local_abspath, path, pool));
  err = svn_wc__db_temp_wcroot_tempdir(&temp_dir, db, local_abspath,
                                       pool, pool);
  err = svn_error_compose_create(err, svn_wc__db_close(db));
  if (err)
    return svn_error_trace(err);

  SVN_ERR(svn_io_open_unique_file3(fp, new_name, temp_dir,
                                   delete_when, pool, pool));

  return SVN_NO_ERROR;
}
Exemplo n.º 2
0
/* Compute the delta between OLDROOT/OLDPATH and NEWROOT/NEWPATH and
   store it into a new temporary file *TEMPFILE.  OLDROOT may be NULL,
   in which case the delta will be computed against an empty file, as
   per the svn_fs_get_file_delta_stream docstring.  Record the length
   of the temporary file in *LEN, and rewind the file before
   returning. */
static svn_error_t *
store_delta(apr_file_t **tempfile, svn_filesize_t *len,
            svn_fs_root_t *oldroot, const char *oldpath,
            svn_fs_root_t *newroot, const char *newpath, apr_pool_t *pool)
{
  svn_stream_t *temp_stream;
  apr_off_t offset = 0;
  svn_txdelta_stream_t *delta_stream;
  svn_txdelta_window_handler_t wh;
  void *whb;

  /* Create a temporary file and open a stream to it. Note that we need
     the file handle in order to rewind it. */
  SVN_ERR(svn_io_open_unique_file3(tempfile, NULL, NULL,
                                   svn_io_file_del_on_pool_cleanup,
                                   pool, pool));
  temp_stream = svn_stream_from_aprfile2(*tempfile, TRUE, pool);

  /* Compute the delta and send it to the temporary file. */
  SVN_ERR(svn_fs_get_file_delta_stream(&delta_stream, oldroot, oldpath,
                                       newroot, newpath, pool));
  svn_txdelta_to_svndiff2(&wh, &whb, temp_stream, 0, pool);
  SVN_ERR(svn_txdelta_send_txstream(delta_stream, wh, whb, pool));

  /* Get the length of the temporary file and rewind it. */
  SVN_ERR(svn_io_file_seek(*tempfile, APR_CUR, &offset, pool));
  *len = offset;
  offset = 0;
  return svn_io_file_seek(*tempfile, APR_SET, &offset, pool);
}
Exemplo n.º 3
0
static svn_error_t *
open_tmp_file(apr_file_t **fp,
              void *callback_baton,
              apr_pool_t *pool)
{
  /* Open a unique file;  use APR_DELONCLOSE. */
  return svn_io_open_unique_file3(fp, NULL, NULL, svn_io_file_del_on_close,
                                  pool, pool);
}
Exemplo n.º 4
0
static svn_error_t *
open_tmp_file(apr_file_t **fp,
              void *callback_baton,
              apr_pool_t *pool)
{
  return svn_error_trace(svn_io_open_unique_file3(fp, NULL, NULL,
                                  svn_io_file_del_on_pool_cleanup,
                                  pool, pool));
}
Exemplo n.º 5
0
/* Create a temporary file F that will automatically be deleted when the
   pool is cleaned up.  Fill it with VALUE, and leave it open and rewound,
   ready to be read from. */
static svn_error_t *
create_temp_file(apr_file_t **f, const svn_string_t *value, apr_pool_t *pool)
{
  apr_off_t offset = 0;

  SVN_ERR(svn_io_open_unique_file3(f, NULL, NULL,
                                   svn_io_file_del_on_pool_cleanup,
                                   pool, pool));
  SVN_ERR(svn_io_file_write_full(*f, value->data, value->len, NULL, pool));
  return svn_io_file_seek(*f, APR_SET, &offset, pool);
}
Exemplo n.º 6
0
svn_error_t *
svn_stream_open_unique(svn_stream_t **stream,
                       const char **temp_path,
                       const char *dirpath,
                       svn_io_file_del_t delete_when,
                       apr_pool_t *result_pool,
                       apr_pool_t *scratch_pool)
{
  apr_file_t *file;

  SVN_ERR(svn_io_open_unique_file3(&file, temp_path, dirpath,
                                   delete_when, result_pool, scratch_pool));
  *stream = svn_stream_from_aprfile2(file, FALSE, result_pool);

  return SVN_NO_ERROR;
}
Exemplo n.º 7
0
/* Get the empty file associated with the edit baton. This is cached so
 * that it can be reused, all empty files are the same.
 */
static svn_error_t *
get_empty_file(struct edit_baton *eb,
               const char **empty_file_path)
{
  /* Create the file if it does not exist */
  /* Note that we tried to use /dev/null in r857294, but
     that won't work on Windows: it's impossible to stat NUL */
  if (!eb->empty_file)
    SVN_ERR(svn_io_open_unique_file3(NULL, &(eb->empty_file), NULL,
                                     svn_io_file_del_on_pool_cleanup,
                                     eb->pool, eb->pool));

  *empty_file_path = eb->empty_file;

  return SVN_NO_ERROR;
}
Exemplo n.º 8
0
/* Produce a diff of depth DEPTH between two arbitrary directories at
 * LOCAL_ABSPATH1 and LOCAL_ABSPATH2, using the provided diff callbacks
 * to show file changes and, for versioned nodes, property changes.
 *
 * If ROOT_ABSPATH1 and ROOT_ABSPATH2 are not NULL, show paths in diffs
 * relative to these roots, rather than relative to LOCAL_ABSPATH1 and
 * LOCAL_ABSPATH2. This is needed when crawling a subtree that exists
 * only within LOCAL_ABSPATH2. */
static svn_error_t *
do_arbitrary_dirs_diff(const char *local_abspath1,
                       const char *local_abspath2,
                       const char *root_abspath1,
                       const char *root_abspath2,
                       svn_depth_t depth,
                       const svn_wc_diff_callbacks4_t *callbacks,
                       void *diff_baton,
                       svn_client_ctx_t *ctx,
                       apr_pool_t *scratch_pool)
{
  apr_file_t *empty_file;
  svn_node_kind_t kind1;

  struct arbitrary_diff_walker_baton b;

  /* If LOCAL_ABSPATH1 is not a directory, crawl LOCAL_ABSPATH2 instead
   * and compare it to LOCAL_ABSPATH1, showing only additions.
   * This case can only happen during recursion from arbitrary_diff_walker(),
   * because do_arbitrary_nodes_diff() prevents this from happening at
   * the root of the comparison. */
  SVN_ERR(svn_io_check_resolved_path(local_abspath1, &kind1, scratch_pool));
  b.recursing_within_added_subtree = (kind1 != svn_node_dir);

  b.root1_abspath = root_abspath1 ? root_abspath1 : local_abspath1;
  b.root2_abspath = root_abspath2 ? root_abspath2 : local_abspath2;
  b.recursing_within_adm_dir = FALSE;
  b.adm_dir_abspath = NULL;
  b.callbacks = callbacks;
  b.diff_baton = diff_baton;
  b.ctx = ctx;
  b.pool = scratch_pool;

  SVN_ERR(svn_io_open_unique_file3(&empty_file, &b.empty_file_abspath,
                                   NULL, svn_io_file_del_on_pool_cleanup,
                                   scratch_pool, scratch_pool));

  if (depth <= svn_depth_immediates)
    SVN_ERR(arbitrary_diff_this_dir(&b, local_abspath1, depth, scratch_pool));
  else if (depth == svn_depth_infinity)
    SVN_ERR(svn_io_dir_walk2(b.recursing_within_added_subtree ? local_abspath2
                                                              : local_abspath1,
                             0, arbitrary_diff_walker, &b, scratch_pool));
  return SVN_NO_ERROR;
}
Exemplo n.º 9
0
    void open_unique_file( const std::string &tmp_dir )
    {
#if defined( PYSVN_HAS_IO_OPEN_UNIQUE_FILE3 )
        svn_error_t *error = svn_io_open_unique_file3
            (
            &m_apr_file,
            &m_filename,
            tmp_dir.c_str(),
            svn_io_file_del_none,
            m_pool,
            m_pool
            );
#elif defined( PYSVN_HAS_IO_OPEN_UNIQUE_FILE2 )
        svn_error_t *error = svn_io_open_unique_file2
            (
            &m_apr_file,
            &m_filename,
            tmp_dir.c_str(),
            ".tmp",
            svn_io_file_del_none,
            m_pool
            );
#else
        svn_error_t *error = svn_io_open_unique_file
            (
            &m_apr_file,
            &m_filename,
            tmp_dir.c_str(),
            ".tmp",
            false,
            m_pool
            );
#endif
        if( error != NULL )
        {
            throw SvnException( error );
        }
    }
Exemplo n.º 10
0
static svn_error_t *
test_readonly(apr_pool_t *pool)
{
  const char *path;
  apr_finfo_t finfo;
  svn_boolean_t read_only;
  apr_int32_t wanted = APR_FINFO_SIZE | APR_FINFO_MTIME | APR_FINFO_TYPE
                        | APR_FINFO_LINK | APR_FINFO_PROT;


  SVN_ERR(svn_io_open_unique_file3(NULL, &path, NULL,
                                   svn_io_file_del_on_pool_cleanup,
                                   pool, pool));

  /* File should be writable */
  SVN_ERR(svn_io_stat(&finfo, path, wanted, pool));
  SVN_ERR(svn_io__is_finfo_read_only(&read_only, &finfo, pool));
  SVN_TEST_ASSERT(!read_only);

  /* Set read only */
  SVN_ERR(svn_io_set_file_read_only(path, FALSE, pool));

  /* File should be read only */
  SVN_ERR(svn_io_stat(&finfo, path, wanted, pool));
  SVN_ERR(svn_io__is_finfo_read_only(&read_only, &finfo, pool));
  SVN_TEST_ASSERT(read_only);

  /* Set writable */
  SVN_ERR(svn_io_set_file_read_write(path, FALSE, pool));

  /* File should be writable */
  SVN_ERR(svn_io_stat(&finfo, path, wanted, pool));
  SVN_ERR(svn_io__is_finfo_read_only(&read_only, &finfo, pool));
  SVN_TEST_ASSERT(!read_only);

  return SVN_NO_ERROR;
}
Exemplo n.º 11
0
svn_error_t *
svn_wc_create_tmp_file2(apr_file_t **fp,
                        const char **new_name,
                        const char *path,
                        svn_io_file_del_t delete_when,
                        apr_pool_t *pool)
{
  const char *temp_dir;
  apr_file_t *file;

  SVN_ERR_ASSERT(fp || new_name);

  temp_dir = svn_wc__adm_child(path, SVN_WC__ADM_TMP, pool);

  SVN_ERR(svn_io_open_unique_file3(&file, new_name, temp_dir,
                                   delete_when, pool, pool));

  if (fp)
    *fp = file;
  else
    SVN_ERR(svn_io_file_close(file, pool));

  return SVN_NO_ERROR;
}
Exemplo n.º 12
0
/* Create a PATCH_FILE containing the contents of DIFF. */
static svn_error_t *
create_patch_file(svn_patch_file_t **patch_file,
                  const char *diff, apr_pool_t *pool)
{
  apr_size_t bytes;
  apr_size_t len;
  const char *path;
  apr_file_t *apr_file;

  /* Create a patch file. */
  SVN_ERR(svn_io_open_unique_file3(&apr_file, &path, NULL,
                                   svn_io_file_del_on_pool_cleanup,
                                   pool, pool));

  bytes = strlen(diff);
  SVN_ERR(svn_io_file_write_full(apr_file, diff, bytes, &len, pool));
  if (len != bytes)
    return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
                             "Cannot write to '%s'", path);
  SVN_ERR(svn_io_file_close(apr_file, pool));
  SVN_ERR(svn_diff_open_patch_file(patch_file, path, pool));

  return SVN_NO_ERROR;
}
Exemplo n.º 13
0
/* See doc string for svn_ra_neon__parsed_request. */
static svn_error_t *
parsed_request(svn_ra_neon__request_t *req,
               svn_ra_neon__session_t *ras,
               const char *method,
               const char *url,
               const char *body,
               apr_file_t *body_file,
               void set_parser(ne_xml_parser *parser,
                               void *baton),
               svn_ra_neon__startelm_cb_t startelm_cb,
               svn_ra_neon__cdata_cb_t cdata_cb,
               svn_ra_neon__endelm_cb_t endelm_cb,
               void *baton,
               apr_hash_t *extra_headers,
               int *status_code,
               svn_boolean_t spool_response,
               apr_pool_t *pool)
{
  ne_xml_parser *success_parser = NULL;
  spool_reader_baton_t spool_reader_baton;

  if (body == NULL)
    SVN_ERR(svn_ra_neon__set_neon_body_provider(req, body_file));

  /* ### use a symbolic name somewhere for this MIME type? */
  ne_add_request_header(req->ne_req, "Content-Type", "text/xml");

  /* create a parser to read the normal response body */
  success_parser = svn_ra_neon__xml_parser_create(req, NULL,
                                                  startelm_cb, cdata_cb,
                                                  endelm_cb, baton);

  /* if our caller is interested in having access to this parser, call
     the SET_PARSER callback with BATON. */
  if (set_parser != NULL)
    set_parser(success_parser, baton);

  /* Register the "main" accepter and body-reader with the request --
     the one to use when the HTTP status is 2XX.  If we are spooling
     the response to disk first, we use our custom spool reader.  */
  if (spool_response)
    {
      /* Blow the temp-file away as soon as we eliminate the entire request */
      SVN_ERR(svn_io_open_unique_file3(&spool_reader_baton.spool_file,
                                       &spool_reader_baton.spool_file_name,
                                       NULL,
                                       svn_io_file_del_on_pool_cleanup,
                                       req->pool, pool));
      spool_reader_baton.req = req;

      svn_ra_neon__add_response_body_reader(req, ne_accept_2xx, spool_reader,
                                            &spool_reader_baton);
    }
  else
    attach_ne_body_reader(req, ne_accept_2xx, cancellation_callback,
                          get_cancellation_baton(req, ne_xml_parse_v,
                                                 success_parser, pool));

  /* run the request and get the resulting status code. */
  SVN_ERR(svn_ra_neon__request_dispatch(
              status_code, req, extra_headers, body,
              (strcmp(method, "PROPFIND") == 0) ? 207 : 200,
              0, pool));

  if (spool_response)
    {
      /* All done with the temporary file we spooled the response into. */
      (void) apr_file_close(spool_reader_baton.spool_file);

      /* The success parser may set an error value in req->err */
      SVN_RA_NEON__REQ_ERR
        (req, parse_spool_file(ras, spool_reader_baton.spool_file_name,
                               success_parser, req->pool));
      if (req->err)
        {
          svn_error_compose(req->err, svn_error_createf
                            (SVN_ERR_RA_DAV_REQUEST_FAILED, NULL,
                             _("Error reading spooled %s request response"),
                             method));
          return req->err;
        }
    }

  SVN_ERR(svn_ra_neon__check_parse_error(method, success_parser, url));

  return SVN_NO_ERROR;
}
Exemplo n.º 14
0
/* Edit CHUNK and return the result in *MERGED_CHUNK allocated in POOL. */
static svn_error_t *
edit_chunk(apr_array_header_t **merged_chunk,
           apr_array_header_t *chunk,
           const char *editor_cmd,
           apr_hash_t *config,
           apr_pool_t *result_pool,
           apr_pool_t *scratch_pool)
{
  apr_file_t *temp_file;
  const char *temp_file_name;
  int i;
  apr_off_t pos;
  svn_boolean_t eof;
  svn_error_t *err;
  apr_pool_t *iterpool;

  SVN_ERR(svn_io_open_unique_file3(&temp_file, &temp_file_name, NULL,
                                   svn_io_file_del_on_pool_cleanup,
                                   scratch_pool, scratch_pool));
  iterpool = svn_pool_create(scratch_pool);
  for (i = 0; i < chunk->nelts; i++)
    {
      svn_stringbuf_t *line = APR_ARRAY_IDX(chunk, i, svn_stringbuf_t *);
      apr_size_t bytes_written;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_io_file_write_full(temp_file, line->data, line->len,
                                     &bytes_written, iterpool));
      if (line->len != bytes_written)
        return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL,
                                _("Could not write data to temporary file"));
    }
  SVN_ERR(svn_io_file_flush(temp_file, scratch_pool));

  err = svn_cmdline__edit_file_externally(temp_file_name, editor_cmd,
                                          config, scratch_pool);
  if (err && (err->apr_err == SVN_ERR_CL_NO_EXTERNAL_EDITOR))
    {
      svn_error_t *root_err = svn_error_root_cause(err);

      SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
                                  root_err->message ? root_err->message :
                                  _("No editor found.")));
      svn_error_clear(err);
      *merged_chunk = NULL;
      svn_pool_destroy(iterpool);
      return SVN_NO_ERROR;
    }
  else if (err && (err->apr_err == SVN_ERR_EXTERNAL_PROGRAM))
    {
      svn_error_t *root_err = svn_error_root_cause(err);

      SVN_ERR(svn_cmdline_fprintf(stderr, scratch_pool, "%s\n",
                                  root_err->message ? root_err->message :
                                  _("Error running editor.")));
      svn_error_clear(err);
      *merged_chunk = NULL;
      svn_pool_destroy(iterpool);
      return SVN_NO_ERROR;
    }
  else if (err)
    return svn_error_trace(err);

  *merged_chunk = apr_array_make(result_pool, 1, sizeof(svn_stringbuf_t *));
  pos = 0;
  SVN_ERR(svn_io_file_seek(temp_file, APR_SET, &pos, scratch_pool));
  do
    {
      svn_stringbuf_t *line;
      const char *eol_str;

      svn_pool_clear(iterpool);

      SVN_ERR(svn_io_file_readline(temp_file, &line, &eol_str, &eof,
                                   APR_SIZE_MAX, result_pool, iterpool));
      if (eol_str)
        svn_stringbuf_appendcstr(line, eol_str);

      APR_ARRAY_PUSH(*merged_chunk, svn_stringbuf_t *) = line;
    }
  while (!eof);
  svn_pool_destroy(iterpool);

  SVN_ERR(svn_io_file_close(temp_file, scratch_pool));

  return SVN_NO_ERROR;
}
Exemplo n.º 15
0
svn_error_t *
svn_wc__internal_translated_file(const char **xlated_abspath,
                                 const char *src_abspath,
                                 svn_wc__db_t *db,
                                 const char *versioned_abspath,
                                 apr_uint32_t flags,
                                 svn_cancel_func_t cancel_func,
                                 void *cancel_baton,
                                 apr_pool_t *result_pool,
                                 apr_pool_t *scratch_pool)
{
  svn_subst_eol_style_t style;
  const char *eol;
  apr_hash_t *keywords;
  svn_boolean_t special;

  SVN_ERR_ASSERT(svn_dirent_is_absolute(src_abspath));
  SVN_ERR_ASSERT(svn_dirent_is_absolute(versioned_abspath));
  SVN_ERR(svn_wc__get_translate_info(&style, &eol,
                                     &keywords,
                                     &special,
                                     db, versioned_abspath, NULL, FALSE,
                                     scratch_pool, scratch_pool));

  if (! svn_subst_translation_required(style, eol, keywords, special, TRUE)
      && (! (flags & SVN_WC_TRANSLATE_FORCE_COPY)))
    {
      /* Translation would be a no-op, so return the original file. */
      *xlated_abspath = src_abspath;
    }
  else  /* some translation (or copying) is necessary */
    {
      const char *tmp_dir;
      const char *tmp_vfile;
      svn_boolean_t repair_forced
          = (flags & SVN_WC_TRANSLATE_FORCE_EOL_REPAIR) != 0;
      svn_boolean_t expand = (flags & SVN_WC_TRANSLATE_TO_NF) == 0;

      if (flags & SVN_WC_TRANSLATE_USE_GLOBAL_TMP)
        tmp_dir = NULL;
      else
        SVN_ERR(svn_wc__db_temp_wcroot_tempdir(&tmp_dir, db, versioned_abspath,
                                               scratch_pool, scratch_pool));

      SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_vfile, tmp_dir,
                (flags & SVN_WC_TRANSLATE_NO_OUTPUT_CLEANUP)
                  ? svn_io_file_del_none
                  : svn_io_file_del_on_pool_cleanup,
                result_pool, scratch_pool));

      /* ### ugh. the repair behavior does NOT match the docstring. bleah.
         ### all of these translation functions are crap and should go
         ### away anyways. we'll just deprecate most of the functions and
         ### properly document the survivors */

      if (expand)
        {
          /* from normal form */

          repair_forced = TRUE;
        }
      else
        {
          /* to normal form */

          if (style == svn_subst_eol_style_native)
            eol = SVN_SUBST_NATIVE_EOL_STR;
          else if (style == svn_subst_eol_style_fixed)
            repair_forced = TRUE;
          else if (style != svn_subst_eol_style_none)
            return svn_error_create(SVN_ERR_IO_UNKNOWN_EOL, NULL, NULL);
        }

      SVN_ERR(svn_subst_copy_and_translate4(src_abspath, tmp_vfile,
                                            eol, repair_forced,
                                            keywords,
                                            expand,
                                            special,
                                            cancel_func, cancel_baton,
                                            result_pool));

      *xlated_abspath = tmp_vfile;
    }

  return SVN_NO_ERROR;
}
Exemplo n.º 16
0
svn_error_t *
svn_spillbuf__write(svn_spillbuf_t *buf,
                    const char *data,
                    apr_size_t len,
                    apr_pool_t *scratch_pool)
{
  struct memblock_t *mem;

  /* We do not (yet) have a spill file, but the amount stored in memory
     will grow too large. Create the file and place the pending data into
     the temporary file.  */
  if (buf->spill == NULL
      && ((buf->maxsize - buf->memory_size) < len))
    {
      SVN_ERR(svn_io_open_unique_file3(&buf->spill,
                                       &buf->filename,
                                       buf->dirpath,
                                       (buf->delete_on_close
                                        ? svn_io_file_del_on_close
                                        : svn_io_file_del_none),
                                       buf->pool, scratch_pool));

      /* Optionally write the memory contents into the file. */
      if (buf->spill_all_contents)
        {
          mem = buf->head;
          while (mem != NULL)
            {
              SVN_ERR(svn_io_file_write_full(buf->spill, mem->data, mem->size,
                                             NULL, scratch_pool));
              mem = mem->next;
            }

          /* Adjust the start offset for reading from the spill file.

             This way, the first `buf->memory_size` bytes of data will
             be read from the existing in-memory buffers, which makes
             more sense than discarding the buffers and re-reading
             data from the file. */
          buf->spill_start = buf->memory_size;
        }
    }

  /* Once a spill file has been constructed, then we need to put all
     arriving data into the file. We will no longer attempt to hold it
     in memory.  */
  if (buf->spill != NULL)
    {
      apr_off_t output_unused = 0;  /* ### stupid API  */

      /* Seek to the end of the spill file. We don't know if a read has
         occurred since our last write, and moved the file position.  */
      SVN_ERR(svn_io_file_seek(buf->spill,
                               APR_END, &output_unused,
                               scratch_pool));

      SVN_ERR(svn_io_file_write_full(buf->spill, data, len,
                                     NULL, scratch_pool));
      buf->spill_size += len;

      return SVN_NO_ERROR;
    }

  while (len > 0)
    {
      apr_size_t amt;

      if (buf->tail == NULL || buf->tail->size == buf->blocksize)
        {
          /* There is no existing memblock (that may have space), or the
             tail memblock has no space, so we need a new memblock.  */
          mem = get_buffer(buf);
          mem->size = 0;
          mem->next = NULL;
        }
      else
        {
          mem = buf->tail;
        }

      /* Compute how much to write into the memblock.  */
      amt = buf->blocksize - mem->size;
      if (amt > len)
        amt = len;

      /* Copy some data into this memblock.  */
      memcpy(&mem->data[mem->size], data, amt);
      mem->size += amt;
      data += amt;
      len -= amt;

      /* We need to record how much is buffered in memory. Once we reach
         buf->maxsize (or thereabouts, it doesn't have to be precise), then
         we'll switch to putting the content into a file.  */
      buf->memory_size += amt;

      /* Start a list of buffers, or (if we're not writing into the tail)
         append to the end of the linked list of buffers.  */
      if (buf->tail == NULL)
        {
          buf->head = mem;
          buf->tail = mem;
        }
      else if (mem != buf->tail)
        {
          buf->tail->next = mem;
          buf->tail = mem;
        }
    }

  return SVN_NO_ERROR;
}
Exemplo n.º 17
0
/* Make a copy of the filesystem node (or tree if RECURSIVE) at
   SRC_ABSPATH under a temporary name in the directory
   TMPDIR_ABSPATH and return the absolute path of the copy in
   *DST_ABSPATH.  Return the node kind of SRC_ABSPATH in *KIND.  If
   SRC_ABSPATH doesn't exist then set *DST_ABSPATH to NULL to indicate
   that no copy was made. */
static svn_error_t *
copy_to_tmpdir(svn_skel_t **work_item,
               svn_node_kind_t *kind,
               svn_wc__db_t *db,
               const char *src_abspath,
               const char *dst_abspath,
               const char *tmpdir_abspath,
               svn_boolean_t file_copy,
               svn_boolean_t unversioned,
               svn_cancel_func_t cancel_func,
               void *cancel_baton,
               apr_pool_t *result_pool,
               apr_pool_t *scratch_pool)
{
  svn_boolean_t is_special;
  svn_io_file_del_t delete_when;
  const char *dst_tmp_abspath;
  svn_node_kind_t dsk_kind;
  if (!kind)
    kind = &dsk_kind;

  *work_item = NULL;

  SVN_ERR(svn_io_check_special_path(src_abspath, kind, &is_special,
                                    scratch_pool));
  if (*kind == svn_node_none)
    {
      return SVN_NO_ERROR;
    }
  else if (*kind == svn_node_unknown)
    {
      return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
                               _("Source '%s' is unexpected kind"),
                               svn_dirent_local_style(src_abspath,
                                                      scratch_pool));
    }
  else if (*kind == svn_node_dir || is_special)
    delete_when = svn_io_file_del_on_close;
  else /* the default case: (*kind == svn_node_file) */
    delete_when = svn_io_file_del_none;

  /* ### Do we need a pool cleanup to remove the copy?  We can't use
     ### svn_io_file_del_on_pool_cleanup above because a) it won't
     ### handle the directory case and b) we need to be able to remove
     ### the cleanup before queueing the move work item. */

  if (file_copy && !unversioned)
    {
      svn_boolean_t modified;
      /* It's faster to look for mods on the source now, as
         the timestamp might match, than to examine the
         destination later as the destination timestamp will
         never match. */
      SVN_ERR(svn_wc__internal_file_modified_p(&modified,
                                               db, src_abspath,
                                               FALSE, scratch_pool));
      if (!modified)
        {
          /* Why create a temp copy if we can just reinstall from pristine? */
          SVN_ERR(svn_wc__wq_build_file_install(work_item,
                                                db, dst_abspath, NULL, FALSE,
                                                TRUE,
                                                result_pool, scratch_pool));
          return SVN_NO_ERROR;
        }
    }

  /* Set DST_TMP_ABSPATH to a temporary unique path.  If *KIND is file, leave
     a file there and then overwrite it; otherwise leave no node on disk at
     that path.  In the latter case, something else might use that path
     before we get around to using it a moment later, but never mind. */
  SVN_ERR(svn_io_open_unique_file3(NULL, &dst_tmp_abspath, tmpdir_abspath,
                                   delete_when, scratch_pool, scratch_pool));

  if (*kind == svn_node_dir)
    {
      if (file_copy)
        SVN_ERR(svn_io_copy_dir_recursively(
                           src_abspath,
                           tmpdir_abspath,
                           svn_dirent_basename(dst_tmp_abspath, scratch_pool),
                           TRUE, /* copy_perms */
                           cancel_func, cancel_baton,
                           scratch_pool));
      else
        SVN_ERR(svn_io_dir_make(dst_tmp_abspath, APR_OS_DEFAULT, scratch_pool));
    }
  else if (!is_special)
    SVN_ERR(svn_io_copy_file(src_abspath, dst_tmp_abspath,
                             TRUE /* copy_perms */,
                             scratch_pool));
  else
    SVN_ERR(svn_io_copy_link(src_abspath, dst_tmp_abspath, scratch_pool));

  if (file_copy)
    {
      /* Remove 'read-only' from the destination file; it's a local add now. */
      SVN_ERR(svn_io_set_file_read_write(dst_tmp_abspath,
                                         FALSE, scratch_pool));
    }

  SVN_ERR(svn_wc__wq_build_file_move(work_item, db, dst_abspath,
                                     dst_tmp_abspath, dst_abspath,
                                     result_pool, scratch_pool));

  return SVN_NO_ERROR;
}