You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@subversion.apache.org by rh...@apache.org on 2015/11/30 11:24:23 UTC

svn commit: r1717223 [32/50] - in /subversion/branches/ra-git: ./ build/ build/ac-macros/ build/generator/ build/generator/templates/ contrib/hook-scripts/ notes/ notes/api-errata/1.9/ notes/move-tracking/ subversion/ subversion/bindings/ctypes-python/...

Modified: subversion/branches/ra-git/subversion/libsvn_subr/config_auth.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/config_auth.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/config_auth.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/config_auth.c Mon Nov 30 10:24:16 2015
@@ -144,7 +144,7 @@ svn_config_write_auth_data(apr_hash_t *h
             apr_psprintf(pool, _("Error writing hash to '%s'"),
                          svn_dirent_local_style(auth_path, pool)));
   SVN_ERR(svn_stream_close(stream));
-  SVN_ERR(svn_io_file_rename(tmp_path, auth_path, pool));
+  SVN_ERR(svn_io_file_rename2(tmp_path, auth_path, FALSE, pool));
 
   /* To be nice, remove the realmstring from the hash again, just in
      case the caller wants their hash unchanged.

Modified: subversion/branches/ra-git/subversion/libsvn_subr/config_file.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/config_file.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/config_file.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/config_file.c Mon Nov 30 10:24:16 2015
@@ -74,6 +74,9 @@ typedef struct parse_context_t
   char parser_buffer[SVN__STREAM_CHUNK_SIZE]; /* Larger than most config files */
   size_t buffer_pos; /* Current position within parser_buffer */
   size_t buffer_size; /* parser_buffer contains this many bytes */
+
+  /* Non-zero if we hit EOF on the stream. */
+  svn_boolean_t hit_stream_eof;
 } parse_context_t;
 
 
