changeset 16381:fc5c37ccbece

acl: Fix endless loop on Solaris with vxfs. * lib/file-has-acl.c (file_has_acl) [Solaris]: Treat a failing acl()/facl() call for ACE_GETACL like a failing call for ACE_GETACLCNT. * lib/set-mode-acl.c (qset_acl) [Solaris]: Likewise. * lib/copy-acl.c (qcopy_acl)[Solaris]: Likewise. * tests/test-sameacls.c (main)[Solaris]: Likewise. Reported by Bill Jones in <http://debbugs.gnu.org/cgi/bugreport.cgi?bug=10639>, via Paul Eggert.
author Bruno Haible <bruno@clisp.org>
date Sun, 19 Feb 2012 22:17:05 +0100
parents 1d3faf917922
children cc05dad27529
files ChangeLog lib/copy-acl.c lib/file-has-acl.c lib/set-mode-acl.c tests/test-sameacls.c
diffstat 5 files changed, 110 insertions(+), 60 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2012-02-19  Bruno Haible  <bruno@clisp.org>
+
+	acl: Fix endless loop on Solaris with vxfs.
+	* lib/file-has-acl.c (file_has_acl) [Solaris]: Treat a failing
+	acl()/facl() call for ACE_GETACL like a failing call for ACE_GETACLCNT.
+	* lib/set-mode-acl.c (qset_acl) [Solaris]: Likewise.
+	* lib/copy-acl.c (qcopy_acl)[Solaris]: Likewise.
+	* tests/test-sameacls.c (main)[Solaris]: Likewise.
+	Reported by Bill Jones in
+	<http://debbugs.gnu.org/cgi/bugreport.cgi?bug=10639>, via Paul Eggert.
+
 2012-02-19  Bruno Haible  <bruno@clisp.org>
 
 	acl: Fix copy-acl test failure on Solaris 11 2011-11.
--- a/lib/copy-acl.c
+++ b/lib/copy-acl.c
@@ -235,10 +235,22 @@
           return -2;
         }
 
-      if ((source_desc != -1
-           ? facl (source_desc, ACE_GETACL, ace_count, ace_entries)
-           : acl (src_name, ACE_GETACL, ace_count, ace_entries))
-          == ace_count)
+      ret = (source_desc != -1
+             ? facl (source_desc, ACE_GETACL, ace_count, ace_entries)
+             : acl (src_name, ACE_GETACL, ace_count, ace_entries));
+      if (ret < 0)
+        {
+          free (ace_entries);
+          if (errno == ENOSYS || errno == EINVAL)
+            {
+              ace_count = 0;
+              ace_entries = NULL;
+              break;
+            }
+          else
+            return -2;
+        }
+      if (ret == ace_count)
         break;
       /* Huh? The number of ACL entries changed since the last call.
          Repeat.  */
--- a/lib/file-has-acl.c
+++ b/lib/file-has-acl.c
@@ -626,6 +626,8 @@
 
         for (;;)
           {
+            int ret;
+
             count = acl (name, ACE_GETACLCNT, 0, NULL);
 
             if (count < 0)
@@ -656,7 +658,16 @@
                 errno = ENOMEM;
                 return -1;
               }
