#!/bin/sh # Show all commands when run with environment variable VERBOSE=yes. test -z $VERBOSE || set -x test $USE_ACL = 0 && do { echo "Skipping test: insufficient ACL support" exit 77 } # func_tmpdir # creates a temporary directory. # Sets variable # - tmp pathname of freshly created temporary directory proc 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) do { # Use the mktemp program if available. If not available, hide the error # message. setglobal tmp = $[shell {umask 077 && mktemp -d "$TMPDIR/glXXXXXX"}] && test -n $tmp && test -d $tmp } || do { # 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. setglobal tmp = "$TMPDIR/gl$Pid-$RANDOM" shell {umask 077 && mkdir $tmp} } || do { echo "$0: cannot create a temporary directory in $TMPDIR" > !2 exit 1 } } func_tmpdir setglobal builddir = $[pwd] cd $builddir || do { 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.) shell { 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, hpuxjfs, osf1, aix, macosx, irix, none. # TODO: Support also native Windows platforms (mingw). setglobal acl_flavor = 'none' if shell {getfacl tmpfile0 >/dev/null} 2>/dev/null { # Platforms with the getfacl and setfacl programs. # Linux, FreeBSD, Solaris, Cygwin. if shell {setfacl --help >/dev/null} 2>/dev/null { # Linux, Cygwin. if shell {env LC_ALL=C setfacl --help | grep ' --set-file' >/dev/null} 2>/dev/null { # Linux. setglobal acl_flavor = 'linux' } else { setglobal acl_flavor = 'cygwin' } } else { # FreeBSD, Solaris. if shell {env LC_ALL=C setfacl !2 > !1 | grep '\-x entries' >/dev/null} 2>/dev/null { # FreeBSD. setglobal acl_flavor = 'freebsd' } else { # Solaris. setglobal acl_flavor = 'solaris' } } } else { if shell {lsacl / >/dev/null} 2>/dev/null { # Platforms with the lsacl and chacl programs. # HP-UX, sometimes also IRIX. if shell {getacl tmpfile0 >/dev/null} 2>/dev/null { # HP-UX 11.11 or newer. setglobal acl_flavor = 'hpuxjfs' } else { # HP-UX 11.00. setglobal acl_flavor = 'hpux' } } else { if shell {getacl tmpfile0 >/dev/null} 2>/dev/null { # Tru64, NonStop Kernel. if shell {getacl -m tmpfile0 >/dev/null} 2>/dev/null { # Tru64. setglobal acl_flavor = 'osf1' } else { # NonStop Kernel. setglobal acl_flavor = 'nsk' } } else { if shell {aclget tmpfile0 >/dev/null} 2>/dev/null { # AIX. setglobal acl_flavor = 'aix' } else { if shell {fsaclctl -v >/dev/null} 2>/dev/null { # Mac OS X. setglobal acl_flavor = 'macosx' } else { if test -f /sbin/chacl { # IRIX. setglobal acl_flavor = 'irix' } } } } } } if test $acl_flavor != none { # A POSIX compliant 'id' program. if test -f /usr/xpg4/bin/id { setglobal ID = '/usr/xpg4/bin/id' } else { setglobal ID = 'id' } # Use a user and group id different from the current one, to avoid # redundant/ambiguous ACLs. setglobal myuid = $[$ID -u] setglobal mygid = $[$ID -g] setglobal auid = '1' if test $auid = $myuid { setglobal auid = '2'; } setglobal agid = '1' if test $agid = $mygid { setglobal agid = '2'; } } for mode in [700 400 200 100 644 650 605 011 4700 2070] { 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 { setglobal 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. setglobal modestring = $[ls -l tmpfile1 | dd ibs=1 count=10 !2 >/dev/null] if test "x$modestring" != "x$modestring0" { echo "mode = $mode: tmpfile1 has wrong mode: $modestring" !1 > !2 exit 1 } if test $["$builddir"/test-file-has-acl$(EXEEXT) tmpfile1] != no { echo "mode = $mode: tmpfile1 got an ACL" !1 > !2 exit 1 } if test $acl_flavor != none { # Prepare a file with an ACL. echo "Special contents" > tmpfile2 chmod 600 tmpfile2 # Set an ACL for a user (or group). match $acl_flavor { with linux | freebsd | solaris setfacl -m user:$auid:1 tmpfile0 with cygwin setfacl -m group:0:1 tmpfile0 with hpux setglobal orig = $[lsacl tmpfile0 | sed -e 's/ tmpfile0$//] chacl -r "$(orig)($auid.%,--x)" tmpfile0 with hpuxjfs setglobal orig = $[lsacl tmpfile0 | sed -e 's/ tmpfile0$//] chacl -r "$(orig)($auid.%,--x)" tmpfile0 \ || setacl -m user:$auid:1 tmpfile0 with osf1 setacl -u user:$auid:1 tmpfile0 with nsk setacl -m user:$auid:1 tmpfile0 with aix do { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo " permit --x u:$auid"; } | aclput tmpfile0 with macosx /bin/chmod +a "user:daemon allow execute" tmpfile0 with irix /sbin/chacl user::rw-,group::---,other::---,user:$auid:--x tmpfile0 } # 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. setglobal modestring = $[ls -l tmpfile2 | dd ibs=1 count=10 !2 >/dev/null] if test "x$modestring" != "x$modestring0" { echo "mode = $mode: tmpfile2 has wrong mode: $modestring" !1 > !2 exit 1 } if test $["$builddir"/test-file-has-acl$(EXEEXT) tmpfile2] != no { echo "mode = $mode: tmpfile2 still has an ACL" !1 > !2 exit 1 } } } } rm -f tmpfile[0-9] } || exit 1 rm -rf $tmp exit 0