Hi Bruno The shell commands are setacl and getacl.
Output of "VERBOSE=1 make check TESTS=test-file-has-acl.sh" attached. Will have a look at that new acltestdir shortly Bye, Jojo -----Original Message----- From: Bruno Haible [mailto:[email protected]] Sent: Sunday, October 03, 2010 4:34 AM To: Schmitz, Joachim Cc: 'Paolo Bonzini'; 'bug-gnulib' Subject: Re: ACLs on HP NonStop Hi Joachim, > Attached my patches so far... > ... > ../gllib/libgnu.a(set-mode-acl.o): In function `qset_acl': > set-mode-acl.o(.text._148712224+0x202): unresolved reference to facl. This needs another approach. The test in gl_FUNC_ACL and the code in lib/acl-internal.h use different code for each platform, because each platform has its own idiosyncratic ACL related APIs. You tried to map the NonStop API to Solaris/Cygwin API, and that failed. So I would suggest to create a new code path for NonStop in these files. Similarly, in the test suite files tests/test-file-has-acl.sh tests/test-set-mode-acl.sh tests/test-copy-acl.sh tests/test-copy-file.sh a similar dispatch is made according to the shell commands that can be used to set and edit ACLs. To progress on this: 1) The C API: You provided us the necessary documentation and excepts from <sys/acl.h>. Thanks. 2) The shell commands: Can you run $ VERBOSE=1 make check TESTS=test-file-has-acl.sh This should show which value the variable 'acl_flavor' gets, and which shell commands then succeed or fail. Maybe we to create separate code path for acl_flavor=nsk. This depends on how closely NSK implements the ACL related shell commands of some other platform. 3) When this is done, we can turn to the lib/*acl* part. Here a new code path appears to be needed. I've created a new acltestdir.tar.gz for you at http://www.haible.de/bruno/gnu/acltestdir.tar.gz It contains the tentative patch attached below. Bruno --- lib/acl-internal.h.orig Sun Oct 3 04:26:51 2010 +++ lib/acl-internal.h Sun Oct 3 04:21:58 2010 @@ -26,7 +26,7 @@ #if HAVE_SYS_ACL_H # include <sys/acl.h> #endif -#if defined HAVE_ACL && ! defined GETACLCNT && defined ACL_CNT +#if defined HAVE_FACL && ! defined GETACLCNT && defined ACL_CNT # define GETACLCNT ACL_CNT #endif @@ -158,7 +158,7 @@ extern int acl_access_nontrivial (acl_t); # endif -# elif HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ +# elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ /* Set to 1 if a file's mode is implicit by the ACL. Set to 0 if a file's mode is stored independently from the ACL. */ @@ -216,6 +216,12 @@ Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ extern int acl_nontrivial (struct acl *a); +# elif HAVE_ACLSORT /* NonStop Kernel */ + +/* Return 1 if the given ACL is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +extern int acl_nontrivial (int count, struct acl *entries); + # endif #endif --- lib/copy-acl.c.orig Sun Oct 3 04:26:51 2010 +++ lib/copy-acl.c Sun Oct 3 04:25:58 2010 @@ -516,6 +516,68 @@ return 0; +#elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + + int count; + struct acl entries[NACLENTRIES]; + int ret; + + for (;;) + { + count = acl ((char *) src_name, ACL_CNT, NACLENTRIES, NULL); + + if (count < 0) + { + if (0) + { + count = 0; + break; + } + else + return -2; + } + + if (count == 0) + break; + + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory allocation. */ + abort (); + + if (acl ((char *) name, ACL_GET, count, entries) == count) + break; + /* Huh? The number of ACL entries changed since the last call. + Repeat. */ + } + + if (count == 0) + return qset_acl (dst_name, dest_desc, mode); + + ret = acl ((char *) dst_name, ACL_SET, count, entries); + if (ret < 0) + { + int saved_errno = errno; + + if (0) + { + if (!acl_nontrivial (count, entries)) + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + + chmod_or_fchmod (dst_name, dest_desc, mode); + errno = saved_errno; + return -1; + } + + if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + { + /* We did not call chmod so far, and either the mode and the ACL are + separate or special bits are to be set which don't fit into ACLs. */ + + return chmod_or_fchmod (dst_name, dest_desc, mode); + } + return 0; + #else return qset_acl (dst_name, dest_desc, mode); --- lib/file-has-acl.c.orig Sun Oct 3 04:26:51 2010 +++ lib/file-has-acl.c Sun Oct 3 03:07:12 2010 @@ -118,7 +118,7 @@ # endif -#elif USE_ACL && HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ +#elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ # if !defined ACL_NO_TRIVIAL /* Solaris <= 10, Cygwin */ @@ -292,6 +292,32 @@ # endif } +# elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */ + +/* Test an ACL retrieved with ACL_GET. + Return 1 if the given ACL, consisting of COUNT entries, is non-trivial. + Return 0 if it is trivial, i.e. equivalent to a simple stat() mode. */ +int +acl_nontrivial (int count, struct acl *entries) +{ + int i; + + for (i = 0; i < count; i++) + { + struct acl *ace = &entries[i]; + + /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat(). + If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat(). + We don't need to check ace->a_id in these cases. */ + if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */ + || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */ + || ace->a_type == CLASS_OBJ + || ace->a_type == OTHER_OBJ)) + return 1; + } + return 0; +} + # endif #endif @@ -377,7 +403,7 @@ return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1; return ret; -# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */ +# elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */ # if defined ACL_NO_TRIVIAL @@ -598,6 +624,37 @@ return acl_nontrivial (&u.a); +# elif HAVE_ACLSORT /* NonStop Kernel */ + + int count; + struct acl entries[NACLENTRIES]; + + for (;;) + { + count = acl ((char *) name, ACL_CNT, NACLENTRIES, NULL); + + if (count < 0) + return -1; + + if (count == 0) + return 0; + + if (count > NACLENTRIES) + /* If NACLENTRIES cannot be trusted, use dynamic memory + allocation. */ + abort (); + + /* If there are more than 4 entries, there cannot be only the + four base ACL entries. */ + if (count > 4) + return 1; + + if (acl ((char *) name, ACL_GET, count, entries) == count) + return acl_nontrivial (count, entries); + /* Huh? The number of ACL entries changed since the last call. + Repeat. */ + } + # endif } #endif --- lib/set-mode-acl.c.orig Sun Oct 3 04:26:51 2010 +++ lib/set-mode-acl.c Sun Oct 3 03:34:20 2010 @@ -201,7 +201,7 @@ return chmod_or_fchmod (name, desc, mode); # endif -# elif HAVE_ACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */ +# elif HAVE_FACL && defined GETACLCNT /* Solaris, Cygwin, not HP-UX */ # if defined ACL_NO_TRIVIAL /* Solaris 10 (newer version), which has additional API declared in @@ -573,6 +573,51 @@ return ret; +# elif HAVE_ACLSORT /* NonStop Kernel */ + + struct acl entries[4]; + int ret; + + entries[0].a_type = USER_OBJ; + entries[0].a_id = 0; /* irrelevant */ + entries[0].a_perm = (mode >> 6) & 7; + entries[1].a_type = GROUP_OBJ; + entries[1].a_id = 0; /* irrelevant */ + entries[1].a_perm = (mode >> 3) & 7; + entries[2].a_type = CLASS_OBJ; + entries[2].a_id = 0; + entries[2].a_perm = (mode >> 3) & 7; + entries[3].a_type = OTHER_OBJ; + entries[3].a_id = 0; + entries[3].a_perm = mode & 7; + + ret = aclsort (sizeof (entries) / sizeof (struct acl), 1, entries); + if (ret > 0) + abort (); + if (ret < 0) + { + if (0) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + + ret = acl ((char *) name, ACL_SET, + sizeof (entries) / sizeof (struct acl), entries); + if (ret < 0) + { + if (0) + return chmod_or_fchmod (name, desc, mode); + return -1; + } + + if (mode & (S_ISUID | S_ISGID | S_ISVTX)) + { + /* We did not call chmod so far, so the special bits have not yet + been set. */ + return chmod_or_fchmod (name, desc, mode); + } + return 0; + # else /* Unknown flavor of ACLs */ return chmod_or_fchmod (name, desc, mode); # endif --- m4/acl.m4.orig Sun Oct 3 04:26:51 2010 +++ m4/acl.m4 Sat Oct 2 18:05:22 2010 @@ -1,5 +1,5 @@ # acl.m4 - check for access control list (ACL) primitives -# serial 10 +# serial 11 # Copyright (C) 2002, 2004-2010 Free Software Foundation, Inc. # This file is free software; the Free Software Foundation @@ -76,8 +76,8 @@ dnl Test for Solaris API (Solaris, Cygwin). if test $use_acl = 0; then - AC_CHECK_FUNCS([acl]) - if test $ac_cv_func_acl = yes; then + AC_CHECK_FUNCS([facl]) + if test $ac_cv_func_facl = yes; then AC_SEARCH_LIBS([acl_trivial], [sec], [if test "$ac_cv_search_acl_trivial" != "none required"; then LIB_ACL=$ac_cv_search_acl_trivial @@ -89,7 +89,7 @@ fi dnl Test for HP-UX API. - if test $use_acl = 0 || test "$ac_cv_func_acl" = yes; then + if test $use_acl = 0; then AC_CHECK_FUNCS([getacl]) if test $ac_cv_func_getacl = yes; then use_acl=1 @@ -111,6 +111,14 @@ use_acl=1 fi fi + + dnl Test for NonStop Kernel API. + if test $use_acl = 0; then + AC_CHECK_FUNCS([aclsort]) + if test $ac_cv_func_aclsort = yes; then + use_acl=1 + fi + fi LIBS=$ac_save_LIBS fi --- tests/test-sameacls.c.orig Sun Oct 3 04:26:51 2010 +++ tests/test-sameacls.c Sat Oct 2 18:10:42 2010 @@ -24,7 +24,7 @@ #include <string.h> #include <sys/stat.h> -#if HAVE_ACL_GET_FILE || HAVE_ACL || HAVE_ACLX_GET || HAVE_STATACL +#if HAVE_ACL_GET_FILE || HAVE_FACL || HAVE_ACLX_GET || HAVE_STATACL # include <sys/types.h> # include <sys/acl.h> #endif @@ -218,7 +218,7 @@ } } } -#elif HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ +#elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */ int count1; int count2; @@ -520,6 +520,71 @@ file1, file2); return 1; } +#elif HAVE_ACLSORT /* NonStop Kernel */ + int count1; + int count2; + + count1 = acl ((char *) file1, ACL_CNT, NACLENTRIES, NULL); + count2 = acl ((char *) file2, ACL_CNT, NACLENTRIES, NULL); + + if (count1 < 0) + { + fprintf (stderr, "error accessing the ACLs of file %s\n", file1); + fflush (stderr); + abort (); + } + if (count2 < 0) + { + fprintf (stderr, "error accessing the ACLs of file %s\n", file2); + fflush (stderr); + abort (); + } + if (count1 != count2) + { + fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n", + file1, file2, count1, count2); + return 1; + } + else if (count1 > 0) + { + struct acl *entries1 = XNMALLOC (count1, struct acl); + struct acl *entries2 = XNMALLOC (count2, struct acl); + int i; + + if (acl ((char *) file1, ACL_GET, count1, entries1) < count1) + { + fprintf (stderr, "error retrieving the ACLs of file %s\n", file1); + fflush (stderr); + abort (); + } + if (acl ((char *) file2, ACL_GET, count2, entries2) < count1) + { + fprintf (stderr, "error retrieving the 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 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_id != entries2[i].a_id) + { + fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n", + file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id); + return 1; + } + if (entries1[i].a_perm != entries2[i].a_perm) + { + fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n", + file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm); + return 1; + } + } + } #endif }
testacl.out
Description: Binary data
