]> git.eshelyaron.com Git - emacs.git/commitdiff
Don't fail in acl_set_file on MS-Windows if the operation is a no-op.
authorEli Zaretskii <eliz@gnu.org>
Sun, 23 Dec 2012 17:16:33 +0000 (19:16 +0200)
committerEli Zaretskii <eliz@gnu.org>
Sun, 23 Dec 2012 17:16:33 +0000 (19:16 +0200)
 src/w32.c (acl_set_file): If setting the file security descriptor
 fails, and the new DACL is identical to the existing one, silently
 return success.  This fixes problems for users backing up their
 own files without having the necessary privileges for setting
 security descriptors.

src/ChangeLog
src/w32.c

index c7502104ddffbcfddaed90d619530acd57300810..648f14a61e4e482ad9af336ed685fa25520c5949 100644 (file)
@@ -1,5 +1,11 @@
 2012-12-23  Eli Zaretskii  <eliz@gnu.org>
 
+       * w32.c (acl_set_file): If setting the file security descriptor
+       fails, and the new DACL is identical to the existing one, silently
+       return success.  This fixes problems for users backing up their
+       own files without having the necessary privileges for setting
+       security descriptors.
+
        * w32proc.c (reader_thread): Do not index fd_info[] with negative
        values.
        (reader_thread): Exit when cp->status becomes STATUS_READ_ERROR
index 47b950668b08727b48ec1f04030964206ee7c102..9ebc97088d02576105d868da8bd218ad1f7c8d20 100644 (file)
--- a/src/w32.c
+++ b/src/w32.c
@@ -4876,8 +4876,31 @@ acl_set_file (const char *fname, acl_type_t type, acl_t acl)
       retval = 0;
       errno = e;
     }
-  else if (err == ERROR_INVALID_OWNER)
-    errno = EPERM;
+  else if (err == ERROR_INVALID_OWNER || err == ERROR_NOT_ALL_ASSIGNED)
+    {
+      /* Maybe the requested ACL and the one the file already has are
+        identical, in which case we can silently ignore the
+        failure.  (And no, Windows doesn't.)  */
+      acl_t current_acl = acl_get_file (fname, ACL_TYPE_ACCESS);
+
+      errno = EPERM;
+      if (current_acl)
+       {
+         char *acl_from = acl_to_text (current_acl, NULL);
+         char *acl_to = acl_to_text (acl, NULL);
+
+         if (acl_from && acl_to && xstrcasecmp (acl_from, acl_to) == 0)
+           {
+             retval = 0;
+             errno = e;
+           }
+         if (acl_from)
+           acl_free (acl_from);
+         if (acl_to)
+           acl_free (acl_to);
+         acl_free (current_acl);
+       }
+    }
   else if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND)
     errno = ENOENT;