From 1e5535ce0c17e7e605e71d7423789a3d5254d9f7 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 19 Feb 2012 22:17:05 +0100 Subject: [PATCH] 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 , via Paul Eggert. --- ChangeLog | 11 +++++ lib/copy-acl.c | 20 +++++++-- lib/file-has-acl.c | 13 +++++- lib/set-mode-acl.c | 16 ++++++-- tests/test-sameacls.c | 110 +++++++++++++++++++++++++++----------------------- 5 files changed, 110 insertions(+), 60 deletions(-) diff --git a/ChangeLog b/ChangeLog index 82726fb14..851f4fc68 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,16 @@ 2012-02-19 Bruno Haible + 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 + , via Paul Eggert. + +2012-02-19 Bruno Haible + acl: Fix copy-acl test failure on Solaris 11 2011-11. * lib/file-has-acl.c (NEW_ACE_WRITEA_DATA): New macro. (acl_ace_nontrivial): Relax the restrictions on access_masks[] so diff --git a/lib/copy-acl.c b/lib/copy-acl.c index 9b9f033dd..685d4cf44 100644 --- a/lib/copy-acl.c +++ b/lib/copy-acl.c @@ -235,10 +235,22 @@ qcopy_acl (const char *src_name, int source_desc, const char *dst_name, 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. */ diff --git a/lib/file-has-acl.c b/lib/file-has-acl.c index 2d4531b74..77822f040 100644 --- a/lib/file-has-acl.c +++ b/lib/file-has-acl.c @@ -626,6 +626,8 @@ file_has_acl (char const *name, struct stat const *sb) for (;;) { + int ret; + count = acl (name, ACE_GETACLCNT, 0, NULL); if (count < 0) @@ -656,7 +658,16 @@ file_has_acl (char const *name, struct stat const *sb) 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)) { diff --git a/lib/set-mode-acl.c b/lib/set-mode-acl.c index a81b321b6..7fb0890ee 100644 --- a/lib/set-mode-acl.c +++ b/lib/set-mode-acl.c @@ -219,6 +219,8 @@ qset_acl (char const *name, int desc, mode_t mode) for (;;) { + int ret; + if (desc != -1) count = facl (desc, ACE_GETACLCNT, 0, NULL); else @@ -234,10 +236,16 @@ qset_acl (char const *name, int desc, mode_t mode) 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; diff --git a/tests/test-sameacls.c b/tests/test-sameacls.c index c06322077..1cc9e26e7 100644 --- a/tests/test-sameacls.c +++ b/tests/test-sameacls.c @@ -310,58 +310,66 @@ main (int argc, char *argv[]) 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; - 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; - } - } - } + 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 (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; -- 2.11.0