[prev in list] [next in list] [prev in thread] [next in thread] 

List:       subversion-dev
Subject:    [PATCH] Proof-of-concept patch for APR 1.2 support on Windows
From:       "Sergey A. Lipnevich" <sergey () optimaltec ! com>
Date:       2006-06-28 5:42:08
Message-ID: e7t4ud$u3l$1 () sea ! gmane ! org
[Download RAW message or body]

Hi All,

I was trying to run Subversion 1.3.x (.1 and .2) on Windows with Apache
2.2, and came across a discussion related to handling of APR_INCOMPLETE
error (http://svn.haxx.se/dev/archive-2005-12/0522.shtml) and a related
question of what to do with svn_io_set_file_read_write_carefully
(http://svn.haxx.se/dev/archive-2006-06/0093.shtml). Since my setup
wasn't working, I tried to fix Subversion 1.3.2 according to the ideas
mentioned in these threads, and came up with the following patch
(borrowing an idea from D.J. Heap's patch above for
svn_io_set_file_read_write_carefully). It's not intended for commit as
it is. Please let me know if this is the right approach to take, and
what needs to be done to finish this patch.

I ran the test suite with the following two consistent failures that I
didn't yet investigate:

FAIL:  stat_tests.py 8: status for unignored file and directory
Log:
  svn: warning: 'newfile' is not under version control
  FAIL:  stat_tests.py 8: status for unignored file and directory

FAIL:  lock_tests.py 19: update handles svn:needs-lock correctly
Log:
  svn: '.' is not a working copy
  FAIL:  lock_tests.py 19: update handles svn:needs-lock correctly

The compiler I use is from VS 2005.
Thanks!

Sergey.

[
  Initial support for APR 1.2, boils down to avoiding APR_FINFO_PROT as much
  as possible.

  * subversion/libsvn_subr/io.c:

    use APR_FREADONLY to detect read-only file attribute on Win32;

    replace contents of svn_io_set_file_read_write_carefully with
    a call to either svn_io_set_file_read_write or
    svn_io_set_file_read_only;

    don't do anything about "executable" attribute on Win32;

    if svn_io_stat gets APR_INCOMPLETE status, disregard it if all but
    APR_FINFO_PROT bits are valid;

    don't try to handle SGID bit on Win32;

    remove pre-APR 0.9.5 code related to SGID.
]



["apr-1.2.diff" (text/x-patch)]

--- subversion/libsvn_subr/io.c	2005-11-16 18:05:43.000000000 -0500
+++ subversion/libsvn_subr/io.c	2006-06-27 17:46:52.131177100 -0400
@@ -47,6 +47,10 @@
 #include <apr_strings.h>
 #include <apr_portable.h>
 #include <apr_md5.h>
+#ifdef WIN32
+/* APR keeps this declaration private, but we need it. */
+#define APR_FREADONLY 0x10000000 /* from apr_arch_file_io.h */
+#endif
 
 #include "svn_types.h"
 #include "svn_path.h"
@@ -1052,94 +1056,8 @@ svn_io_set_file_read_write_carefully (co
                                       svn_boolean_t ignore_enoent,
                                       apr_pool_t *pool)
 {
-  apr_status_t status;
-  const char *path_apr;
-  apr_finfo_t finfo;
-  apr_fileperms_t perms_to_set;
-
-  SVN_ERR (svn_path_cstring_from_utf8 (&path_apr, path, pool));
-
-  /* Try to change only a minimal amount of the perms first 
-     by getting the current perms and adding execute bits
-     only on where read perms are granted.  If this fails
-     fall through to the svn_io_set_file* calls. */
-  status = apr_stat (&finfo, path_apr, APR_FINFO_PROT, pool);
-  if (status)
-    {
-      if (ignore_enoent && APR_STATUS_IS_ENOENT (status))
-        return SVN_NO_ERROR;
-      else if (status != APR_ENOTIMPL)
-        return svn_error_wrap_apr (status,
-                                   _("Can't change read-write perms of "
-                                     "file '%s'"),
-                                   svn_path_local_style (path, pool));
-    } 
-  else
-    {
-      perms_to_set = finfo.protection;
-      if (enable_write) /* Make read-write. */
-        SVN_ERR (get_default_file_perms (path, &perms_to_set, 
-                                         pool));
-      else /* Make read-only. */
-        {
-          if (finfo.protection & APR_UREAD)
-            perms_to_set &= ~APR_UWRITE;
-          if (finfo.protection & APR_GREAD)
-            perms_to_set &= ~APR_GWRITE;
-          if (finfo.protection & APR_WREAD)
-            perms_to_set &= ~APR_WWRITE;
-        }
-
-      /* If we aren't changing anything then just return, this save
-         some system calls and helps with shared working copies */
-      if (perms_to_set == finfo.protection)
-        return SVN_NO_ERROR;
-
-      status = apr_file_perms_set (path_apr, perms_to_set);
-      if (status)
-        {
-          if (APR_STATUS_IS_EPERM (status))
-            {
-              /* We don't have permissions to change the
-                 permissions!  Try a move, copy, and delete
-                 workaround to see if we can get the file owned by
-                 us.  If these succeed, try the permissions set
-                 again.
-
-                 Note that we only attempt this in the
-                 stat-available path.  This assumes that the
-                 move-copy workaround will only be helpful on
-                 platforms that implement apr_stat. */
-              SVN_ERR (reown_file (path_apr, pool));
-              status = apr_file_perms_set (path_apr, perms_to_set);
-            }
-
-          if (status)
-            {
-              if (ignore_enoent && APR_STATUS_IS_ENOENT (status))
-                return SVN_NO_ERROR;
-              else if (status == APR_ENOTIMPL) /* on win32, for example. */
-                {
-                  if (enable_write)
-                    SVN_ERR (svn_io_set_file_read_write (path, ignore_enoent,
-                                                         pool));
-
-                  else
-                    SVN_ERR (svn_io_set_file_read_only (path, ignore_enoent,
-                                                        pool));
-                }
-              else
-                return svn_error_wrap_apr
-                  (status, _("Can't change read-write perms of file '%s'"),
-                   svn_path_local_style (path, pool));
-            }
-          else
-            return SVN_NO_ERROR;
-        }
-      else
-        return SVN_NO_ERROR;
-    } 
-  return SVN_NO_ERROR;
+  return (enable_write ? svn_io_set_file_read_write : svn_io_set_file_read_only)
+         (path, ignore_enoent, pool);
 }
 
 svn_error_t *
@@ -1150,12 +1068,21 @@ svn_io_set_file_executable (const char *
 {
   apr_status_t status;
   const char *path_apr;
+  apr_finfo_t finfo;
 
   SVN_ERR (svn_path_cstring_from_utf8 (&path_apr, path, pool));
 
+#ifdef WIN32
+  /* No executable attribute is available on Win32. */
+
+  if (ignore_enoent)
+    return SVN_NO_ERROR;
+
+  /* We have to make sure the file exists before leaving. */
+  status = apr_stat(&finfo, path_apr, APR_FINFO_MIN, pool);
+#else /* !WIN32 */
   if (executable)
     {
-      apr_finfo_t finfo;
       apr_fileperms_t perms_to_set;
 
       /* Try to change only a minimal amount of the perms first 
@@ -1233,7 +1160,8 @@ svn_io_set_file_executable (const char *
                                  0,
                                  APR_FILE_ATTR_EXECUTABLE,
                                  pool);
-    
+#endif /* WIN32 */
+
   if (status && status != APR_ENOTIMPL)
     if (!ignore_enoent || !APR_STATUS_IS_ENOENT(status))
       return svn_error_wrap_apr (status,
@@ -2357,8 +2285,20 @@ svn_io_stat (apr_finfo_t *finfo, const c
 
   status = apr_stat (finfo, fname_apr, wanted, pool);
   if (status)
-    return svn_error_wrap_apr (status, _("Can't stat '%s'"),
-                               svn_path_local_style (fname, pool));
+    {
+      /* See if the error is due to APR_FINFO_PROT and the rest of the
+       * "wanted" data is valid. */
+      if (APR_STATUS_IS_INCOMPLETE(status) && (wanted & APR_FINFO_PROT))
+        {
+          apr_int32_t invalid = wanted & ~finfo->valid;
+          /* All invalid bits are in APR_FINFO_PROT? */
+          if (!(invalid & ~APR_FINFO_PROT))
+            return SVN_NO_ERROR;
+        }
+
+      return svn_error_wrap_apr (status, _("Can't stat '%s'"),
+                                 svn_path_local_style (fname, pool));
+    }
 
   return SVN_NO_ERROR;  
 }
@@ -2385,7 +2325,9 @@ svn_io_file_rename (const char *from_pat
   SVN_ERR (svn_path_cstring_from_utf8 (&to_path_apr, to_path, pool));
 
 #ifdef WIN32
-  status = apr_stat (&finfo, to_path_apr, APR_FINFO_PROT, pool);
+  /* On Win32, APR_FINFO_MIN is enough to get APR_FREADONLY flag in
+   * finfo.protection. */
+  status = apr_stat (&finfo, to_path_apr, APR_FINFO_MIN, pool);
   if (APR_STATUS_IS_ENOENT (status))
     {
       was_read_only = FALSE;
@@ -2398,8 +2340,7 @@ svn_io_file_rename (const char *from_pat
          file permissions. But that shouldn't happen in a Subversion
          working copy, and then set_read_write will fail, so the end
          result is the same. */
-      was_read_only = !(finfo.protection
-                        & (APR_UWRITE | APR_GWRITE | APR_WWRITE));
+      was_read_only = (finfo.protection & APR_FREADONLY) != 0;
       if (was_read_only)
         SVN_ERR (svn_io_set_file_read_write (to_path, FALSE, pool));
     }
@@ -2529,7 +2470,9 @@ dir_make (const char *path, apr_fileperm
     }
 #endif
 
-#if defined(APR_GSETID)
+  /* Don't try to set group ID on Win32. */
+#if defined(APR_GSETID) && !defined(WIN32)
+  /* APR_GSETID appears in APR 0.9.5. */
   if (sgid)
     {
       apr_finfo_t finfo;
@@ -2544,20 +2487,7 @@ dir_make (const char *path, apr_fileperm
        * don't support the sgid bit, and that's okay. */
       apr_file_perms_set (path_apr, finfo.protection | APR_GSETID);
     }
-#elif !defined (WIN32)
-  /* APR_GSETID appears in APR 0.9.5, so we need some fallback code
-     until Subversion can require 0.9.5. */
-  if (sgid)
-  {
-    struct stat st;
-
-    if (stat (path_apr, &st) != 0)
-      return svn_error_wrap_apr (APR_FROM_OS_ERROR (errno),
-                                 _("Can't stat new directory '%s'"),
-                                 svn_path_local_style (path, pool));
-    chmod (path_apr, (st.st_mode & ~S_IFMT) | S_ISGID);
-  }
-#endif
+#endif /* APR_GSETID && !WIN32 */
 
   return SVN_NO_ERROR;
 }




---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@subversion.tigris.org
For additional commands, e-mail: dev-help@subversion.tigris.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic