Alien-SVN

 view release on metacpan or  search on metacpan

src/subversion/subversion/libsvn_subr/io.c  view on Meta::CPAN

    {
      *same12 = *same13 = FALSE;
      SVN_ERR(contents_identical_p(same23, file2, file3, scratch_pool));
    }
  else
    {
      SVN_ERR_ASSERT(!diff_size12 && !diff_size23 && !diff_size13);
      SVN_ERR(contents_three_identical_p(same12, same23, same13,
                                         file1, file2, file3,
                                         scratch_pool));
    }

  return SVN_NO_ERROR;
}

#ifdef WIN32
/* Counter value of file_mktemp request (used in a threadsafe way), to make
   sure that a single process normally never generates the same tempname
   twice */
static volatile apr_uint32_t tempname_counter = 0;
#endif

/* Creates a new temporary file in DIRECTORY with apr flags FLAGS.
   Set *NEW_FILE to the file handle and *NEW_FILE_NAME to its name.
   Perform temporary allocations in SCRATCH_POOL and the result in
   RESULT_POOL. */
static svn_error_t *
temp_file_create(apr_file_t **new_file,
                 const char **new_file_name,
                 const char *directory,
                 apr_int32_t flags,
                 apr_pool_t *result_pool,
                 apr_pool_t *scratch_pool)
{
#ifndef WIN32
  const char *templ = svn_dirent_join(directory, "svn-XXXXXX", scratch_pool);
  const char *templ_apr;
  apr_status_t status;

  SVN_ERR(svn_path_cstring_from_utf8(&templ_apr, templ, scratch_pool));

  /* ### svn_path_cstring_from_utf8() guarantees to make a copy of the
         data available in POOL and we need a non-const pointer here,
         as apr changes the template to return the new filename. */
  status = apr_file_mktemp(new_file, (char *)templ_apr, flags, result_pool);

  if (status)
    return svn_error_wrap_apr(status, _("Can't create temporary file from "
                              "template '%s'"), templ);

  /* Translate the returned path back to utf-8 before returning it */
  return svn_error_trace(svn_path_cstring_to_utf8(new_file_name,
                                                  templ_apr,
                                                  result_pool));
#else
  /* The Windows implementation of apr_file_mktemp doesn't handle access
     denied errors correctly. Therefore we implement our own temp file
     creation function here. */

  /* ### Most of this is borrowed from the svn_io_open_uniquely_named(),
     ### the function we used before. But we try to guess a more unique
     ### name before trying if it exists. */

  /* Offset by some time value and a unique request nr to make the number
     +- unique for both this process and on the computer */
  int baseNr = (GetTickCount() << 11) + 7 * svn_atomic_inc(&tempname_counter)
               + GetCurrentProcessId();
  int i;

  /* ### Maybe use an iterpool? */
  for (i = 0; i <= 99999; i++)
    {
      apr_uint32_t unique_nr;
      const char *unique_name;
      const char *unique_name_apr;
      apr_file_t *try_file;
      apr_status_t apr_err;

      /* Generate a number that should be unique for this application and
         usually for the entire computer to reduce the number of cycles
         through this loop. (A bit of calculation is much cheaper then
         disk io) */
      unique_nr = baseNr + 3 * i;

      unique_name = svn_dirent_join(directory,
                                    apr_psprintf(scratch_pool, "svn-%X",
                                                 unique_nr),
                                    scratch_pool);

      SVN_ERR(cstring_from_utf8(&unique_name_apr, unique_name, scratch_pool));

      apr_err = file_open(&try_file, unique_name_apr, flags,
                          APR_OS_DEFAULT, FALSE, scratch_pool);

      if (APR_STATUS_IS_EEXIST(apr_err))
          continue;
      else if (apr_err)
        {
          /* On Win32, CreateFile fails with an "Access Denied" error
             code, rather than "File Already Exists", if the colliding
             name belongs to a directory. */

          if (APR_STATUS_IS_EACCES(apr_err))
            {
              apr_finfo_t finfo;
              apr_status_t apr_err_2 = apr_stat(&finfo, unique_name_apr,
                                                APR_FINFO_TYPE, scratch_pool);

              if (!apr_err_2 && finfo.filetype == APR_DIR)
                continue;

              apr_err_2 = APR_TO_OS_ERROR(apr_err);

              if (apr_err_2 == ERROR_ACCESS_DENIED ||
                  apr_err_2 == ERROR_SHARING_VIOLATION)
                {
                  /* The file is in use by another process or is hidden;
                     create a new name, but don't do this 99999 times in
                     case the folder is not writable */
                  i += 797;
                  continue;



( run in 0.912 second using v1.01-cache-2.11-cpan-63c85eba8c4 )