Mercurial > hg > octave-nkf > gnulib-hg
changeset 10142:dc740b83408a
New ACL unit tests.
author | Bruno Haible <bruno@clisp.org> |
---|---|
date | Sun, 01 Jun 2008 22:51:13 +0200 |
parents | 69c854126601 |
children | 15617fa27827 |
files | ChangeLog modules/acl-tests modules/copy-file-tests tests/test-copy-acl.c tests/test-copy-acl.sh tests/test-file-has-acl.c tests/test-file-has-acl.sh tests/test-set-mode-acl.c tests/test-set-mode-acl.sh |
diffstat | 9 files changed, 1275 insertions(+), 17 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2008-06-01 Bruno Haible <bruno@clisp.org> + + New ACL tests. + * tests/test-file-has-acl.sh: New file. + * tests/test-file-has-acl.c: New file. + * tests/test-set-mode-acl.sh: New file. + * tests/test-set-mode-acl.c: New file. + * tests/test-copy-acl.sh: New file, based on tests/test-copy-file.sh. + * tests/test-copy-acl.c: New file. + * modules/acl-tests: New file, based on modules/copy-file-tests. + * modules/copy-file-tests (Files): Remove tests/test-sameacls.c. + (Depends-on): Add acl-tests. + (configure.ac): Remove checks. + (Makefile.am): Don't create test-sameacls program here any more. + 2008-06-01 Bruno Haible <bruno@clisp.org> * tests/test-copy-file.sh: Portability fixes for Solaris, HP-UX, IRIX.
new file mode 100644 --- /dev/null +++ b/modules/acl-tests @@ -0,0 +1,39 @@ +Files: +tests/test-file-has-acl.sh +tests/test-set-mode-acl.sh +tests/test-copy-acl.sh +tests/test-file-has-acl.c +tests/test-set-mode-acl.c +tests/test-copy-acl.c +tests/test-sameacls.c + +Depends-on: +progname +read-file +unistd +xalloc + +configure.ac: +AC_REQUIRE([gl_FUNC_ACL]) +save_LIBS="$LIBS" +LIBS="$LIB_ACL $LIBS" +dnl Test for functions present on Linux, FreeBSD, MacOS X, IRIX, Tru64. +AC_CHECK_FUNCS([acl_get_file]) +dnl Test for functions present on Solaris, Cygwin. +AC_CHECK_FUNCS([acl]) +dnl Test for functions present on HP-UX. +AC_CHECK_FUNCS([getacl]) +dnl Test for functions present on AIX. +AC_CHECK_FUNCS([aclx_get]) +dnl Test for functions present on older AIX. +AC_CHECK_FUNCS([statacl]) +LIBS="$save_LIBS" + +Makefile.am: +TESTS += test-file-has-acl.sh test-set-mode-acl.sh test-copy-acl.sh +TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' +check_PROGRAMS += test-file-has-acl test-set-mode-acl test-copy-acl test-sameacls +test_file_has_acl_LDADD = $(LDADD) $(LIB_ACL) +test_set_mode_acl_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@ +test_copy_acl_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@ +test_sameacls_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@
--- a/modules/copy-file-tests +++ b/modules/copy-file-tests @@ -1,33 +1,18 @@ Files: tests/test-copy-file.sh tests/test-copy-file.c -tests/test-sameacls.c Depends-on: acl +acl-tests progname read-file xalloc configure.ac: -AC_REQUIRE([gl_FUNC_ACL]) -save_LIBS="$LIBS" -LIBS="$LIB_ACL $LIBS" -dnl Test for functions present on Linux, FreeBSD, MacOS X, IRIX, Tru64, Cygwin. -AC_CHECK_FUNCS([acl_get_file]) -dnl Test for functions present on Solaris. -AC_CHECK_FUNCS([acl]) -dnl Test for functions present on HP-UX. -AC_CHECK_FUNCS([getacl]) -dnl Test for functions present on AIX. -AC_CHECK_FUNCS([aclx_get]) -dnl Test for functions present on older AIX. -AC_CHECK_FUNCS([statacl]) -LIBS="$save_LIBS" Makefile.am: TESTS += test-copy-file.sh TESTS_ENVIRONMENT += EXEEXT='@EXEEXT@' -check_PROGRAMS += test-copy-file test-sameacls +check_PROGRAMS += test-copy-file test_copy_file_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@ -test_sameacls_LDADD = $(LDADD) $(LIB_ACL) @LIBINTL@
new file mode 100644 --- /dev/null +++ b/tests/test-copy-acl.c @@ -0,0 +1,87 @@ +/* Test of copying of files. + Copyright (C) 2008 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2008. */ + +#include <config.h> + +#include "acl.h" + +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#include "progname.h" + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +int +main (int argc, char *argv[]) +{ + const char *file1; + const char *file2; + int fd1; + struct stat statbuf; + int mode; + int fd2; + + set_program_name (argv[0]); + + ASSERT (argc == 3); + + file1 = argv[1]; + file2 = argv[2]; + + fd1 = open (file1, O_RDONLY); + if (fd1 < 0 || fstat (fd1, &statbuf) < 0) + { + fprintf (stderr, "could not open file \"%s\"\n", file1); + exit (EXIT_FAILURE); + } + mode = statbuf.st_mode & 07777; + + fd2 = open (file2, O_WRONLY, 0600); + if (fd2 < 0) + { + fprintf (stderr, "could not open file \"%s\"\n", file2); + exit (EXIT_FAILURE); + } + +#if USE_ACL + if (copy_acl (file1, fd1, file2, fd2, mode)) + exit (EXIT_FAILURE); +#else + chmod (file2, mode); +#endif + + close (fd2); + close (fd1); + + return 0; +}
new file mode 100755 --- /dev/null +++ b/tests/test-copy-acl.sh @@ -0,0 +1,485 @@ +#!/bin/sh + +# Show all commands when run with environment variable VERBOSE=yes. +test -z "$VERBOSE" || set -x + +# func_tmpdir +# creates a temporary directory. +# Sets variable +# - tmp pathname of freshly created temporary directory +func_tmpdir () +{ + # Use the environment variable TMPDIR, falling back to /tmp. This allows + # users to specify a different temporary directory, for example, if their + # /tmp is filled up or too small. + : ${TMPDIR=/tmp} + { + # Use the mktemp program if available. If not available, hide the error + # message. + tmp=`(umask 077 && mktemp -d "$TMPDIR/glXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" + } || + { + # Use a simple mkdir command. It is guaranteed to fail if the directory + # already exists. $RANDOM is bash specific and expands to empty in shells + # other than bash, ksh and zsh. Its use does not increase security; + # rather, it minimizes the probability of failure in a very cluttered /tmp + # directory. + tmp=$TMPDIR/gl$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || + { + echo "$0: cannot create a temporary directory in $TMPDIR" >&2 + exit 1 + } +} + +func_tmpdir +builddir=`pwd` +cd "$builddir" || + { + echo "$0: cannot determine build directory (unreadable parent dir?)" >&2 + exit 1 + } +# Switch to a temporary directory, to increase the likelihood that ACLs are +# supported on the current file system. (/tmp is usually locally mounted, +# whereas the build dir is sometimes NFS-mounted.) +( cd "$tmp" + + # Prepare tmpfile0. + rm -f tmpfile[0-9] tmpaclout[0-2] + echo "Simple contents" > tmpfile0 + chmod 600 tmpfile0 + + # Classification of the platform according to the programs available for + # manipulating ACLs. + # Possible values are: + # linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none. + # TODO: Support also native Win32 platforms (mingw). + acl_flavor=none + if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then + # Platforms with the getfacl and setfacl programs. + # Linux, FreeBSD, Solaris, Cygwin. + if (setfacl --help >/dev/null) 2>/dev/null; then + # Linux, Cygwin. + if (LC_ALL=C setfacl --help | grep ' --set-file' >/dev/null) 2>/dev/null; then + # Linux. + acl_flavor=linux + else + acl_flavor=cygwin + fi + else + # FreeBSD, Solaris. + if (LC_ALL=C setfacl 2>&1 | grep '\-x entries' >/dev/null) 2>/dev/null; then + # FreeBSD. + acl_flavor=freebsd + else + # Solaris. + acl_flavor=solaris + fi + fi + else + if (lsacl / >/dev/null) 2>/dev/null; then + # Platforms with the lsacl and chacl programs. + # HP-UX, sometimes also IRIX. + acl_flavor=hpux + else + if (getacl tmpfile0 >/dev/null) 2>/dev/null; then + # Tru64. + acl_flavor=osf1 + else + if (aclget tmpfile0 >/dev/null) 2>/dev/null; then + # AIX. + acl_flavor=aix + else + if (fsaclctl -v >/dev/null) 2>/dev/null; then + # MacOS X. + acl_flavor=macosx + else + if test -f /sbin/chacl; then + # IRIX. + acl_flavor=irix + fi + fi + fi + fi + fi + fi + + # Define a function to test for the same ACLs, from the point of view of + # the programs. + # func_test_same_acls file1 file2 + case $acl_flavor in + linux | cygwin | freebsd | solaris) + func_test_same_acls () + { + getfacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1 + getfacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2 + cmp tmpaclout1 tmpaclout2 > /dev/null + } + ;; + hpux) + func_test_same_acls () + { + lsacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1 + lsacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2 + cmp tmpaclout1 tmpaclout2 > /dev/null + } + ;; + osf1) + func_test_same_acls () + { + getacl "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1 + getacl "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2 + cmp tmpaclout1 tmpaclout2 > /dev/null + } + ;; + aix) + func_test_same_acls () + { + aclget "$1" > tmpaclout1 + aclget "$2" > tmpaclout2 + cmp tmpaclout1 tmpaclout2 > /dev/null + } + ;; + macosx) + func_test_same_acls () + { + /bin/ls -le "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1 + /bin/ls -le "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2 + cmp tmpaclout1 tmpaclout2 > /dev/null + } + ;; + irix) + func_test_same_acls () + { + /bin/ls -lD "$1" | sed -e "s/$1/FILENAME/g" > tmpaclout1 + /bin/ls -lD "$2" | sed -e "s/$2/FILENAME/g" > tmpaclout2 + cmp tmpaclout1 tmpaclout2 > /dev/null + } + ;; + none) + func_test_same_acls () + { + : + } + ;; + esac + + # func_test_copy file1 file2 + # copies file1 to file2 and verifies the permissions and ACLs are the same + # on both. + func_test_copy () + { + echo "Simple contents" > "$2" + chmod 600 "$2" + "$builddir"/test-copy-acl${EXEEXT} "$1" "$2" || exit 1 + "$builddir"/test-sameacls${EXEEXT} "$1" "$2" || exit 1 + func_test_same_acls "$1" "$2" || exit 1 + } + + func_test_copy tmpfile0 tmpfile1 + + if test $acl_flavor != none; then + # Use a user and group id different from the current one, to avoid + # redundant/ambiguous ACLs. + myuid=`id -u` + mygid=`id -g` + auid=1 + if test "$auid" = "$myuid"; then auid=2; fi + agid=1 + if test "$agid" = "$mygid"; then agid=2; fi + + case $acl_flavor in + linux | cygwin | freebsd | solaris) + + # Set an ACL for a user. + setfacl -m user:$auid:1 tmpfile0 + + func_test_copy tmpfile0 tmpfile2 + + # Set an ACL for a group. + setfacl -m group:$agid:4 tmpfile0 + + func_test_copy tmpfile0 tmpfile3 + + # Set an ACL for other. + case $acl_flavor in + freebsd) setfacl -m other::4 tmpfile0 ;; + solaris) chmod o+r tmpfile0 ;; + *) setfacl -m other:4 tmpfile0 ;; + esac + + func_test_copy tmpfile0 tmpfile4 + + # Remove the ACL for the user. + case $acl_flavor in + linux) setfacl -x user:$auid tmpfile0 ;; + freebsd) setfacl -x user:$auid:1 tmpfile0 ;; + *) setfacl -d user:$auid:1 tmpfile0 ;; + esac + + func_test_copy tmpfile0 tmpfile5 + + # Remove the ACL for other. + case $acl_flavor in + linux | solaris) ;; # impossible + freebsd) setfacl -x other::4 tmpfile0 ;; + *) setfacl -d other:4 tmpfile0 ;; + esac + + func_test_copy tmpfile0 tmpfile6 + + # Remove the ACL for the group. + case $acl_flavor in + linux) setfacl -x group:$agid tmpfile0 ;; + freebsd) setfacl -x group:$agid:4 tmpfile0 ;; + *) setfacl -d group:$agid:4 tmpfile0 ;; + esac + + func_test_copy tmpfile0 tmpfile7 + + # Delete all optional ACLs. + case $acl_flavor in + linux | freebsd) + setfacl -m user:$auid:1 tmpfile0 + setfacl -b tmpfile0 + ;; + *) + setfacl -s user::6,group::0,other:0 tmpfile0 ;; + esac + + func_test_copy tmpfile0 tmpfile8 + + # Copy ACLs from a file that has no ACLs. + echo > tmpfile9 + chmod a+x tmpfile9 + case $acl_flavor in + linux) getfacl tmpfile9 | setfacl --set-file=- tmpfile0 ;; + freebsd) ;; + *) getfacl tmpfile9 | setfacl -f - tmpfile0 ;; + esac + rm -f tmpfile9 + + func_test_copy tmpfile0 tmpfile9 + + ;; + + hpux) + + # Set an ACL for a user. + orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'` + chacl -r "${orig}($auid.%,--x)" tmpfile0 + + func_test_copy tmpfile0 tmpfile2 + + # Set an ACL for a group. + orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'` + chacl -r "${orig}(%.$agid,r--)" tmpfile0 + + func_test_copy tmpfile0 tmpfile3 + + # Set an ACL for other. + orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'` + chacl -r "${orig}(%.%,r--)" tmpfile0 + + func_test_copy tmpfile0 tmpfile4 + + # Remove the ACL for the user. + chacl -d "($auid.%,--x)" tmpfile0 + + func_test_copy tmpfile0 tmpfile5 + + # Remove the ACL for the group. + chacl -d "(%.$agid,r--)" tmpfile0 + + func_test_copy tmpfile0 tmpfile6 + + # Delete all optional ACLs. + chacl -z tmpfile0 + + func_test_copy tmpfile0 tmpfile8 + + # Copy ACLs from a file that has no ACLs. + echo > tmpfile9 + chmod a+x tmpfile9 + orig=`lsacl tmpfile9 | sed -e 's/ tmpfile9$//'` + rm -f tmpfile9 + chacl -r "${orig}" tmpfile0 + + func_test_copy tmpfile0 tmpfile9 + + ;; + + osf1) + + # Set an ACL for a user. + setacl -u user:$auid:1 tmpfile0 + + func_test_copy tmpfile0 tmpfile2 + + # Set an ACL for a group. + setacl -u group:$agid:4 tmpfile0 + + func_test_copy tmpfile0 tmpfile3 + + # Set an ACL for other. + setacl -u other::4 tmpfile0 + + func_test_copy tmpfile0 tmpfile4 + + # Remove the ACL for the user. + setacl -x user:$auid:1 tmpfile0 + + func_test_copy tmpfile0 tmpfile5 + + if false; then # would give an error "can't set ACL: Invalid argument" + # Remove the ACL for other. + setacl -x other::4 tmpfile0 + + func_test_copy tmpfile0 tmpfile6 + fi + + # Remove the ACL for the group. + setacl -x group:$agid:4 tmpfile0 + + func_test_copy tmpfile0 tmpfile7 + + # Delete all optional ACLs. + setacl -u user:$auid:1 tmpfile0 + setacl -b tmpfile0 + + func_test_copy tmpfile0 tmpfile8 + + # Copy ACLs from a file that has no ACLs. + echo > tmpfile9 + chmod a+x tmpfile9 + getacl tmpfile9 > tmpaclout0 + setacl -b -U tmpaclout0 tmpfile0 + rm -f tmpfile9 + + func_test_copy tmpfile0 tmpfile9 + + ;; + + aix) + + # Set an ACL for a user. + { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo " permit --x u:$auid"; } | aclput tmpfile0 + + func_test_copy tmpfile0 tmpfile2 + + # Set an ACL for a group. + { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo " permit r-- g:$agid"; } | aclput tmpfile0 + + func_test_copy tmpfile0 tmpfile3 + + # Set an ACL for other. + chmod o+r tmpfile0 + + func_test_copy tmpfile0 tmpfile4 + + # Remove the ACL for the user. + aclget tmpfile0 | grep -v ' u:[^ ]*$' | aclput tmpfile0 + + func_test_copy tmpfile0 tmpfile5 + + # Remove the ACL for the group. + aclget tmpfile0 | grep -v ' g:[^ ]*$' | aclput tmpfile0 + + func_test_copy tmpfile0 tmpfile7 + + # Delete all optional ACLs. + aclget tmpfile0 | sed -e 's/enabled$/disabled/' | sed -e '/disabled$/q' | aclput tmpfile0 + + func_test_copy tmpfile0 tmpfile8 + + # Copy ACLs from a file that has no ACLs. + echo > tmpfile9 + chmod a+x tmpfile9 + aclget tmpfile9 | aclput tmpfile0 + rm -f tmpfile9 + + func_test_copy tmpfile0 tmpfile9 + + ;; + + macosx) + + # Set an ACL for a user. + /bin/chmod +a "user:daemon allow execute" tmpfile0 + + func_test_copy tmpfile0 tmpfile2 + + # Set an ACL for a group. + /bin/chmod +a "group:daemon allow read" tmpfile0 + + func_test_copy tmpfile0 tmpfile3 + + # Set an ACL for other. + chmod o+r tmpfile0 + + func_test_copy tmpfile0 tmpfile4 + + # Remove the ACL for the user. + /bin/chmod -a "user:daemon allow execute" tmpfile0 + + func_test_copy tmpfile0 tmpfile5 + + # Remove the ACL for the group. + /bin/chmod -a "group:daemon allow read" tmpfile0 + + func_test_copy tmpfile0 tmpfile7 + + # Delete all optional ACLs. + /bin/chmod -N tmpfile0 + + func_test_copy tmpfile0 tmpfile8 + + # Copy ACLs from a file that has no ACLs. + echo > tmpfile9 + chmod a+x tmpfile9 + { /bin/ls -le tmpfile9 | sed -n -e 's/^ [0-9][0-9]*: //p'; echo; } | /bin/chmod -E tmpfile0 + rm -f tmpfile9 + + func_test_copy tmpfile0 tmpfile9 + + ;; + + irix) + + # Set an ACL for a user. + /sbin/chacl user::rw-,group::---,other::---,user:$auid:--x tmpfile0 + + func_test_copy tmpfile0 tmpfile2 + + # Set an ACL for a group. + /sbin/chacl user::rw-,group::---,other::---,user:$auid:--x,group:$agid:r-- tmpfile0 + + func_test_copy tmpfile0 tmpfile3 + + # Set an ACL for other. + /sbin/chacl user::rw-,group::---,user:$auid:--x,group:$agid:r--,other::r-- tmpfile0 + + func_test_copy tmpfile0 tmpfile4 + + # Remove the ACL for the user. + /sbin/chacl user::rw-,group::---,group:$agid:r--,other::r-- tmpfile0 + + func_test_copy tmpfile0 tmpfile5 + + # Remove the ACL for the group. + /sbin/chacl user::rw-,group::---,other::r-- tmpfile0 + + func_test_copy tmpfile0 tmpfile7 + + ;; + + esac + fi + + rm -f tmpfile[0-9] tmpaclout[0-2] +) || exit 1 + +rm -rf "$tmp" +exit 0
new file mode 100644 --- /dev/null +++ b/tests/test-file-has-acl.c @@ -0,0 +1,72 @@ +/* Test for presence of ACL. + Copyright (C) 2008 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2008. */ + +#include <config.h> + +#include "acl.h" + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +int +main (int argc, char *argv[]) +{ + const char *file; + struct stat statbuf; + + ASSERT (argc == 2); + + file = argv[1]; + + if (stat (file, &statbuf) < 0) + { + fprintf (stderr, "could not access file \"%s\"\n", file); + exit (EXIT_FAILURE); + } + +#if USE_ACL + { + int ret = file_has_acl (file, &statbuf); + if (ret < 0) + { + fprintf (stderr, "could not access the ACL of file \"%s\"\n", file); + exit (EXIT_FAILURE); + } + printf ("%s\n", ret ? "yes" : "no"); + } +#else + printf ("no\n"); +#endif + + return 0; +}
new file mode 100755 --- /dev/null +++ b/tests/test-file-has-acl.sh @@ -0,0 +1,325 @@ +#!/bin/sh + +# Show all commands when run with environment variable VERBOSE=yes. +test -z "$VERBOSE" || set -x + +# func_tmpdir +# creates a temporary directory. +# Sets variable +# - tmp pathname of freshly created temporary directory +func_tmpdir () +{ + # Use the environment variable TMPDIR, falling back to /tmp. This allows + # users to specify a different temporary directory, for example, if their + # /tmp is filled up or too small. + : ${TMPDIR=/tmp} + { + # Use the mktemp program if available. If not available, hide the error + # message. + tmp=`(umask 077 && mktemp -d "$TMPDIR/glXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" + } || + { + # Use a simple mkdir command. It is guaranteed to fail if the directory + # already exists. $RANDOM is bash specific and expands to empty in shells + # other than bash, ksh and zsh. Its use does not increase security; + # rather, it minimizes the probability of failure in a very cluttered /tmp + # directory. + tmp=$TMPDIR/gl$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || + { + echo "$0: cannot create a temporary directory in $TMPDIR" >&2 + exit 1 + } +} + +func_tmpdir +builddir=`pwd` +cd "$builddir" || + { + echo "$0: cannot determine build directory (unreadable parent dir?)" >&2 + exit 1 + } +# Switch to a temporary directory, to increase the likelihood that ACLs are +# supported on the current file system. (/tmp is usually locally mounted, +# whereas the build dir is sometimes NFS-mounted.) +( cd "$tmp" + + # Prepare tmpfile0. + rm -f tmpfile[0-9] tmp.err + echo "Simple contents" > tmpfile0 + chmod 600 tmpfile0 + + # Classification of the platform according to the programs available for + # manipulating ACLs. + # Possible values are: + # linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none. + # TODO: Support also native Win32 platforms (mingw). + acl_flavor=none + if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then + # Platforms with the getfacl and setfacl programs. + # Linux, FreeBSD, Solaris, Cygwin. + if (setfacl --help >/dev/null) 2>/dev/null; then + # Linux, Cygwin. + if (LC_ALL=C setfacl --help | grep ' --set-file' >/dev/null) 2>/dev/null; then + # Linux. + acl_flavor=linux + else + acl_flavor=cygwin + fi + else + # FreeBSD, Solaris. + if (LC_ALL=C setfacl 2>&1 | grep '\-x entries' >/dev/null) 2>/dev/null; then + # FreeBSD. + acl_flavor=freebsd + else + # Solaris. + acl_flavor=solaris + fi + fi + else + if (lsacl / >/dev/null) 2>/dev/null; then + # Platforms with the lsacl and chacl programs. + # HP-UX, sometimes also IRIX. + acl_flavor=hpux + else + if (getacl tmpfile0 >/dev/null) 2>/dev/null; then + # Tru64. + acl_flavor=osf1 + else + if (aclget tmpfile0 >/dev/null) 2>/dev/null; then + # AIX. + acl_flavor=aix + else + if (fsaclctl -v >/dev/null) 2>/dev/null; then + # MacOS X. + acl_flavor=macosx + else + if test -f /sbin/chacl; then + # IRIX. + acl_flavor=irix + fi + fi + fi + fi + fi + fi + + # func_test_has_acl file expected + # tests the result of the file_has_acl function on file, and checks that it + # matches the expected value. + func_test_has_acl () + { + res=`"$builddir"/test-file-has-acl${EXEEXT} "$1"` + test "$res" = "$2" || { + echo "file_has_acl(\"$1\") returned $res, expected $2" 1>&2 + exit 1 + } + } + + # func_test_file_has_acl file expected + # tests the result of the file_has_acl function on file, and checks that it + # matches the expected value. + func_test_file_has_acl () + { + res=`"$builddir"/test-file-has-acl${EXEEXT} "$1"` + test "$res" = "$2" || { + echo "file_has_acl(\"$1\") returned $res, expected $2" 1>&2 + exit 1 + } + } + + # func_test_has_acl file expected + # tests the result of the file_has_acl function on file, and checks that it + # matches the expected value, also taking into account the system's 'ls' + # program. + case $acl_flavor in + freebsd | solaris | hpux | macosx) + case $acl_flavor in + freebsd | solaris | hpux) acl_ls_option="-ld" ;; + macosx) acl_ls_option="-lde" ;; + esac + func_test_has_acl () + { + func_test_file_has_acl "$1" "$2" + case `/bin/ls $acl_ls_option "$1" | sed 1q` in + ??????????+*) + test "$2" = yes || { + echo "/bin/ls $acl_ls_option $1 shows an ACL, but expected $2" 1>&2 + exit 1 + } + ;; + ??????????" "*) + test "$2" = no || { + echo "/bin/ls $acl_ls_option $1 shows no ACL, but expected $2" 1>&2 + exit 1 + } + ;; + esac + } + ;; + irix) + func_test_has_acl () + { + func_test_file_has_acl "$1" "$2" + case `/bin/ls -ldD "$1" | sed 1q` in + *" []") + test "$2" = no || { + echo "/bin/ls -ldD $1 shows no ACL, but expected $2" 1>&2 + exit 1 + } + ;; + *) + test "$2" = yes || { + echo "/bin/ls -ldD $1 shows an ACL, but expected $2" 1>&2 + exit 1 + } + ;; + esac + } + ;; + *) + func_test_has_acl () + { + func_test_file_has_acl "$1" "$2" + } + ;; + esac + + func_test_has_acl tmpfile0 no + + if test $acl_flavor != none; then + # Use a user and group id different from the current one, to avoid + # redundant/ambiguous ACLs. + myuid=`id -u` + mygid=`id -g` + auid=1 + if test "$auid" = "$myuid"; then auid=2; fi + agid=1 + if test "$agid" = "$mygid"; then agid=2; fi + + case $acl_flavor in + linux | cygwin | freebsd | solaris) + + # Set an ACL for a user. + if setfacl -m user:$auid:1 tmpfile0; then + + func_test_has_acl tmpfile0 yes + + # Remove the ACL for the user. + case $acl_flavor in + linux) setfacl -x user:$auid tmpfile0 ;; + freebsd) setfacl -x user:$auid:1 tmpfile0 ;; + *) setfacl -d user:$auid:1 tmpfile0 ;; + esac + + # On Linux, the ACL for the mask is implicitly added. + # On Solaris, it is always there. + case $acl_flavor in + linux) func_test_has_acl tmpfile0 yes ;; + *) func_test_has_acl tmpfile0 no ;; + esac + + # Remove the ACL for the mask, if it was implicitly added. + case $acl_flavor in + linux | freebsd) setfacl -x mask: tmpfile0 ;; + *) setfacl -d mask: tmpfile0 ;; + esac + + func_test_has_acl tmpfile0 no + + fi + ;; + + hpux) + + # Set an ACL for a user. + orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'` + if chacl -r "${orig}($auid.%,--x)" tmpfile0; then + + func_test_has_acl tmpfile0 yes + + # Remove the ACL for the user. + chacl -d "($auid.%,--x)" tmpfile0 + + func_test_has_acl tmpfile0 no + + fi + ;; + + osf1) + + # Set an ACL for a user. + setacl -u user:$auid:1 tmpfile0 2> tmp.err + cat tmp.err 1>&2 + if grep 'Error:' tmp.err > /dev/null \ + || grep 'Operation not supported' tmp.err > /dev/null; then + : + else + + func_test_has_acl tmpfile0 yes + + # Remove the ACL for the user. + setacl -x user:$auid:1 tmpfile0 + + func_test_has_acl tmpfile0 no + + fi + ;; + + aix) + + # Set an ACL for a user. + { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo " permit --x u:$auid"; } | aclput tmpfile0 + if aclget tmpfile0 | grep enabled > /dev/null; then + + func_test_has_acl tmpfile0 yes + + # Remove the ACL for the user. + aclget tmpfile0 | grep -v ' u:[^ ]*$' | aclput tmpfile0 + + func_test_has_acl tmpfile0 no + + fi + ;; + + macosx) + + # Set an ACL for a user. + /bin/chmod +a "user:daemon allow execute" tmpfile0 + + func_test_has_acl tmpfile0 yes + + # Remove the ACL for the user. + /bin/chmod -a "user:daemon allow execute" tmpfile0 + + func_test_has_acl tmpfile0 no + + ;; + + irix) + + # Set an ACL for a user. + /sbin/chacl user::rw-,group::---,other::---,user:$auid:--x tmpfile0 2> tmp.err + cat tmp.err 1>&2 + if test -s tmp.err; then :; else + + func_test_has_acl tmpfile0 yes + + # Remove the ACL for the user. + /sbin/chacl user::rw-,group::---,other::--- tmpfile0 + + func_test_has_acl tmpfile0 no + + fi + ;; + + esac + fi + + rm -f tmpfile[0-9] tmp.err +) || exit 1 + +rm -rf "$tmp" +exit 0
new file mode 100644 --- /dev/null +++ b/tests/test-set-mode-acl.c @@ -0,0 +1,56 @@ +/* Test of setting an ACL equivalent to a mode. + Copyright (C) 2008 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* Written by Bruno Haible <bruno@clisp.org>, 2008. */ + +#include <config.h> + +#include "acl.h" + +#include <stdio.h> +#include <stdlib.h> + +#include "progname.h" + +#define ASSERT(expr) \ + do \ + { \ + if (!(expr)) \ + { \ + fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + fflush (stderr); \ + abort (); \ + } \ + } \ + while (0) + +int +main (int argc, char *argv[]) +{ + const char *file; + int mode; + + set_program_name (argv[0]); + + ASSERT (argc == 3); + + file = argv[1]; + mode = strtol (argv[2], NULL, 8); + + set_acl (file, -1, mode); + + return 0; +}
new file mode 100755 --- /dev/null +++ b/tests/test-set-mode-acl.sh @@ -0,0 +1,194 @@ +#!/bin/sh + +# Show all commands when run with environment variable VERBOSE=yes. +test -z "$VERBOSE" || set -x + +# func_tmpdir +# creates a temporary directory. +# Sets variable +# - tmp pathname of freshly created temporary directory +func_tmpdir () +{ + # Use the environment variable TMPDIR, falling back to /tmp. This allows + # users to specify a different temporary directory, for example, if their + # /tmp is filled up or too small. + : ${TMPDIR=/tmp} + { + # Use the mktemp program if available. If not available, hide the error + # message. + tmp=`(umask 077 && mktemp -d "$TMPDIR/glXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" + } || + { + # Use a simple mkdir command. It is guaranteed to fail if the directory + # already exists. $RANDOM is bash specific and expands to empty in shells + # other than bash, ksh and zsh. Its use does not increase security; + # rather, it minimizes the probability of failure in a very cluttered /tmp + # directory. + tmp=$TMPDIR/gl$$-$RANDOM + (umask 077 && mkdir "$tmp") + } || + { + echo "$0: cannot create a temporary directory in $TMPDIR" >&2 + exit 1 + } +} + +func_tmpdir +builddir=`pwd` +cd "$builddir" || + { + echo "$0: cannot determine build directory (unreadable parent dir?)" >&2 + exit 1 + } +# Switch to a temporary directory, to increase the likelihood that ACLs are +# supported on the current file system. (/tmp is usually locally mounted, +# whereas the build dir is sometimes NFS-mounted.) +( cd "$tmp" + + # Prepare tmpfile0. + rm -f tmpfile[0-9] + echo "Simple contents" > tmpfile0 + chmod 600 tmpfile0 + + # Classification of the platform according to the programs available for + # manipulating ACLs. + # Possible values are: + # linux, cygwin, freebsd, solaris, hpux, osf1, aix, macosx, irix, none. + # TODO: Support also native Win32 platforms (mingw). + acl_flavor=none + if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then + # Platforms with the getfacl and setfacl programs. + # Linux, FreeBSD, Solaris, Cygwin. + if (setfacl --help >/dev/null) 2>/dev/null; then + # Linux, Cygwin. + if (LC_ALL=C setfacl --help | grep ' --set-file' >/dev/null) 2>/dev/null; then + # Linux. + acl_flavor=linux + else + acl_flavor=cygwin + fi + else + # FreeBSD, Solaris. + if (LC_ALL=C setfacl 2>&1 | grep '\-x entries' >/dev/null) 2>/dev/null; then + # FreeBSD. + acl_flavor=freebsd + else + # Solaris. + acl_flavor=solaris + fi + fi + else + if (lsacl / >/dev/null) 2>/dev/null; then + # Platforms with the lsacl and chacl programs. + # HP-UX, sometimes also IRIX. + acl_flavor=hpux + else + if (getacl tmpfile0 >/dev/null) 2>/dev/null; then + # Tru64. + acl_flavor=osf1 + else + if (aclget tmpfile0 >/dev/null) 2>/dev/null; then + # AIX. + acl_flavor=aix + else + if (fsaclctl -v >/dev/null) 2>/dev/null; then + # MacOS X. + acl_flavor=macosx + else + if test -f /sbin/chacl; then + # IRIX. + acl_flavor=irix + fi + fi + fi + fi + fi + fi + + if test $acl_flavor != none; then + # Use a user and group id different from the current one, to avoid + # redundant/ambiguous ACLs. + myuid=`id -u` + mygid=`id -g` + auid=1 + if test "$auid" = "$myuid"; then auid=2; fi + agid=1 + if test "$agid" = "$mygid"; then agid=2; fi + fi + + for mode in 700 400 200 100 644 650 605 011 4700 2070; do + rm -f tmpfile0 tmpfile1 tmpfile2 + + # Prepare a file with no ACL. + echo "Anything" > tmpfile0 + # If a mode is not supported (e.g. 2070 on FreeBSD), we skip testing it. + if chmod $mode tmpfile0 2>/dev/null; then + modestring0=`ls -l tmpfile0 | dd ibs=1 count=10 2>/dev/null` + + # Prepare a file with no ACL. + echo "Some contents" > tmpfile1 + chmod 600 tmpfile1 + + # Try to set the ACL to only the given mode. + "$builddir"/test-set-mode-acl${EXEEXT} tmpfile1 $mode + # Verify that tmpfile1 has no ACL and has the desired mode. + modestring=`ls -l tmpfile1 | dd ibs=1 count=10 2>/dev/null` + if test "x$modestring" != "x$modestring0"; then + echo "mode = $mode: tmpfile1 has wrong mode: $modestring" 1>&2 + exit 1 + fi + if test `"$builddir"/test-file-has-acl${EXEEXT} tmpfile1` != no; then + echo "mode = $mode: tmpfile1 got an ACL" 1>&2 + exit 1 + fi + + if test $acl_flavor != none; then + + # Prepare a file with an ACL. + echo "Special contents" > tmpfile2 + chmod 600 tmpfile2 + # Set an ACL for a user. + case $acl_flavor in + linux | cygwin | freebsd | solaris) + setfacl -m user:$auid:1 tmpfile0 + ;; + hpux) + orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'` + chacl -r "${orig}($auid.%,--x)" tmpfile0 + ;; + osf1) + setacl -u user:$auid:1 tmpfile0 + ;; + aix) + { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo " permit --x u:$auid"; } | aclput tmpfile0 + ;; + macosx) + /bin/chmod +a "user:daemon allow execute" tmpfile0 + ;; + irix) + /sbin/chacl user::rw-,group::---,other::---,user:$auid:--x tmpfile0 + ;; + esac + + # Try to set the ACL to only the given mode. + "$builddir"/test-set-mode-acl${EXEEXT} tmpfile2 $mode + # Verify that tmpfile2 has no ACL and has the desired mode. + modestring=`ls -l tmpfile2 | dd ibs=1 count=10 2>/dev/null` + if test "x$modestring" != "x$modestring0"; then + echo "mode = $mode: tmpfile2 has wrong mode: $modestring" 1>&2 + exit 1 + fi + if test `"$builddir"/test-file-has-acl${EXEEXT} tmpfile2` != no; then + echo "mode = $mode: tmpfile2 still has an ACL" 1>&2 + exit 1 + fi + fi + fi + done + + rm -f tmpfile[0-9] +) || exit 1 + +rm -rf "$tmp" +exit 0