@@ -101,11 +104,15 @@ parser_getc(parse_context_t *ctx, int *c
         }
       else
         {
-          ctx->buffer_pos = 0;
-          ctx->buffer_size = sizeof(ctx->parser_buffer);
+          if (!ctx->hit_stream_eof)
+            {
+              ctx->buffer_pos = 0;
+              ctx->buffer_size = sizeof(ctx->parser_buffer);
 
-          SVN_ERR(svn_stream_read_full(ctx->stream, ctx->parser_buffer,
-                                       &(ctx->buffer_size)));
+              SVN_ERR(svn_stream_read_full(ctx->stream, ctx->parser_buffer,
+                                           &(ctx->buffer_size)));
+              ctx->hit_stream_eof = (ctx->buffer_size != sizeof(ctx->parser_buffer));
+            }
 
           if (ctx->buffer_pos < ctx->buffer_size)
             {
@@ -224,8 +231,10 @@ skip_bom(parse_context_t *ctx)
        * of the BOM characters into the parse_context_t buffer.  This can
        * safely be assumed as long as we only try to use skip_bom() at the
        * start of the stream and the buffer is longer than 3 characters. */
-      SVN_ERR_ASSERT(ctx->buffer_size > ctx->buffer_pos + 1);
-      if (buf[ctx->buffer_pos] == 0xBB && buf[ctx->buffer_pos + 1] == 0xBF)
+      SVN_ERR_ASSERT(ctx->buffer_size > ctx->buffer_pos + 1 ||
+                     ctx->hit_stream_eof);
+      if (ctx->buffer_size > ctx->buffer_pos + 1 &&
+          buf[ctx->buffer_pos] == 0xBB && buf[ctx->buffer_pos + 1] == 0xBF)
         ctx->buffer_pos += 2;
       else
         SVN_ERR(parser_ungetc(ctx, ch));
@@ -579,6 +588,7 @@ svn_config__parse_stream(svn_config_t *c
   ctx->value = svn_stringbuf_create_empty(scratch_pool);
   ctx->buffer_pos = 0;
   ctx->buffer_size = 0;
+  ctx->hit_stream_eof = FALSE;
 
   SVN_ERR(skip_bom(ctx));
 
@@ -940,7 +950,6 @@ svn_config_ensure(const char *config_dir
         "###                              HTTP operation."                   NL
         "###   http-chunked-requests      Whether to use chunked transfer"   NL
         "###                              encoding for HTTP requests body."  NL
-        "###   neon-debug-mask            Debug mask for Neon HTTP library"  NL
         "###   ssl-authority-files        List of files, each of a trusted CA"
                                                                              NL
         "###   ssl-trust-default-ca       Trust the system 'default' CAs"    NL
@@ -1033,7 +1042,6 @@ svn_config_ensure(const char *config_dir
         "### Most users will not need to explicitly set the http-library"    NL
         "### option, but valid values for the option include:"               NL
         "###    'serf': Serf-based module (Subversion 1.5 - present)"        NL
-        "###    'neon': Neon-based module (Subversion 1.0 - 1.7)"            NL
         "### Availability of these modules may depend on your specific"      NL
         "### Subversion distribution."                                       NL
         "###"                                                                NL
@@ -1058,7 +1066,6 @@ svn_config_ensure(const char *config_dir
         "# http-proxy-username = blah"                                       NL
         "# http-proxy-password = doubleblah"                                 NL
         "# http-timeout = 60"                                                NL
-        "# neon-debug-mask = 130"                                            NL
 #ifndef SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE
         "# store-plaintext-passwords = no"                                   NL
 #endif
@@ -1099,7 +1106,6 @@ svn_config_ensure(const char *config_dir
         "# http-proxy-password = defaultpassword"                            NL
         "# http-compression = no"                                            NL
         "# No http-timeout, so just use the builtin default."                NL
-        "# No neon-debug-mask, so neon debugging is disabled."               NL
         "# ssl-authority-files = /path/to/CAcert.pem;/path/to/CAcert2.pem"   NL
         "#"                                                                  NL
         "# Password / passphrase caching parameters:"                        NL
@@ -1411,7 +1417,7 @@ svn_config_get_user_config_path(const ch
     if (! homedir)
       return SVN_NO_ERROR;
     *path = svn_dirent_join_many(pool,
-                               svn_dirent_canonicalize(homedir, pool),
+                                 homedir,
                                SVN_CONFIG__USR_DIRECTORY, fname, SVN_VA_NULL);
   }
 #endif /* WIN32 */

Modified: subversion/branches/ra-git/subversion/libsvn_subr/config_win.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/config_win.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/config_win.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/config_win.c Mon Nov 30 10:24:16 2015
@@ -197,14 +197,19 @@ svn_config__parse_registry(svn_config_t
                      &hkey);
   if (err != ERROR_SUCCESS)
     {
-      const int is_enoent = APR_STATUS_IS_ENOENT(APR_FROM_OS_ERROR(err));
+      apr_status_t apr_err = APR_FROM_OS_ERROR(err);
+      svn_boolean_t is_enoent = APR_STATUS_IS_ENOENT(apr_err)
+                                || (err == ERROR_INVALID_HANDLE);
+
       if (!is_enoent)
-        return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
+        return svn_error_createf(SVN_ERR_BAD_FILENAME,
+                                 svn_error_wrap_apr(apr_err, NULL),
                                  _("Can't open registry key '%s'"),
                                  svn_dirent_local_style(file, pool));
-      else if (must_exist && is_enoent)
-        return svn_error_createf(SVN_ERR_BAD_FILENAME, NULL,
-                                 _("Can't find registry key '%s'"),
+      else if (must_exist)
+        return svn_error_createf(SVN_ERR_BAD_FILENAME,
+                                 NULL,
+                                 _("Can't open registry key '%s'"),
                                  svn_dirent_local_style(file, pool));
       else
         return SVN_NO_ERROR;

Modified: subversion/branches/ra-git/subversion/libsvn_subr/deprecated.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/deprecated.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/deprecated.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/deprecated.c Mon Nov 30 10:24:16 2015
@@ -46,6 +46,7 @@
 #include "svn_utf.h"
 #include "svn_xml.h"
 #include "svn_auth.h"
+#include "svn_base64.h"
 
 #include "opt.h"
 #include "auth.h"
@@ -889,6 +890,26 @@ svn_io_stat_dirent(const svn_io_dirent2_
                                 scratch_pool));
 }
 
+svn_error_t *
+svn_io_file_rename(const char *from_path, const char *to_path,
+                   apr_pool_t *pool)
+{
+  return svn_error_trace(svn_io_file_rename2(from_path, to_path,
+                                             FALSE, pool));
+}
+
+svn_error_t *
+svn_io_write_atomic(const char *final_path,
+                    const void *buf,
+                    apr_size_t nbytes,
+                    const char *copy_perms_path,
+                    apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(svn_io_write_atomic2(final_path, buf, nbytes,
+                                              copy_perms_path, TRUE,
+                                              scratch_pool));
+}
+
 /*** From constructors.c ***/
 svn_log_changed_path_t *
 svn_log_changed_path_dup(const svn_log_changed_path_t *changed_path,
@@ -1058,6 +1079,12 @@ svn_stream_from_aprfile(apr_file_t *file
 }
 
 svn_error_t *
+svn_stream_for_stdin(svn_stream_t **in, apr_pool_t *pool)
+{
+  return svn_error_trace(svn_stream_for_stdin2(in, FALSE, pool));
+}
+
+svn_error_t *
 svn_stream_contents_same(svn_boolean_t *same,
                          svn_stream_t *stream1,
                          svn_stream_t *stream2,
@@ -1183,6 +1210,16 @@ svn_stream_checksummed(svn_stream_t *str
   return s;
 }
 
+svn_error_t *
+svn_string_from_stream(svn_string_t **result,
+                       svn_stream_t *stream,
+                       apr_pool_t *result_pool,
+                       apr_pool_t *scratch_pool)
+{
+  return svn_error_trace(svn_string_from_stream2(result, stream, 0,
+                                                 result_pool));
+}
+
 /*** From path.c ***/
 
 const char *
@@ -1501,7 +1538,11 @@ void
 svn_auth_get_gpg_agent_simple_provider(svn_auth_provider_object_t **provider,
                                        apr_pool_t *pool)
 {
+#ifdef SVN_HAVE_GPG_AGENT
   svn_auth__get_gpg_agent_simple_provider(provider, pool);
+#else
+  svn_auth__get_dummmy_simple_provider(provider, pool);
+#endif /* SVN_HAVE_GPG_AGENT */
 }
 #endif /* !WIN32 */
 
@@ -1534,3 +1575,10 @@ svn_cmdline_create_auth_baton(svn_auth_b
                                                         cancel_baton,
                                                         pool));
 }
+
+/*** From base64.c ***/
+svn_stream_t *
+svn_base64_encode(svn_stream_t *output, apr_pool_t *pool)
+{
+  return svn_base64_encode2(output, TRUE, pool);
+}

Modified: subversion/branches/ra-git/subversion/libsvn_subr/dirent_uri.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/dirent_uri.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/dirent_uri.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/dirent_uri.c Mon Nov 30 10:24:16 2015
@@ -495,14 +495,20 @@ canonicalize(path_type_t type, const cha
 #ifdef SVN_USE_DOS_PATHS
       /* If this is the first path segment of a file:// URI and it contains a
          windows drive letter, convert the drive letter to upper case. */
-      else if (url && canon_segments == 1 && seglen == 2 &&
+      else if (url && canon_segments == 1 && seglen >= 2 &&
                (strncmp(canon, "file:", 5) == 0) &&
                src[0] >= 'a' && src[0] <= 'z' && src[1] == ':')
         {
           *(dst++) = canonicalize_to_upper(src[0]);
           *(dst++) = ':';
-          if (*next)
-            *(dst++) = *next;
+          if (seglen > 2) /* drive relative path */
+            {
+              memcpy(dst, src + 2, seglen - 2);
+              dst += seglen - 2;
+            }
+
+          if (slash_len)
+            *(dst++) = '/';
           canon_segments++;
         }
 #endif /* SVN_USE_DOS_PATHS */
@@ -1295,9 +1301,9 @@ svn_relpath_split(const char **dirpath,
 }
 
 const char *
-svn_relpath_limit(const char *relpath,
-                  int max_components,
-                  apr_pool_t *result_pool)
+svn_relpath_prefix(const char *relpath,
+                   int max_components,
+                   apr_pool_t *result_pool)
 {
   const char *end;
   assert(relpath_is_canonical(relpath));
@@ -2398,8 +2404,11 @@ svn_uri_get_dirent_from_file_url(const c
         if (dup_path[1] == '|')
           dup_path[1] = ':';
 
-        if (dup_path[2] == '/' || dup_path[2] == '\0')
+        if (dup_path[2] == '/' || dup_path[2] == '\\' || dup_path[2] == '\0')
           {
+            /* Dirents have upper case drive letters in their canonical form */
+            dup_path[0] = canonicalize_to_upper(dup_path[0]);
+
             if (dup_path[2] == '\0')
               {
                 /* A valid dirent for the driveroot must be like "C:/" instead of
@@ -2412,6 +2421,8 @@ svn_uri_get_dirent_from_file_url(const c
                 new_path[3] = '\0';
                 dup_path = new_path;
               }
+            else
+              dup_path[2] = '/'; /* Ensure not relative for '\' after drive! */
           }
       }
     if (hostname)

Modified: subversion/branches/ra-git/subversion/libsvn_subr/dso.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/dso.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/dso.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/dso.c Mon Nov 30 10:24:16 2015
@@ -19,7 +19,6 @@
  * ====================================================================
  */
 
-#include <apr_thread_mutex.h>
 #include <apr_hash.h>
 
 #include "svn_hash.h"
@@ -29,6 +28,7 @@
 
 #include "private/svn_mutex.h"
 #include "private/svn_atomic.h"
+#include "private/svn_subr_private.h"
 
 /* A mutex to protect our global pool and cache. */
 static svn_mutex__t *dso_mutex = NULL;
@@ -123,4 +123,11 @@ svn_dso_load(apr_dso_handle_t **dso, con
 
   return SVN_NO_ERROR;
 }
+
+apr_pool_t *
+svn_dso__pool(void)
+{
+  return dso_pool;
+}
+
 #endif /* APR_HAS_DSO */

Modified: subversion/branches/ra-git/subversion/libsvn_subr/error.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/error.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/error.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/error.c Mon Nov 30 10:24:16 2015
@@ -59,11 +59,12 @@ static apr_threadkey_t *error_line_key =
 /* No-op destructor for apr_threadkey_private_create(). */
 static void null_threadkey_dtor(void *stuff) {}
 
-/* Handler for svn_atomic__init_once used by svn_error__locate to
-   initialize the thread-local error location storage.
-   This function will never return an error. */
-static svn_error_t *
-locate_init_once(void *ignored_baton, apr_pool_t *ignored_pool)
+/* Implements svn_atomic__str_init_func_t.
+   Callback used by svn_error__locate to initialize the thread-local
+   error location storage.  This function will never return an
+   error string. */
+static const char *
+locate_init_once(void *ignored_baton)
 {
   /* Strictly speaking, this is a memory leak, since we're creating an
      unmanaged, top-level pool and never destroying it.  We do this
@@ -86,7 +87,7 @@ locate_init_once(void *ignored_baton, ap
   if (status != APR_SUCCESS)
     error_file_key = error_line_key = NULL;
 
-  return SVN_NO_ERROR;
+  return NULL;
 }
 #  endif  /* APR_HAS_THREADS */
 
@@ -124,9 +125,7 @@ svn_error__locate(const char *file, long
 #ifdef SVN_DEBUG
 #  if APR_HAS_THREADS
   static volatile svn_atomic_t init_status = 0;
-  svn_error_clear(svn_atomic__init_once(&init_status,
-                                        locate_init_once,
-                                        NULL, NULL));
+  svn_atomic__init_once_no_error(&init_status, locate_init_once, NULL);
 
   if (error_file_key && error_line_key)
     {
@@ -164,7 +163,9 @@ make_error_internal(apr_status_t apr_err
 {
   apr_pool_t *pool;
   svn_error_t *new_error;
-  apr_status_t status = APR_SUCCESS;
+#ifdef SVN_DEBUG
+  apr_status_t status = APR_ENOTIMPL;
+#endif
 
   /* Reuse the child's pool, or create our own. */
   if (child)

Modified: subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.c Mon Nov 30 10:24:16 2015
@@ -132,6 +132,25 @@ svn__fnv1a_32x4(const void *input, apr_s
                              len - processed);
 }
 
+void
+svn__fnv1a_32x4_raw(apr_uint32_t hashes[4],
+                    const void *input,
+                    apr_size_t len)
+{
+  apr_size_t processed;
+
+  apr_size_t i;
+  for (i = 0; i < SCALING; ++i)
+    hashes[i] = FNV1_BASE_32;
+
+  /* Process full 16 byte chunks. */
+  processed = fnv1a_32x4(hashes, input, len);
+
+  /* Fold the remainder (if any) into the first hash. */
+  hashes[0] = fnv1a_32(hashes[0], (const char *)input + processed,
+                       len - processed);
+}
+
 struct svn_fnv1a_32__context_t
 {
   apr_uint32_t hash;

Modified: subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.h
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.h?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.h (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/fnv1a.h Mon Nov 30 10:24:16 2015
@@ -76,6 +76,14 @@ svn_fnv1a_32x4__update(svn_fnv1a_32x4__c
 apr_uint32_t
 svn_fnv1a_32x4__finalize(svn_fnv1a_32x4__context_t *context);
 
+/* Set HASHES to the 4 partial hash sums produced by the modified FVN-1a
+ * over INPUT of LEN bytes.
+ */
+void
+svn__fnv1a_32x4_raw(apr_uint32_t hashes[4],
+                    const void *input,
+                    apr_size_t len);
+
 #ifdef __cplusplus
 }
 #endif /* __cplusplus */

Modified: subversion/branches/ra-git/subversion/libsvn_subr/hash.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/hash.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/hash.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/hash.c Mon Nov 30 10:24:16 2015
@@ -135,7 +135,7 @@ svn_hash__read_entry(svn_hash__entry_t *
                                   0, APR_SIZE_MAX, 10);
       if (err)
         return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key length"));
       entry->keylen = (apr_size_t)ui64;
 
       /* Now read that much into a buffer. */
@@ -148,19 +148,19 @@ svn_hash__read_entry(svn_hash__entry_t *
       SVN_ERR(svn_stream_read_full(stream, &c, &len));
       if (c != '\n')
         return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key data"));
 
       /* Read a val length line */
       SVN_ERR(svn_stream_readline(stream, &buf, "\n", &eof, pool));
 
       if ((buf->data[0] == 'V') && (buf->data[1] == ' '))
         {
-          /* Get the length of the key */
+          /* Get the length of the val */
           err = svn_cstring_strtoui64(&ui64, buf->data + 2,
                                       0, APR_SIZE_MAX, 10);
           if (err)
             return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
-                                    _("Serialized hash malformed"));
+                                    _("Serialized hash malformed value length"));
           entry->vallen = (apr_size_t)ui64;
 
           entry->val = apr_palloc(pool, entry->vallen + 1);
@@ -172,7 +172,7 @@ svn_hash__read_entry(svn_hash__entry_t *
           SVN_ERR(svn_stream_read_full(stream, &c, &len));
           if (c != '\n')
             return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
-                                    _("Serialized hash malformed"));
+                                    _("Serialized hash malformed value data"));
         }
       else
         return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
@@ -186,7 +186,7 @@ svn_hash__read_entry(svn_hash__entry_t *
                                   0, APR_SIZE_MAX, 10);
       if (err)
         return svn_error_create(SVN_ERR_MALFORMED_FILE, err,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key length"));
       entry->keylen = (apr_size_t)ui64;
 
       /* Now read that much into a buffer. */
@@ -199,7 +199,7 @@ svn_hash__read_entry(svn_hash__entry_t *
       SVN_ERR(svn_stream_read_full(stream, &c, &len));
       if (c != '\n')
         return svn_error_create(SVN_ERR_MALFORMED_FILE, NULL,
-                                _("Serialized hash malformed"));
+                                _("Serialized hash malformed key data"));
 
       /* Remove this hash entry. */
       entry->vallen = 0;

Modified: subversion/branches/ra-git/subversion/libsvn_subr/io.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/io.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/io.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/io.c Mon Nov 30 10:24:16 2015
@@ -142,6 +142,23 @@
 #endif
 
 #ifdef WIN32
+
+#if _WIN32_WINNT < 0x600 /* Does the SDK assume Windows Vista+? */
+typedef struct _FILE_RENAME_INFO {
+  BOOL   ReplaceIfExists;
+  HANDLE RootDirectory;
+  DWORD  FileNameLength;
+  WCHAR  FileName[1];
+} FILE_RENAME_INFO, *PFILE_RENAME_INFO;
+
+typedef struct _FILE_DISPOSITION_INFO {
+  BOOL DeleteFile;
+} FILE_DISPOSITION_INFO, *PFILE_DISPOSITION_INFO;
+
+#define FileRenameInfo 3
+#define FileDispositionInfo 4
+#endif /* WIN32 < Vista */
+
 /* One-time initialization of the late bound Windows API functions. */
 static volatile svn_atomic_t win_dynamic_imports_state = 0;
 
@@ -152,7 +169,13 @@ typedef DWORD (WINAPI *GETFINALPATHNAMEB
                DWORD cchFilePath,
                DWORD dwFlags);
 
+typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile,
+                                                    int FileInformationClass,
+                                                    LPVOID lpFileInformation,
+                                                    DWORD dwBufferSize);
+
 static GETFINALPATHNAMEBYHANDLE get_final_path_name_by_handle_proc = NULL;
+static SetFileInformationByHandle_t set_file_information_by_handle_proc = NULL;
 
 /* Forward declaration. */
 static svn_error_t * io_win_read_link(svn_string_t **dest,
@@ -555,10 +578,8 @@ svn_io_open_uniquely_named(apr_file_t **
                 continue;
 
 #ifdef WIN32
-              apr_err_2 = APR_TO_OS_ERROR(apr_err);
-
-              if (apr_err_2 == ERROR_ACCESS_DENIED ||
-                  apr_err_2 == ERROR_SHARING_VIOLATION)
+              if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED) ||
+                  apr_err == APR_FROM_OS_ERROR(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
@@ -750,7 +771,7 @@ svn_io_copy_link(const char *src,
                                     ".tmp", pool));
 
   /* Move the tmp-link to link. */
-  return svn_io_file_rename(dst_tmp, dst, pool);
+  return svn_io_file_rename2(dst_tmp, dst, FALSE, pool);
 
 #else
   return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
@@ -919,7 +940,7 @@ svn_io_copy_file(const char *src,
   if (copy_perms)
     SVN_ERR(svn_io_copy_perms(src, dst_tmp, pool));
 
-  return svn_error_trace(svn_io_file_rename(dst_tmp, dst, pool));
+  return svn_error_trace(svn_io_file_rename2(dst_tmp, dst, FALSE, pool));
 }
 
 #if !defined(WIN32) && !defined(__OS2__)
@@ -1191,7 +1212,7 @@ svn_error_t *
 svn_io_file_create_bytes(const char *file,
                          const void *contents,
                          apr_size_t length,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
   apr_file_t *f;
   apr_size_t written;
@@ -1200,13 +1221,14 @@ svn_io_file_create_bytes(const char *fil
   SVN_ERR(svn_io_file_open(&f, file,
                            (APR_WRITE | APR_CREATE | APR_EXCL),
                            APR_OS_DEFAULT,
-                           pool));
+                           scratch_pool));
   if (length)
-    err = svn_io_file_write_full(f, contents, length, &written, pool);
+    err = svn_io_file_write_full(f, contents, length, &written,
+                                 scratch_pool);
 
   err = svn_error_compose_create(
                     err,
-                    svn_io_file_close(f, pool));
+                    svn_io_file_close(f, scratch_pool));
 
   if (err)
     {
@@ -1216,7 +1238,7 @@ svn_io_file_create_bytes(const char *fil
       return svn_error_trace(
                 svn_error_compose_create(
                     err,
-                    svn_io_remove_file2(file, TRUE, pool)));
+                    svn_io_remove_file2(file, TRUE, scratch_pool)));
     }
 
   return SVN_NO_ERROR;
@@ -1235,9 +1257,10 @@ svn_io_file_create(const char *file,
 
 svn_error_t *
 svn_io_file_create_empty(const char *file,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
-  return svn_error_trace(svn_io_file_create_bytes(file, NULL, 0, pool));
+  return svn_error_trace(svn_io_file_create_bytes(file, NULL, 0,
+                                                  scratch_pool));
 }
 
 svn_error_t *
@@ -1502,20 +1525,23 @@ reown_file(const char *path,
   SVN_ERR(svn_io_open_unique_file3(NULL, &unique_name,
                                    svn_dirent_dirname(path, pool),
                                    svn_io_file_del_none, pool, pool));
-  SVN_ERR(svn_io_file_rename(path, unique_name, pool));
+  SVN_ERR(svn_io_file_rename2(path, unique_name, FALSE, pool));
   SVN_ERR(svn_io_copy_file(unique_name, path, TRUE, pool));
   return svn_error_trace(svn_io_remove_file2(unique_name, FALSE, pool));
 }
 
 /* Determine what the PERMS for a new file should be by looking at the
-   permissions of a temporary file that we create.
+   permissions of a temporary file that we create in DIRECTORY.  
+   DIRECTORY can be NULL in which case the system temporary dir is used.
    Unfortunately, umask() as defined in POSIX provides no thread-safe way
    to get at the current value of the umask, so what we're doing here is
    the only way we have to determine which combination of write bits
    (User/Group/World) should be set by default.
    Make temporary allocations in SCRATCH_POOL.  */
 static svn_error_t *
-get_default_file_perms(apr_fileperms_t *perms, apr_pool_t *scratch_pool)
+get_default_file_perms(apr_fileperms_t *perms,
+                       const char *directory,
+                       apr_pool_t *scratch_pool)
 {
   /* the default permissions as read from the temp folder */
   static apr_fileperms_t default_perms = 0;
@@ -1547,7 +1573,7 @@ get_default_file_perms(apr_fileperms_t *
                    + (apr_uint32_t)apr_time_now());
       fname_base = apr_psprintf(scratch_pool, "svn-%08x", randomish);
 
-      SVN_ERR(svn_io_open_uniquely_named(&fd, &fname, NULL, fname_base,
+      SVN_ERR(svn_io_open_uniquely_named(&fd, &fname, directory, fname_base,
                                          NULL, svn_io_file_del_none,
                                          scratch_pool, scratch_pool));
       err = svn_io_file_info_get(&finfo, APR_FINFO_PROT, fd, scratch_pool);
@@ -1565,16 +1591,19 @@ get_default_file_perms(apr_fileperms_t *
 }
 
 /* OR together permission bits of the file FD and the default permissions
-   of a file as determined by get_default_file_perms(). Do temporary
+   of a file as determined by get_default_file_perms().  DIRECTORY is used
+   to create temporary files, DIRECTORY can be NULL.  Do temporary
    allocations in SCRATCH_POOL. */
 static svn_error_t *
-merge_default_file_perms(apr_file_t *fd, apr_fileperms_t *perms,
+merge_default_file_perms(apr_file_t *fd,
+                         apr_fileperms_t *perms,
+                         const char *directory,
                          apr_pool_t *scratch_pool)
 {
   apr_finfo_t finfo;
   apr_fileperms_t default_perms;
 
-  SVN_ERR(get_default_file_perms(&default_perms, scratch_pool));
+  SVN_ERR(get_default_file_perms(&default_perms, directory, scratch_pool));
   SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_PROT, fd, scratch_pool));
 
   /* Glom the perms together. */
@@ -1854,16 +1883,23 @@ io_win_file_attrs_set(const char *fname,
                                   _("Can't set attributes of file '%s'"),
                                   svn_dirent_local_style(fname, pool));
 
-    return SVN_NO_ERROR;;
+    return SVN_NO_ERROR;
 }
 
 static svn_error_t *win_init_dynamic_imports(void *baton, apr_pool_t *pool)
 {
-    get_final_path_name_by_handle_proc = (GETFINALPATHNAMEBYHANDLE)
-      GetProcAddress(GetModuleHandleA("kernel32.dll"),
-                     "GetFinalPathNameByHandleW");
+  HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
 
-    return SVN_NO_ERROR;
+  if (kernel32)
+    {
+      get_final_path_name_by_handle_proc = (GETFINALPATHNAMEBYHANDLE)
+        GetProcAddress(kernel32, "GetFinalPathNameByHandleW");
+
+      set_file_information_by_handle_proc = (SetFileInformationByHandle_t)
+        GetProcAddress(kernel32, "SetFileInformationByHandle");
+    }
+
+  return SVN_NO_ERROR;
 }
 
 static svn_error_t * io_win_read_link(svn_string_t **dest,
@@ -1935,6 +1971,130 @@ static svn_error_t * io_win_read_link(sv
       }
 }
 
+/* Wrapper around Windows API function SetFileInformationByHandle() that
+ * returns APR status instead of boolean flag. */
+static apr_status_t
+win32_set_file_information_by_handle(HANDLE hFile,
+                                     int FileInformationClass,
+                                     LPVOID lpFileInformation,
+                                     DWORD dwBufferSize)
+{
+  svn_error_clear(svn_atomic__init_once(&win_dynamic_imports_state,
+                                        win_init_dynamic_imports,
+                                        NULL, NULL));
+
+  if (!set_file_information_by_handle_proc)
+    {
+      return SVN_ERR_UNSUPPORTED_FEATURE;
+    }
+
+  if (!set_file_information_by_handle_proc(hFile, FileInformationClass,
+                                           lpFileInformation,
+                                           dwBufferSize))
+    {
+      return apr_get_os_error();
+    }
+
+  return APR_SUCCESS;
+}
+
+svn_error_t *
+svn_io__win_delete_file_on_close(apr_file_t *file,
+                                 const char *path,
+                                 apr_pool_t *pool)
+{
+  FILE_DISPOSITION_INFO disposition_info;
+  HANDLE hFile;
+  apr_status_t status;
+
+  apr_os_file_get(&hFile, file);
+
+  disposition_info.DeleteFile = TRUE;
+
+  status = win32_set_file_information_by_handle(hFile, FileDispositionInfo,
+                                                &disposition_info,
+                                                sizeof(disposition_info));
+
+  if (status)
+    {
+      return svn_error_wrap_apr(status, _("Can't remove file '%s'"),
+                                svn_dirent_local_style(path, pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
+svn_error_t *
+svn_io__win_rename_open_file(apr_file_t *file,
+                             const char *from_path,
+                             const char *to_path,
+                             apr_pool_t *pool)
+{
+  WCHAR *w_final_abspath;
+  size_t path_len;
+  size_t rename_size;
+  FILE_RENAME_INFO *rename_info;
+  HANDLE hFile;
+  apr_status_t status;
+
+  apr_os_file_get(&hFile, file);
+
+  SVN_ERR(svn_io__utf8_to_unicode_longpath(
+            &w_final_abspath, svn_dirent_local_style(to_path,pool),
+            pool));
+
+  path_len = wcslen(w_final_abspath);
+  rename_size = sizeof(*rename_info) + sizeof(WCHAR) * path_len;
+
+  /* The rename info struct doesn't need hacks for long paths,
+     so no ugly escaping calls here */
+  rename_info = apr_pcalloc(pool, rename_size);
+  rename_info->ReplaceIfExists = TRUE;
+  rename_info->FileNameLength = path_len;
+  memcpy(rename_info->FileName, w_final_abspath, path_len * sizeof(WCHAR));
+
+  status = win32_set_file_information_by_handle(hFile, FileRenameInfo,
+                                                rename_info,
+                                                rename_size);
+
+  if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status))
+    {
+      /* Set the destination file writable because Windows will not allow
+         us to rename when final_abspath is read-only. */
+      SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool));
+
+      status = win32_set_file_information_by_handle(hFile,
+                                                    FileRenameInfo,
+                                                    rename_info,
+                                                    rename_size);
+   }
+
+  /* Windows returns Vista+ client accessing network share stored on Windows
+     Server 2003 returns ERROR_ACCESS_DENIED. The same happens when Vista+
+     client access Windows Server 2008 with disabled SMBv2 protocol.
+
+     So return SVN_ERR_UNSUPPORTED_FEATURE in this case like we do when
+     SetFileInformationByHandle() is not available and let caller to
+     handle it.
+
+     See "Access denied error on checkout-commit after updating to 1.9.X"
+     discussion on dev@s.a.o:
+     http://svn.haxx.se/dev/archive-2015-09/0054.shtml */
+  if (status == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED))
+    {
+      status = SVN_ERR_UNSUPPORTED_FEATURE;
+    }
+
+  if (status)
+    {
+      return svn_error_wrap_apr(status, _("Can't move '%s' to '%s'"),
+                                svn_dirent_local_style(from_path, pool),
+                                svn_dirent_local_style(to_path, pool));
+    }
+
+  return SVN_NO_ERROR;
+}
+
 #endif /* WIN32 */
 
 svn_error_t *
@@ -2118,7 +2278,6 @@ svn_io_is_file_executable(svn_boolean_t
 
 
 /*** File locking. ***/
-#if !defined(WIN32) && !defined(__OS2__)
 /* Clear all outstanding locks on ARG, an open apr_file_t *. */
 static apr_status_t
 file_clear_locks(void *arg)
@@ -2133,7 +2292,6 @@ file_clear_locks(void *arg)
 
   return 0;
 }
-#endif
 
 svn_error_t *
 svn_io_lock_open_file(apr_file_t *lockfile_handle,
@@ -2191,13 +2349,14 @@ svn_io_lock_open_file(apr_file_t *lockfi
         }
     }
 
-/* On Windows and OS/2 file locks are automatically released when
-   the file handle closes */
-#if !defined(WIN32) && !defined(__OS2__)
+  /* On Windows, a process may not release file locks before closing the
+     handle, and in this case the outstanding locks are unlocked by the OS.
+     However, this is not recommended, because the actual unlocking may be
+     postponed depending on available system resources.  We explicitly unlock
+     the file as a part of the pool cleanup handler. */
   apr_pool_cleanup_register(pool, lockfile_handle,
                             file_clear_locks,
                             apr_pool_cleanup_null);
-#endif
 
   return SVN_NO_ERROR;
 }
@@ -2221,11 +2380,7 @@ svn_io_unlock_open_file(apr_file_t *lock
     return svn_error_wrap_apr(apr_err, _("Can't unlock file '%s'"),
                               try_utf8_from_internal_style(fname, pool));
 
-/* On Windows and OS/2 file locks are automatically released when
-   the file handle closes */
-#if !defined(WIN32) && !defined(__OS2__)
   apr_pool_cleanup_kill(pool, lockfile_handle, file_clear_locks);
-#endif
 
   return SVN_NO_ERROR;
 }
@@ -2299,6 +2454,14 @@ svn_error_t *svn_io_file_flush_to_disk(a
                                        apr_pool_t *pool)
 {
   apr_os_file_t filehand;
+  const char *fname;
+  apr_status_t apr_err;
+
+  /* We need this only in case of an error but this is cheap to get -
+   * so we do it here for clarity. */
+  apr_err = apr_file_name_get(&fname, file);
+  if (apr_err)
+    return svn_error_wrap_apr(apr_err, _("Can't get file name"));
 
   /* ### In apr 1.4+ we could delegate most of this function to
          apr_file_sync(). The only major difference is that this doesn't
@@ -2316,7 +2479,8 @@ svn_error_t *svn_io_file_flush_to_disk(a
 
     if (! FlushFileBuffers(filehand))
         return svn_error_wrap_apr(apr_get_os_error(),
-                                  _("Can't flush file to disk"));
+                                  _("Can't flush file '%s' to disk"),
+                                  try_utf8_from_internal_style(fname, pool));
 
 #else
       int rv;
@@ -2337,7 +2501,8 @@ svn_error_t *svn_io_file_flush_to_disk(a
 
       if (rv == -1)
         return svn_error_wrap_apr(apr_get_os_error(),
-                                  _("Can't flush file to disk"));
+                                  _("Can't flush file '%s' to disk"),
+                                  try_utf8_from_internal_style(fname, pool));
 
 #endif
   }
@@ -2565,7 +2730,7 @@ svn_io_remove_dir2(const char *path, svn
      If we need to bail out, do so early. */
 
   if (cancel_func)
-    SVN_ERR((*cancel_func)(cancel_baton));
+    SVN_ERR(cancel_func(cancel_baton));
 
   subpool = svn_pool_create(pool);
 
@@ -2598,7 +2763,7 @@ svn_io_remove_dir2(const char *path, svn
       else
         {
           if (cancel_func)
-            SVN_ERR((*cancel_func)(cancel_baton));
+            SVN_ERR(cancel_func(cancel_baton));
 
           err = svn_io_remove_file2(fullpath, FALSE, subpool);
           if (err)
@@ -3580,6 +3745,16 @@ svn_io_file_info_get(apr_finfo_t *finfo,
              pool);
 }
 
+svn_error_t *
+svn_io_file_size_get(svn_filesize_t *filesize_p, apr_file_t *file,
+                     apr_pool_t *pool)
+{
+  apr_finfo_t finfo;
+  SVN_ERR(svn_io_file_info_get(&finfo, APR_FINFO_SIZE, file, pool));
+
+  *filesize_p = finfo.size;
+  return SVN_NO_ERROR;
+}
 
 svn_error_t *
 svn_io_file_read(apr_file_t *file, void *buf,
@@ -3633,7 +3808,7 @@ svn_io_file_aligned_seek(apr_file_t *fil
                          apr_off_t block_size,
                          apr_off_t *buffer_start,
                          apr_off_t offset,
-                         apr_pool_t *pool)
+                         apr_pool_t *scratch_pool)
 {
   const apr_size_t apr_default_buffer_size = 4096;
   apr_size_t file_buffer_size = apr_default_buffer_size;
@@ -3683,7 +3858,7 @@ svn_io_file_aligned_seek(apr_file_t *fil
          buffer and no I/O will actually happen in the FILL_BUFFER
          section below.
        */
-      SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, pool));
+      SVN_ERR(svn_io_file_seek(file, APR_CUR, &current, scratch_pool));
       fill_buffer = aligned_offset + file_buffer_size <= current
                  || current <= aligned_offset;
     }
@@ -3694,7 +3869,8 @@ svn_io_file_aligned_seek(apr_file_t *fil
       apr_status_t status;
 
       /* seek to the start of the block and cause APR to read 1 block */
-      SVN_ERR(svn_io_file_seek(file, APR_SET, &aligned_offset, pool));
+      SVN_ERR(svn_io_file_seek(file, APR_SET, &aligned_offset,
+                               scratch_pool));
       status = apr_file_getc(&dummy, file);
 
       /* read may fail if we seek to or behind EOF.  That's ok then. */
@@ -3702,17 +3878,17 @@ svn_io_file_aligned_seek(apr_file_t *fil
         return do_io_file_wrapper_cleanup(file, status,
                                           N_("Can't read file '%s'"),
                                           N_("Can't read stream"),
-                                          pool);
+                                          scratch_pool);
     }
 
   /* finally, seek to the OFFSET the caller wants */
   desired_offset = offset;
-  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, pool));
+  SVN_ERR(svn_io_file_seek(file, APR_SET, &offset, scratch_pool));
   if (desired_offset != offset)
     return do_io_file_wrapper_cleanup(file, APR_EOF,
                                       N_("Can't seek in file '%s'"),
                                       N_("Can't seek in stream"),
-                                      pool);
+                                      scratch_pool);
 
   /* return the buffer start that we (probably) enforced */
   if (buffer_start)
@@ -3824,11 +4000,12 @@ svn_io_write_unique(const char **tmp_pat
 }
 
 svn_error_t *
-svn_io_write_atomic(const char *final_path,
-                    const void *buf,
-                    apr_size_t nbytes,
-                    const char *copy_perms_path,
-                    apr_pool_t *scratch_pool)
+svn_io_write_atomic2(const char *final_path,
+                     const void *buf,
+                     apr_size_t nbytes,
+                     const char *copy_perms_path,
+                     svn_boolean_t flush_to_disk,
+                     apr_pool_t *scratch_pool)
 {
   apr_file_t *tmp_file;
   const char *tmp_path;
@@ -3841,7 +4018,7 @@ svn_io_write_atomic(const char *final_pa
 
   err = svn_io_file_write_full(tmp_file, buf, nbytes, NULL, scratch_pool);
 
-  if (!err)
+  if (!err && flush_to_disk)
     err = svn_io_file_flush_to_disk(tmp_file, scratch_pool);
 
   err = svn_error_compose_create(err,
@@ -3851,7 +4028,8 @@ svn_io_write_atomic(const char *final_pa
     err = svn_io_copy_perms(copy_perms_path, tmp_path, scratch_pool);
 
   if (!err)
-    err = svn_io_file_rename(tmp_path, final_path, scratch_pool);
+    err = svn_io_file_rename2(tmp_path, final_path, flush_to_disk,
+                              scratch_pool);
 
   if (err)
     {
@@ -3865,22 +4043,6 @@ svn_io_write_atomic(const char *final_pa
                                                       scratch_pool));
     }
 
-#ifdef __linux__
-  {
-    /* Linux has the unusual feature that fsync() on a file is not
-       enough to ensure that a file's directory entries have been
-       flushed to disk; you have to fsync the directory as well.
-       On other operating systems, we'd only be asking for trouble
-       by trying to open and fsync a directory. */
-    apr_file_t *file;
-
-    SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT,
-                             scratch_pool));
-    SVN_ERR(svn_io_file_flush_to_disk(file, scratch_pool));
-    SVN_ERR(svn_io_file_close(file, scratch_pool));
-  }
-#endif
-
   return SVN_NO_ERROR;
 }
 
@@ -4002,20 +4164,53 @@ svn_io_stat(apr_finfo_t *finfo, const ch
   return SVN_NO_ERROR;
 }
 
+#if defined(WIN32)
+/* Platform specific implementation of apr_file_rename() to workaround
+   APR problems on Windows. */
+static apr_status_t
+win32_file_rename(const WCHAR *from_path_w,
+                  const WCHAR *to_path_w,
+                  svn_boolean_t flush_to_disk)
+{
+  /* APR calls MoveFileExW() with MOVEFILE_COPY_ALLOWED, while we rely
+   * that rename is atomic operation. Call MoveFileEx directly on Windows
+   * without MOVEFILE_COPY_ALLOWED flag to workaround it.
+   */
+
+  DWORD flags = MOVEFILE_REPLACE_EXISTING;
+
+  if (flush_to_disk)
+    {
+      /* Do not return until the file has actually been moved on the disk. */
+      flags |= MOVEFILE_WRITE_THROUGH;
+    }
+
+  if (!MoveFileExW(from_path_w, to_path_w, flags))
+      return apr_get_os_error();
+
+  return APR_SUCCESS;
+}
+#endif
 
 svn_error_t *
-svn_io_file_rename(const char *from_path, const char *to_path,
-                   apr_pool_t *pool)
+svn_io_file_rename2(const char *from_path, const char *to_path,
+                    svn_boolean_t flush_to_disk, apr_pool_t *pool)
 {
   apr_status_t status = APR_SUCCESS;
   const char *from_path_apr, *to_path_apr;
+#if defined(WIN32)
+  WCHAR *from_path_w;
+  WCHAR *to_path_w;
+#endif
 
   SVN_ERR(cstring_from_utf8(&from_path_apr, from_path, pool));
   SVN_ERR(cstring_from_utf8(&to_path_apr, to_path, pool));
 
-  status = apr_file_rename(from_path_apr, to_path_apr, pool);
+#if defined(WIN32)
+  SVN_ERR(svn_io__utf8_to_unicode_longpath(&from_path_w, from_path_apr, pool));
+  SVN_ERR(svn_io__utf8_to_unicode_longpath(&to_path_w, to_path_apr, pool));
+  status = win32_file_rename(from_path_w, to_path_w, flush_to_disk);
 
-#if defined(WIN32) || defined(__OS2__)
   /* If the target file is read only NTFS reports EACCESS and
      FAT/FAT32 reports EEXIST */
   if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status))
@@ -4025,9 +4220,25 @@ svn_io_file_rename(const char *from_path
          allow renaming when from_path is read only. */
       SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool));
 
+      status = win32_file_rename(from_path_w, to_path_w, flush_to_disk);
+    }
+  WIN32_RETRY_LOOP(status, win32_file_rename(from_path_w, to_path_w,
+                                             flush_to_disk));
+#elif defined(__OS2__)
+  status = apr_file_rename(from_path_apr, to_path_apr, pool);
+  /* If the target file is read only NTFS reports EACCESS and
+     FAT/FAT32 reports EEXIST */
+  if (APR_STATUS_IS_EACCES(status) || APR_STATUS_IS_EEXIST(status))
+    {
+      /* Set the destination file writable because OS/2 will not
+         allow us to rename when to_path is read-only, but will
+         allow renaming when from_path is read only. */
+      SVN_ERR(svn_io_set_file_read_write(to_path, TRUE, pool));
+
       status = apr_file_rename(from_path_apr, to_path_apr, pool);
     }
-  WIN32_RETRY_LOOP(status, apr_file_rename(from_path_apr, to_path_apr, pool));
+#else
+  status = apr_file_rename(from_path_apr, to_path_apr, pool);
 #endif /* WIN32 || __OS2__ */
 
   if (status)
@@ -4035,6 +4246,34 @@ svn_io_file_rename(const char *from_path
                               svn_dirent_local_style(from_path, pool),
                               svn_dirent_local_style(to_path, pool));
 
+#if defined(SVN_ON_POSIX)
+  if (flush_to_disk)
+    {
+      /* On POSIX, the file name is stored in the file's directory entry.
+         Hence, we need to fsync() that directory as well.
+         On other operating systems, we'd only be asking for trouble
+         by trying to open and fsync a directory. */
+      const char *dirname;
+      apr_file_t *file;
+
+      dirname = svn_dirent_dirname(to_path, pool);
+      SVN_ERR(svn_io_file_open(&file, dirname, APR_READ, APR_OS_DEFAULT,
+                               pool));
+      SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+      SVN_ERR(svn_io_file_close(file, pool));
+    }
+#elif !defined(WIN32)
+  /* Flush the target of the rename to disk. */
+  if (flush_to_disk)
+    {
+      apr_file_t *file;
+      SVN_ERR(svn_io_file_open(&file, to_path, APR_WRITE,
+                               APR_OS_DEFAULT, pool));
+      SVN_ERR(svn_io_file_flush_to_disk(file, pool));
+      SVN_ERR(svn_io_file_close(file, pool));
+    }
+#endif
+
   return SVN_NO_ERROR;
 }
 
@@ -4043,37 +4282,16 @@ svn_error_t *
 svn_io_file_move(const char *from_path, const char *to_path,
                  apr_pool_t *pool)
 {
-  svn_error_t *err = svn_io_file_rename(from_path, to_path, pool);
+  svn_error_t *err = svn_error_trace(svn_io_file_rename2(from_path, to_path,
+                                                         FALSE, pool));
 
   if (err && APR_STATUS_IS_EXDEV(err->apr_err))
     {
-      const char *tmp_to_path;
-
       svn_error_clear(err);
 
-      SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_to_path,
-                                       svn_dirent_dirname(to_path, pool),
-                                       svn_io_file_del_none,
-                                       pool, pool));
-
-      err = svn_io_copy_file(from_path, tmp_to_path, TRUE, pool);
-      if (err)
-        goto failed_tmp;
-
-      err = svn_io_file_rename(tmp_to_path, to_path, pool);
-      if (err)
-        goto failed_tmp;
-
-      err = svn_io_remove_file2(from_path, FALSE, pool);
-      if (! err)
-        return SVN_NO_ERROR;
-
-      svn_error_clear(svn_io_remove_file2(to_path, FALSE, pool));
-
-      return err;
-
-    failed_tmp:
-      svn_error_clear(svn_io_remove_file2(tmp_to_path, FALSE, pool));
+      /* svn_io_copy_file() performs atomic copy via temporary file. */
+      err = svn_error_trace(svn_io_copy_file(from_path, to_path, TRUE,
+                                             pool));
     }
 
   return err;
@@ -4225,8 +4443,8 @@ svn_io_dir_remove_nonrecursive(const cha
   {
     svn_boolean_t retry = TRUE;
 
-    if (APR_TO_OS_ERROR(status) == ERROR_DIR_NOT_EMPTY)
-      {
+    if (status == APR_FROM_OS_ERROR(ERROR_DIR_NOT_EMPTY))
+    {
         apr_status_t empty_status = dir_is_empty(dirname_apr, pool);
 
         if (APR_STATUS_IS_ENOTEMPTY(empty_status))
@@ -4505,7 +4723,7 @@ svn_io_write_version_file(const char *pa
 #endif /* WIN32 || __OS2__ */
 
   /* rename the temp file as the real destination */
-  SVN_ERR(svn_io_file_rename(path_tmp, path, pool));
+  SVN_ERR(svn_io_file_rename2(path_tmp, path, FALSE, pool));
 
   /* And finally remove the perms to make it read only */
   return svn_io_set_file_read_only(path, FALSE, pool);
@@ -4902,7 +5120,7 @@ temp_file_create(apr_file_t **new_file,
 
       /* 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
+         through this loop. (A bit of calculation is much cheaper than
          disk io) */
       unique_nr = baseNr + 3 * i;
 
@@ -4933,10 +5151,8 @@ temp_file_create(apr_file_t **new_file,
               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)
+              if (apr_err == APR_FROM_OS_ERROR(ERROR_ACCESS_DENIED) ||
+                  apr_err == APR_FROM_OS_ERROR(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
@@ -5070,7 +5286,8 @@ svn_io_open_unique_file3(apr_file_t **fi
     {
       svn_error_t *err;
 
-      SVN_ERR(merge_default_file_perms(tempfile, &perms, scratch_pool));
+      SVN_ERR(merge_default_file_perms(tempfile, &perms, dirpath,
+                                       scratch_pool));
       err = file_perms_set2(tempfile, perms, scratch_pool);
       if (err)
         {

Modified: subversion/branches/ra-git/subversion/libsvn_subr/mergeinfo.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/mergeinfo.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/mergeinfo.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/mergeinfo.c Mon Nov 30 10:24:16 2015
@@ -2306,8 +2306,7 @@ svn_rangelist_dup(const svn_rangelist_t
 svn_merge_range_t *
 svn_merge_range_dup(const svn_merge_range_t *range, apr_pool_t *pool)
 {
-  svn_merge_range_t *new_range = apr_palloc(pool, sizeof(*new_range));
-  memcpy(new_range, range, sizeof(*new_range));
+  svn_merge_range_t *new_range = apr_pmemdup(pool, range, sizeof(*new_range));
   return new_range;
 }
 
@@ -2360,7 +2359,7 @@ svn_mergeinfo__catalog_to_formatted_stri
           svn_stringbuf_appendcstr(output_buf, "\n");
         }
     }
-#if SVN_DEBUG
+#ifdef SVN_DEBUG
   else if (!catalog)
     {
       output_buf = svn_stringbuf_create(key_prefix ? key_prefix : "", pool);

Modified: subversion/branches/ra-git/subversion/libsvn_subr/mutex.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/mutex.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/mutex.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/mutex.c Mon Nov 30 10:24:16 2015
@@ -105,3 +105,13 @@ svn_mutex__unlock(svn_mutex__t *mutex,
 
   return err;
 }
+
+#if APR_HAS_THREADS
+
+apr_thread_mutex_t *
+svn_mutex__get(svn_mutex__t *mutex)
+{
+  return mutex->mutex;
+}
+
+#endif

Modified: subversion/branches/ra-git/subversion/libsvn_subr/opt.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/opt.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/opt.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/opt.c Mon Nov 30 10:24:16 2015
@@ -350,41 +350,50 @@ print_command_info2(const svn_opt_subcom
   return SVN_NO_ERROR;
 }
 
-void
-svn_opt_print_generic_help2(const char *header,
-                            const svn_opt_subcommand_desc2_t *cmd_table,
-                            const apr_getopt_option_t *opt_table,
-                            const char *footer,
-                            apr_pool_t *pool, FILE *stream)
+/* The body for svn_opt_print_generic_help2() function with standard error
+ * handling semantic. Handling of errors implemented at caller side. */
+static svn_error_t *
+print_generic_help_body(const char *header,
+                        const svn_opt_subcommand_desc2_t *cmd_table,
+                        const apr_getopt_option_t *opt_table,
+                        const char *footer,
+                        apr_pool_t *pool, FILE *stream)
 {
   int i = 0;
-  svn_error_t *err;
 
   if (header)
-    if ((err = svn_cmdline_fputs(header, stream, pool)))
-      goto print_error;
+    SVN_ERR(svn_cmdline_fputs(header, stream, pool));
 
   while (cmd_table[i].name)
     {
-      if ((err = svn_cmdline_fputs("   ", stream, pool))
-          || (err = print_command_info2(cmd_table + i, opt_table,
-                                        NULL, FALSE,
-                                        pool, stream))
-          || (err = svn_cmdline_fputs("\n", stream, pool)))
-        goto print_error;
+      SVN_ERR(svn_cmdline_fputs("   ", stream, pool));
+      SVN_ERR(print_command_info2(cmd_table + i, opt_table,
+                                  NULL, FALSE,
+                                  pool, stream));
+      SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
       i++;
     }
 
-  if ((err = svn_cmdline_fputs("\n", stream, pool)))
-    goto print_error;
+  SVN_ERR(svn_cmdline_fputs("\n", stream, pool));
 
   if (footer)
-    if ((err = svn_cmdline_fputs(footer, stream, pool)))
-      goto print_error;
+    SVN_ERR(svn_cmdline_fputs(footer, stream, pool));
+
+  return SVN_NO_ERROR;
+}
+
+void
+svn_opt_print_generic_help2(const char *header,
+                            const svn_opt_subcommand_desc2_t *cmd_table,
+                            const apr_getopt_option_t *opt_table,
+                            const char *footer,
+                            apr_pool_t *pool, FILE *stream)
+{
+  svn_error_t *err;
 
-  return;
+  err = print_generic_help_body(header, cmd_table, opt_table, footer, pool,
+                                stream);
 
- print_error:
   /* Issue #3014:
    * Don't print anything on broken pipes. The pipe was likely
    * closed by the process at the other end. We expect that
@@ -392,7 +401,7 @@ svn_opt_print_generic_help2(const char *
    *
    * ### This assumes that there is only one error in a chain for
    * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
-  if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
+  if (err && err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
     svn_handle_error2(err, stderr, FALSE, "svn: ");
   svn_error_clear(err);
 }

Modified: subversion/branches/ra-git/subversion/libsvn_subr/packed_data.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/packed_data.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/packed_data.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/packed_data.c Mon Nov 30 10:24:16 2015
@@ -308,7 +308,7 @@ unmap_uint(apr_uint64_t value)
  * are no sub-streams).
  */
 static void
-svn_packed__data_flush_buffer(svn_packed__int_stream_t *stream)
+data_flush_buffer(svn_packed__int_stream_t *stream)
 {
   packed_int_private_t *private_data = stream->private_data;
   apr_size_t i;
@@ -382,7 +382,7 @@ svn_packed__add_uint(svn_packed__int_str
 {
   stream->buffer[stream->buffer_used] = value;
   if (++stream->buffer_used == SVN__PACKED_DATA_BUFFER_SIZE)
-    svn_packed__data_flush_buffer(stream);
+    data_flush_buffer(stream);
 }
 
 void
@@ -435,7 +435,7 @@ write_int_stream_structure(svn_stringbuf
                                    + (private_data->is_signed ? 2 : 0));
 
       /* store item count and length their of packed representation */
-      svn_packed__data_flush_buffer(stream);
+      data_flush_buffer(stream);
 
       write_packed_uint(tree_struct, private_data->item_count);
       write_packed_uint(tree_struct, private_data->packed
@@ -561,7 +561,7 @@ write_stream_data(svn_stream_t *stream,
                   svn_stringbuf_t *uncompressed,
                   svn_stringbuf_t *compressed)
 {
-  SVN_ERR(svn__compress(uncompressed,
+  SVN_ERR(svn__compress(uncompressed->data, uncompressed->len,
                         compressed,
                         SVN_DELTA_COMPRESSION_LEVEL_DEFAULT));
 
@@ -972,7 +972,8 @@ read_stream_data(svn_stream_t *stream,
   SVN_ERR(svn_stream_read_full(stream, compressed->data, &compressed->len));
   compressed->data[compressed_len] = '\0';
 
-  SVN_ERR(svn__decompress(compressed, uncompressed, uncompressed_len));
+  SVN_ERR(svn__decompress(compressed->data, compressed->len,
+                          uncompressed, uncompressed_len));
 
   return SVN_NO_ERROR;
 }

Modified: subversion/branches/ra-git/subversion/libsvn_subr/path.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/path.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/path.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/path.c Mon Nov 30 10:24:16 2015
@@ -910,9 +910,24 @@ uri_escape(const char *path, const char
   svn_stringbuf_t *retstr;
   apr_size_t i, copied = 0;
   int c;
+  apr_size_t len;
+  const char *p;
 
-  retstr = svn_stringbuf_create_ensure(strlen(path), pool);
-  for (i = 0; path[i]; i++)
+  /* To terminate our scanning loop, table[NUL] must report "invalid". */
+  assert(table[0] == 0);
+
+  /* Quick check: Does any character need escaping? */
+  for (p = path; table[(unsigned char)*p]; ++p)
+    {}
+
+  /* No char to escape before EOS? */
+  if (*p == '\0')
+    return path;
+
+  /* We need to escape at least one character. */
+  len = strlen(p) + (p - path);
+  retstr = svn_stringbuf_create_ensure(len, pool);
+  for (i = p - path; i < len; i++)
     {
       c = (unsigned char)path[i];
       if (table[c])
@@ -941,10 +956,6 @@ uri_escape(const char *path, const char
       copied = i + 1;
     }
 
-  /* If we didn't encode anything, we don't need to duplicate the string. */
-  if (retstr->len == 0)
-    return path;
-
   /* Anything left to copy? */
   if (i - copied)
     svn_stringbuf_appendbytes(retstr, path + copied, i - copied);
@@ -971,7 +982,7 @@ svn_path_uri_encode(const char *path, ap
 }
 
 static const char iri_escape_chars[256] = {
-  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+  0, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
@@ -998,7 +1009,7 @@ svn_path_uri_from_iri(const char *iri, a
 }
 
 static const char uri_autoescape_chars[256] = {
-  1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
+  0, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
   0, 1, 0, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
   1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 0, 1, 0, 1,

Modified: subversion/branches/ra-git/subversion/libsvn_subr/pool.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/pool.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/pool.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/pool.c Mon Nov 30 10:24:16 2015
@@ -30,7 +30,6 @@
 #include <apr_version.h>
 #include <apr_general.h>
 #include <apr_pools.h>
-#include <apr_thread_mutex.h>
 
 #include "svn_pools.h"
 

Modified: subversion/branches/ra-git/subversion/libsvn_subr/prefix_string.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/prefix_string.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/prefix_string.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/prefix_string.c Mon Nov 30 10:24:16 2015
@@ -228,7 +228,7 @@ svn_prefix_string__create(svn_prefix_tre
     }
 
   /* add sub-node(s) and final string */
-  while (node->length + 7 < len)
+  while (len - node->length > 7)
     {
       new_node = apr_pcalloc(tree->pool, sizeof(*new_node));
       new_node->key.prefix = node;

Modified: subversion/branches/ra-git/subversion/libsvn_subr/properties.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/properties.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/properties.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/properties.c Mon Nov 30 10:24:16 2015
@@ -131,7 +131,6 @@ svn_boolean_t
 svn_prop_has_svn_prop(const apr_hash_t *props, apr_pool_t *pool)
 {
   apr_hash_index_t *hi;
-  const void *prop_name;
 
   if (! props)
     return FALSE;
@@ -139,8 +138,9 @@ svn_prop_has_svn_prop(const apr_hash_t *
   for (hi = apr_hash_first(pool, (apr_hash_t *)props); hi;
        hi = apr_hash_next(hi))
     {
-      apr_hash_this(hi, &prop_name, NULL, NULL);
-      if (svn_prop_is_svn_prop((const char *) prop_name))
+      const char *prop_name = apr_hash_this_key(hi);
+
+      if (svn_prop_is_svn_prop(prop_name))
         return TRUE;
     }
 

Modified: subversion/branches/ra-git/subversion/libsvn_subr/skel.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/skel.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/skel.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/skel.c Mon Nov 30 10:24:16 2015
@@ -380,7 +380,7 @@ explicit_atom(const char *data,
   data++;
 
   /* Check the length.  */
-  if (data + size > end)
+  if (end - data < size)
     return NULL;
 
   /* Allocate the skel representing this string.  */

Modified: subversion/branches/ra-git/subversion/libsvn_subr/sorts.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/sorts.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/sorts.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/sorts.c Mon Nov 30 10:24:16 2015
@@ -333,7 +333,7 @@ svn_sort__array_delete(apr_array_header_
   if (delete_index >= 0
       && delete_index < arr->nelts
       && elements_to_delete > 0
-      && (elements_to_delete + delete_index) <= arr->nelts)
+      && (arr->nelts - delete_index) >= elements_to_delete)
     {
       /* If we are not deleting a block of elements that extends to the end
          of the array, then we need to move the remaining elements to keep

Modified: subversion/branches/ra-git/subversion/libsvn_subr/spillbuf.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/spillbuf.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/spillbuf.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/spillbuf.c Mon Nov 30 10:24:16 2015
@@ -242,7 +242,7 @@ svn_spillbuf__write(svn_spillbuf_t *buf,
      will grow too large. Create the file and place the pending data into
      the temporary file.  */
   if (buf->spill == NULL
-      && (buf->memory_size + len) > buf->maxsize)
+      && ((buf->maxsize - buf->memory_size) < len))
     {
       SVN_ERR(svn_io_open_unique_file3(&buf->spill,
                                        &buf->filename,

Modified: subversion/branches/ra-git/subversion/libsvn_subr/sqlite.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/sqlite.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/sqlite.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/sqlite.c Mon Nov 30 10:24:16 2015
@@ -1171,6 +1171,7 @@ svn_sqlite__open(svn_sqlite__db_t **db,
                  affects application(read: Subversion) performance/behavior. */
               "PRAGMA foreign_keys=OFF;"      /* SQLITE_DEFAULT_FOREIGN_KEYS*/
               "PRAGMA locking_mode = NORMAL;" /* SQLITE_DEFAULT_LOCKING_MODE */
+              /* Testing shows TRUNCATE is faster than DELETE on Windows. */
               "PRAGMA journal_mode = TRUNCATE;"
               ),
                 *db);

Modified: subversion/branches/ra-git/subversion/libsvn_subr/stream.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/stream.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/stream.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/stream.c Mon Nov 30 10:24:16 2015
@@ -42,6 +42,7 @@
 #include "svn_checksum.h"
 #include "svn_path.h"
 #include "svn_private_config.h"
+#include "svn_sorts.h"
 #include "private/svn_atomic.h"
 #include "private/svn_error_private.h"
 #include "private/svn_eol_private.h"
@@ -197,8 +198,15 @@ svn_error_t *
 svn_stream_skip(svn_stream_t *stream, apr_size_t len)
 {
   if (stream->skip_fn == NULL)
-    return svn_error_trace(
-            skip_default_handler(stream->baton, len, stream->read_full_fn));
+    {
+      svn_read_fn_t read_fn = stream->read_full_fn ? stream->read_full_fn
+                                                   : stream->read_fn;
+      if (read_fn == NULL)
+        return svn_error_create(SVN_ERR_STREAM_NOT_SUPPORTED, NULL, NULL);
+
+      return svn_error_trace(skip_default_handler(stream->baton, len,
+                                                  read_fn));
+    }
 
   return svn_error_trace(stream->skip_fn(stream->baton, len));
 }
@@ -938,8 +946,9 @@ static svn_error_t *
 data_available_handler_apr(void *baton, svn_boolean_t *data_available)
 {
   struct baton_apr *btn = baton;
-  apr_pollfd_t pfd;
   apr_status_t status;
+#if !defined(WIN32) || APR_FILES_AS_SOCKETS
+  apr_pollfd_t pfd;
   int n;
 
   pfd.desc_type = APR_POLL_FILE;
@@ -969,6 +978,24 @@ data_available_handler_apr(void *baton,
                                     "failed")),
                               NULL);
     }
+#else
+  HANDLE h;
+  DWORD dwAvail;
+  status = apr_os_file_get(&h, btn->file);
+
+  if (status)
+    return svn_error_wrap_apr(status, NULL);
+
+  if (PeekNamedPipe(h, NULL, 0, NULL, &dwAvail, NULL))
+    {
+      *data_available = (dwAvail > 0);
+      return SVN_NO_ERROR;
+    }
+
+  return svn_error_create(SVN_ERR_STREAM_NOT_SUPPORTED,
+                          svn_error_wrap_apr(apr_get_os_error(), NULL),
+                          _("Windows doesn't support polling on files"));
+#endif
 }
 
 static svn_boolean_t
@@ -1032,10 +1059,12 @@ svn_stream_open_unique(svn_stream_t **st
 }
 
 
-svn_stream_t *
-svn_stream_from_aprfile2(apr_file_t *file,
-                         svn_boolean_t disown,
-                         apr_pool_t *pool)
+/* Helper function that creates a stream from an APR file. */
+static svn_stream_t *
+make_stream_from_apr_file(apr_file_t *file,
+                          svn_boolean_t disown,
+                          svn_boolean_t supports_seek,
+                          apr_pool_t *pool)
 {
   struct baton_apr *baton;
   svn_stream_t *stream;
@@ -1049,9 +1078,14 @@ svn_stream_from_aprfile2(apr_file_t *fil
   stream = svn_stream_create(baton, pool);
   svn_stream_set_read2(stream, read_handler_apr, read_full_handler_apr);
   svn_stream_set_write(stream, write_handler_apr);
-  svn_stream_set_skip(stream, skip_handler_apr);
-  svn_stream_set_mark(stream, mark_handler_apr);
-  svn_stream_set_seek(stream, seek_handler_apr);
+
+  if (supports_seek)
+    {
+      svn_stream_set_skip(stream, skip_handler_apr);
+      svn_stream_set_mark(stream, mark_handler_apr);
+      svn_stream_set_seek(stream, seek_handler_apr);
+    }
+
   svn_stream_set_data_available(stream, data_available_handler_apr);
   svn_stream__set_is_buffered(stream, is_buffered_handler_apr);
   stream->file = file;
@@ -1062,6 +1096,14 @@ svn_stream_from_aprfile2(apr_file_t *fil
   return stream;
 }
 
+svn_stream_t *
+svn_stream_from_aprfile2(apr_file_t *file,
+                         svn_boolean_t disown,
+                         apr_pool_t *pool)
+{
+  return make_stream_from_apr_file(file, disown, TRUE, pool);
+}
+
 apr_file_t *
 svn_stream__aprfile(svn_stream_t *stream)
 {
@@ -1439,31 +1481,44 @@ svn_stream_checksummed2(svn_stream_t *st
 
 /* Miscellaneous stream functions. */
 
+/*
+ * [JAF] By considering the buffer size doubling algorithm we use, I think
+ * the performance characteristics of this implementation are as follows:
+ *
+ * When the effective hint is big enough for the actual data, it uses
+ * minimal time and allocates space roughly equal to the effective hint.
+ * Otherwise, it incurs a time overhead for copying an additional 1x to 2x
+ * the actual length of data, and a space overhead of an additional 2x to
+ * 3x the actual length.
+ */
 svn_error_t *
-svn_stringbuf_from_stream(svn_stringbuf_t **str,
+svn_stringbuf_from_stream(svn_stringbuf_t **result,
                           svn_stream_t *stream,
                           apr_size_t len_hint,
-                          apr_pool_t *pool)
+                          apr_pool_t *result_pool)
 {
 #define MIN_READ_SIZE 64
-
-  apr_size_t to_read = 0;
   svn_stringbuf_t *text
-    = svn_stringbuf_create_ensure(len_hint ? len_hint : MIN_READ_SIZE, pool);
+    = svn_stringbuf_create_ensure(MAX(len_hint + 1, MIN_READ_SIZE),
+                                  result_pool);
 
-  do
+  while(TRUE)
     {
-      to_read = text->blocksize - 1 - text->len;
-      SVN_ERR(svn_stream_read_full(stream, text->data + text->len, &to_read));
-      text->len += to_read;
+      apr_size_t to_read = text->blocksize - 1 - text->len;
+      apr_size_t actually_read = to_read;
+
+      SVN_ERR(svn_stream_read_full(stream, text->data + text->len, &actually_read));
+      text->len += actually_read;
+
+      if (actually_read < to_read)
+        break;
 
-      if (to_read && text->blocksize < text->len + MIN_READ_SIZE)
+      if (text->blocksize < text->len + MIN_READ_SIZE)
         svn_stringbuf_ensure(text, text->blocksize * 2);
     }
-  while (to_read);
 
   text->data[text->len] = '\0';
-  *str = text;
+  *result = text;
 
   return SVN_NO_ERROR;
 }
@@ -1688,16 +1743,23 @@ svn_stream_from_string(const svn_string_
 
 
 svn_error_t *
-svn_stream_for_stdin(svn_stream_t **in, apr_pool_t *pool)
+svn_stream_for_stdin2(svn_stream_t **in,
+                      svn_boolean_t buffered,
+                      apr_pool_t *pool)
 {
   apr_file_t *stdin_file;
   apr_status_t apr_err;
 
-  apr_err = apr_file_open_stdin(&stdin_file, pool);
+  apr_uint32_t flags = buffered ? APR_BUFFERED : 0;
+  apr_err = apr_file_open_flags_stdin(&stdin_file, flags, pool);
   if (apr_err)
     return svn_error_wrap_apr(apr_err, "Can't open stdin");
 
-  *in = svn_stream_from_aprfile2(stdin_file, TRUE, pool);
+  /* STDIN may or may not support positioning requests, but generally
+     it does not, or the behavior is implementation-specific.  Hence,
+     we cannot safely advertise mark(), seek() and non-default skip()
+     support. */
+  *in = make_stream_from_apr_file(stdin_file, TRUE, FALSE, pool);
 
   return SVN_NO_ERROR;
 }
@@ -1713,7 +1775,11 @@ svn_stream_for_stdout(svn_stream_t **out
   if (apr_err)
     return svn_error_wrap_apr(apr_err, "Can't open stdout");
 
-  *out = svn_stream_from_aprfile2(stdout_file, TRUE, pool);
+  /* STDOUT may or may not support positioning requests, but generally
+     it does not, or the behavior is implementation-specific.  Hence,
+     we cannot safely advertise mark(), seek() and non-default skip()
+     support. */
+  *out = make_stream_from_apr_file(stdout_file, TRUE, FALSE, pool);
 
   return SVN_NO_ERROR;
 }
@@ -1729,39 +1795,29 @@ svn_stream_for_stderr(svn_stream_t **err
   if (apr_err)
     return svn_error_wrap_apr(apr_err, "Can't open stderr");
 
-  *err = svn_stream_from_aprfile2(stderr_file, TRUE, pool);
+  /* STDERR may or may not support positioning requests, but generally
+     it does not, or the behavior is implementation-specific.  Hence,
+     we cannot safely advertise mark(), seek() and non-default skip()
+     support. */
+  *err = make_stream_from_apr_file(stderr_file, TRUE, FALSE, pool);
 
   return SVN_NO_ERROR;
 }
 
 
 svn_error_t *
-svn_string_from_stream(svn_string_t **result,
-                       svn_stream_t *stream,
-                       apr_pool_t *result_pool,
-                       apr_pool_t *scratch_pool)
+svn_string_from_stream2(svn_string_t **result,
+                        svn_stream_t *stream,
+                        apr_size_t len_hint,
+                        apr_pool_t *result_pool)
 {
-  svn_stringbuf_t *work = svn_stringbuf_create_ensure(SVN__STREAM_CHUNK_SIZE,
-                                                      result_pool);
-  char *buffer = apr_palloc(scratch_pool, SVN__STREAM_CHUNK_SIZE);
-
-  while (1)
-    {
-      apr_size_t len = SVN__STREAM_CHUNK_SIZE;
-
-      SVN_ERR(svn_stream_read_full(stream, buffer, &len));
-      svn_stringbuf_appendbytes(work, buffer, len);
+  svn_stringbuf_t *buf;
 
-      if (len < SVN__STREAM_CHUNK_SIZE)
-        break;
-    }
+  SVN_ERR(svn_stringbuf_from_stream(&buf, stream, len_hint, result_pool));
+  *result = svn_stringbuf__morph_into_string(buf);
 
   SVN_ERR(svn_stream_close(stream));
 
-  *result = apr_palloc(result_pool, sizeof(**result));
-  (*result)->data = work->data;
-  (*result)->len = work->len;
-
   return SVN_NO_ERROR;
 }
 
@@ -1981,48 +2037,6 @@ struct install_baton_t
 
 #ifdef WIN32
 
-#if _WIN32_WINNT < 0x600 /* Does the SDK assume Windows Vista+? */
-typedef struct _FILE_RENAME_INFO {
-  BOOL   ReplaceIfExists;
-  HANDLE RootDirectory;
-  DWORD  FileNameLength;
-  WCHAR  FileName[1];
-} FILE_RENAME_INFO, *PFILE_RENAME_INFO;
-
-typedef struct _FILE_DISPOSITION_INFO {
-  BOOL DeleteFile;
-} FILE_DISPOSITION_INFO, *PFILE_DISPOSITION_INFO;
-
-#define FileRenameInfo 3
-#define FileDispositionInfo 4
-
-typedef BOOL (WINAPI *SetFileInformationByHandle_t)(HANDLE hFile,
-                                                    int FileInformationClass,
-                                                    LPVOID lpFileInformation,
-                                                    DWORD dwBufferSize);
-
-static volatile SetFileInformationByHandle_t SetFileInformationByHandle_p = 0;
-#define SetFileInformationByHandle (*SetFileInformationByHandle_p)
-
-static volatile svn_atomic_t SetFileInformationByHandle_a = 0;
-
-
-static svn_error_t *
-find_SetFileInformationByHandle(void *baton, apr_pool_t *scratch_pool)
-{
-  HMODULE kernel32 = GetModuleHandle("Kernel32.dll");
-
-  if (kernel32)
-    {
-      SetFileInformationByHandle_p =
-                    (SetFileInformationByHandle_t)
-                      GetProcAddress(kernel32, "SetFileInformationByHandle");
-    }
-
-  return SVN_NO_ERROR;
-}
-#endif /* WIN32 < Vista */
-
 /* Create and open a tempfile in DIRECTORY. Return its handle and path */
 static svn_error_t *
 create_tempfile(HANDLE *hFile,
@@ -2091,6 +2105,8 @@ create_tempfile(HANDLE *hFile,
   return SVN_NO_ERROR;
 }
 
+#endif /* WIN32 */
+
 /* Implements svn_close_fn_t */
 static svn_error_t *
 install_close(void *baton)
@@ -2103,8 +2119,6 @@ install_close(void *baton)
   return SVN_NO_ERROR;
 }
 
-#endif /* WIN32 */
-
 svn_error_t *
 svn_stream__create_for_install(svn_stream_t **install_stream,
                                const char *tmp_abspath,
@@ -2127,8 +2141,8 @@ svn_stream__create_for_install(svn_strea
   /* Wrap as a standard APR file to allow sharing implementation.
 
      But do note that some file functions (such as retrieving the name)
-     don't work on this wrapper. */
-  /* ### Buffered, or not? */
+     don't work on this wrapper.
+     Use buffered mode to match svn_io_open_unique_file3() behavior. */
   status = apr_os_file_put(&file, &hInstall,
                            APR_WRITE | APR_BINARY | APR_BUFFERED,
                            result_pool);
@@ -2159,12 +2173,8 @@ svn_stream__create_for_install(svn_strea
 
   ib->tmp_path = tmp_path;
 
-#ifdef WIN32
   /* Don't close the file on stream close; flush instead */
   svn_stream_set_close(*install_stream, install_close);
-#else
-  /* ### Install pool cleanup handler for tempfile? */
-#endif
 
   return SVN_NO_ERROR;
 }
@@ -2180,105 +2190,48 @@ svn_stream__install_stream(svn_stream_t
 
   SVN_ERR_ASSERT(svn_dirent_is_absolute(final_abspath));
 #ifdef WIN32
-
-#if _WIN32_WINNT < 0x600
-  SVN_ERR(svn_atomic__init_once(&SetFileInformationByHandle_a,
-                                find_SetFileInformationByHandle,
-                                NULL, scratch_pool));
-
-  if (!SetFileInformationByHandle_p)
-    SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool));
-  else
-#endif /* WIN32 < Windows Vista */
+  err = svn_io__win_rename_open_file(ib->baton_apr.file,  ib->tmp_path,
+                                     final_abspath, scratch_pool);
+  if (make_parents && err && APR_STATUS_IS_ENOENT(err->apr_err))
     {
-      WCHAR *w_final_abspath;
-      size_t path_len;
-      size_t rename_size;
-      FILE_RENAME_INFO *rename_info;
-      HANDLE hFile;
-
-      apr_os_file_get(&hFile, ib->baton_apr.file);
-
-      SVN_ERR(svn_utf__win32_utf8_to_utf16(&w_final_abspath,
-                                           svn_dirent_local_style(
-                                                          final_abspath,
-                                                          scratch_pool),
-                                           NULL, scratch_pool));
-      path_len = wcslen(w_final_abspath);
-      rename_size = sizeof(*rename_info) + sizeof(WCHAR) * path_len;
-
-      /* The rename info struct doesn't need hacks for long paths,
-         so no ugly escaping calls here */
-      rename_info = apr_pcalloc(scratch_pool, rename_size);
-      rename_info->ReplaceIfExists = TRUE;
-      rename_info->FileNameLength = path_len;
-      memcpy(rename_info->FileName, w_final_abspath, path_len * sizeof(WCHAR));
-
-      if (!SetFileInformationByHandle(hFile, FileRenameInfo, rename_info,
-                                      rename_size))
-        {
-          svn_boolean_t retry = FALSE;
-          err = svn_error_wrap_apr(apr_get_os_error(), NULL);
-
-          /* ### rhuijben: I wouldn't be surprised if we later find out that we
-                           have to fall back to close+rename on some specific
-                           error values here, to support some non standard NAS
-                           and filesystem scenarios. */
-
-          if (make_parents && err && APR_STATUS_IS_ENOENT(err->apr_err))
-            {
-              svn_error_t *err2;
-
-              err2 = svn_io_make_dir_recursively(svn_dirent_dirname(final_abspath,
-                                                            scratch_pool),
-                                                 scratch_pool);
-
-              if (err2)
-                return svn_error_trace(svn_error_compose_create(err, err2));
-              else
-                svn_error_clear(err);
-
-              retry = TRUE;
-              err = NULL;
-            }
-          else if (err && (APR_STATUS_IS_EACCES(err->apr_err)
-                           || APR_STATUS_IS_EEXIST(err->apr_err)))
-            {
-              svn_error_clear(err);
-              retry = TRUE;
-              err = NULL;
+      svn_error_t *err2;
 
-              /* Set the destination file writable because Windows will not allow
-                 us to rename when final_abspath is read-only. */
-              SVN_ERR(svn_io_set_file_read_write(final_abspath, TRUE,
-                                                 scratch_pool));
-            }
+      err2 = svn_io_make_dir_recursively(svn_dirent_dirname(final_abspath,
+                                                    scratch_pool),
+                                         scratch_pool);
 
-          if (retry)
-            {
-              if (!SetFileInformationByHandle(hFile, FileRenameInfo,
-                                              rename_info, rename_size))
-                {
-                  err = svn_error_wrap_apr(
-                                apr_get_os_error(),
-                                _("Can't move '%s' to '%s'"),
-                                svn_dirent_local_style(ib->tmp_path,
-                                                       scratch_pool),
-                                svn_dirent_local_style(final_abspath,
-                                                       scratch_pool));
-                }
-            }
-        }
+      if (err2)
+        return svn_error_trace(svn_error_compose_create(err, err2));
       else
-        err = NULL;
+        svn_error_clear(err);
+
+      err = svn_io__win_rename_open_file(ib->baton_apr.file, ib->tmp_path,
+                                         final_abspath, scratch_pool);
+    }
 
+  /* ### rhuijben: I wouldn't be surprised if we later find out that we
+                   have to fall back to close+rename on some specific
+                   error values here, to support some non standard NAS
+                   and filesystem scenarios. */
+  if (err && err->apr_err == SVN_ERR_UNSUPPORTED_FEATURE)
+    {
+      /* Rename open files is not supported on this platform: fallback to
+         svn_io_file_rename2(). */
+      svn_error_clear(err);
+      err = SVN_NO_ERROR;
+    }
+  else
+    {
       return svn_error_compose_create(err,
                                       svn_io_file_close(ib->baton_apr.file,
                                                         scratch_pool));
     }
 #endif
 
-  err = svn_io_file_rename(ib->tmp_path, final_abspath, scratch_pool);
+  /* Close temporary file. */
+  SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool));
+
+  err = svn_io_file_rename2(ib->tmp_path, final_abspath, FALSE, scratch_pool);
 
   /* A missing directory is too common to not cover here. */
   if (make_parents && err && APR_STATUS_IS_ENOENT(err->apr_err))
@@ -2296,7 +2249,7 @@ svn_stream__install_stream(svn_stream_t
         /* We could create a directory: retry install */
         svn_error_clear(err);
 
-      SVN_ERR(svn_io_file_rename(ib->tmp_path, final_abspath, scratch_pool));
+      SVN_ERR(svn_io_file_rename2(ib->tmp_path, final_abspath, FALSE, scratch_pool));
     }
   else
     SVN_ERR(err);
@@ -2311,19 +2264,12 @@ svn_stream__install_get_info(apr_finfo_t
                              apr_pool_t *scratch_pool)
 {
   struct install_baton_t *ib = install_stream->baton;
-
-#ifdef WIN32
-  /* On WIN32 the file is still open, so we can obtain the information
-     from the handle without race conditions */
   apr_status_t status;
 
   status = apr_file_info_get(finfo, wanted, ib->baton_apr.file);
 
   if (status)
     return svn_error_wrap_apr(status, NULL);
-#else
-  SVN_ERR(svn_io_stat(finfo, ib->tmp_path, wanted, scratch_pool));
-#endif
 
   return SVN_NO_ERROR;
 }
@@ -2335,39 +2281,25 @@ svn_stream__install_delete(svn_stream_t
   struct install_baton_t *ib = install_stream->baton;
 
 #ifdef WIN32
-  BOOL done;
-
-#if _WIN32_WINNT < 0x600
-
-  SVN_ERR(svn_atomic__init_once(&SetFileInformationByHandle_a,
-                                find_SetFileInformationByHandle,
-                                NULL, scratch_pool));
+  svn_error_t *err;
 
-  if (!SetFileInformationByHandle_p)
-    done = FALSE;
-  else
-#endif /* WIN32 < Windows Vista */
+  /* Mark the file as delete on close to avoid having to reopen
+     the file as part of the delete handling. */
+  err = svn_io__win_delete_file_on_close(ib->baton_apr.file,  ib->tmp_path,
+                                         scratch_pool);
+  if (err == SVN_NO_ERROR)
     {
-      FILE_DISPOSITION_INFO disposition_info;
-      HANDLE hFile;
-
-      apr_os_file_get(&hFile, ib->baton_apr.file);
-
-      disposition_info.DeleteFile = TRUE;
-
-      /* Mark the file as delete on close to avoid having to reopen
-         the file as part of the delete handling. */
-      done = SetFileInformationByHandle(hFile, FileDispositionInfo,
-                                        &disposition_info,
-                                        sizeof(disposition_info));
+      SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool));
+      return SVN_NO_ERROR; /* File is already gone */
     }
 
-   SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool));
-
-   if (done)
-     return SVN_NO_ERROR; /* File is already gone */
+  /* Deleting file on close may be unsupported, so ignore errors and
+     fallback to svn_io_remove_file2(). */
+  svn_error_clear(err);
 #endif
 
+  SVN_ERR(svn_io_file_close(ib->baton_apr.file, scratch_pool));
+
   return svn_error_trace(svn_io_remove_file2(ib->tmp_path, FALSE,
                                              scratch_pool));
 }

Modified: subversion/branches/ra-git/subversion/libsvn_subr/string.c
URL: http://svn.apache.org/viewvc/subversion/branches/ra-git/subversion/libsvn_subr/string.c?rev=1717223&r1=1717222&r2=1717223&view=diff
==============================================================================
--- subversion/branches/ra-git/subversion/libsvn_subr/string.c (original)
+++ subversion/branches/ra-git/subversion/libsvn_subr/string.c Mon Nov 30 10:24:16 2015
@@ -677,7 +677,7 @@ svn_stringbuf_remove(svn_stringbuf_t *st
 {
   if (pos > str->len)
     pos = str->len;
-  if (pos + count > str->len)
+  if (count > str->len - pos)
     count = str->len - pos;
 
   memmove(str->data + pos, str->data + pos + count, str->len - pos - count + 1);
@@ -705,7 +705,7 @@ svn_stringbuf_replace(svn_stringbuf_t *s
 
   if (pos > str->len)
     pos = str->len;
-  if (pos + old_count > str->len)
+  if (old_count > str->len - pos)
     old_count = str->len - pos;
 
   if (old_count < new_count)