-            if (acl (name, ACE_GETACL, count, entries) == count)
+            ret = acl (name, ACE_GETACL, count, entries);
+            if (ret < 0)
+              {
+                free (entries);
+                if (errno == ENOSYS || errno == EINVAL)
+                  break;
+                else
+                  return -1;
+              }
+            if (ret == count)
               {
                 if (acl_ace_nontrivial (count, entries))
                   {
--- a/lib/set-mode-acl.c
+++ b/lib/set-mode-acl.c
@@ -219,6 +219,8 @@
 
     for (;;)
       {
+        int ret;
+
         if (desc != -1)
           count = facl (desc, ACE_GETACLCNT, 0, NULL);
         else
@@ -234,10 +236,16 @@
             errno = ENOMEM;
             return -1;
           }
-        if ((desc != -1
-             ? facl (desc, ACE_GETACL, count, entries)
-             : acl (name, ACE_GETACL, count, entries))
-            == count)
+        ret = (desc != -1
+               ? facl (desc, ACE_GETACL, count, entries)
+               : acl (name, ACE_GETACL, count, entries));
+        if (ret < 0)
+          {
+            free (entries);
+            convention = -1;
+            break;
+          }
+        if (ret == count)
           {
             int i;
 
--- a/tests/test-sameacls.c
+++ b/tests/test-sameacls.c
@@ -310,58 +310,66 @@
       fflush (stderr);
       abort ();
     }
-  if (count1 != count2)
-    {
-      fprintf (stderr, "files %s and %s have different number of ACE-ACLs: %d and %d\n",
-               file1, file2, count1, count2);
-      return 1;
-    }
-  else if (count1 > 0)
-    {
-      ace_t *entries1 = XNMALLOC (count1, ace_t);
-      ace_t *entries2 = XNMALLOC (count2, ace_t);
-      int i;
+  {
+    ace_t *entries1 = XNMALLOC (count1, ace_t);
+    ace_t *entries2 = XNMALLOC (count2, ace_t);
+    int ret;
+    int i;
+
+    ret = acl (file1, ACE_GETACL, count1, entries1);
+    if (ret < 0 && errno == EINVAL)
+      count1 = 0;
+    else if (ret < count1)
+      {
+        fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
+        fflush (stderr);
+        abort ();
+      }
+    ret = acl (file2, ACE_GETACL, count2, entries2);
+    if (ret < 0 && errno == EINVAL)
+      count2 = 0;
+    else if (ret < count2)
+      {
+        fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file2);
+        fflush (stderr);
+        abort ();
+      }
 
-      if (acl (file1, ACE_GETACL, count1, entries1) < count1)
-        {
-          fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
-          fflush (stderr);
-          abort ();
-        }
-      if (acl (file2, ACE_GETACL, count2, entries2) < count1)
-        {
-          fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file2);
-          fflush (stderr);
-          abort ();
-        }
-      for (i = 0; i < count1; i++)
-        {
-          if (entries1[i].a_type != entries2[i].a_type)
-            {
-              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different types %d and %d\n",
-                       file1, file2, i, entries1[i].a_type, entries2[i].a_type);
-              return 1;
-            }
-          if (entries1[i].a_who != entries2[i].a_who)
-            {
-              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different ids %d and %d\n",
-                       file1, file2, i, (int)entries1[i].a_who, (int)entries2[i].a_who);
-              return 1;
-            }
-          if (entries1[i].a_access_mask != entries2[i].a_access_mask)
-            {
-              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different access masks %03o and %03o\n",
-                       file1, file2, i, (unsigned int) entries1[i].a_access_mask, (unsigned int) entries2[i].a_access_mask);
-              return 1;
-            }
-          if (entries1[i].a_flags != entries2[i].a_flags)
-            {
-              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different flags 0x%x and 0x%x\n",
-                       file1, file2, i, (unsigned int) entries1[i].a_flags, (unsigned int) entries2[i].a_flags);
-              return 1;
-            }
-        }
-    }
+    if (count1 != count2)
+      {
+        fprintf (stderr, "files %s and %s have different number of ACE-ACLs: %d and %d\n",
+                 file1, file2, count1, count2);
+        return 1;
+      }
+
+    for (i = 0; i < count1; i++)
+      {
+        if (entries1[i].a_type != entries2[i].a_type)
+          {
+            fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different types %d and %d\n",
+                     file1, file2, i, entries1[i].a_type, entries2[i].a_type);
+            return 1;
+          }
+        if (entries1[i].a_who != entries2[i].a_who)
+          {
+            fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different ids %d and %d\n",
+                     file1, file2, i, (int)entries1[i].a_who, (int)entries2[i].a_who);
+            return 1;
+          }
+        if (entries1[i].a_access_mask != entries2[i].a_access_mask)
+          {
+            fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different access masks %03o and %03o\n",
+                     file1, file2, i, (unsigned int) entries1[i].a_access_mask, (unsigned int) entries2[i].a_access_mask);
+            return 1;
+          }
+        if (entries1[i].a_flags != entries2[i].a_flags)
+          {
+            fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different flags 0x%x and 0x%x\n",
+                     file1, file2, i, (unsigned int) entries1[i].a_flags, (unsigned int) entries2[i].a_flags);
+            return 1;
+          }
+      }
+  }
 # endif
 #elif HAVE_GETACL /* HP-UX */
   int count1;