1#!/bin/sh
2
3# Show all commands when run with environment variable VERBOSE=yes.
4test -z "$VERBOSE" || set -x
5
6test "$USE_ACL" = 0 &&
7  {
8    echo "Skipping test: insufficient ACL support"
9    exit 77
10  }
11
12# func_tmpdir
13# creates a temporary directory.
14# Sets variable
15# - tmp             pathname of freshly created temporary directory
16func_tmpdir ()
17{
18  # Use the environment variable TMPDIR, falling back to /tmp. This allows
19  # users to specify a different temporary directory, for example, if their
20  # /tmp is filled up or too small.
21  : ${TMPDIR=/tmp}
22  {
23    # Use the mktemp program if available. If not available, hide the error
24    # message.
25    tmp=`(umask 077 && mktemp -d "$TMPDIR/glXXXXXX") 2>/dev/null` &&
26    test -n "$tmp" && test -d "$tmp"
27  } ||
28  {
29    # Use a simple mkdir command. It is guaranteed to fail if the directory
30    # already exists.  $RANDOM is bash specific and expands to empty in shells
31    # other than bash, ksh and zsh.  Its use does not increase security;
32    # rather, it minimizes the probability of failure in a very cluttered /tmp
33    # directory.
34    tmp=$TMPDIR/gl$$-$RANDOM
35    (umask 077 && mkdir "$tmp")
36  } ||
37  {
38    echo "$0: cannot create a temporary directory in $TMPDIR" >&2
39    exit 1
40  }
41}
42
43func_tmpdir
44# builddir may already be set by the script that invokes this one.
45case "$builddir" in
46  '') builddir=`pwd` ;;
47  /* | ?:*) ;;
48  *) builddir=`pwd`/$builddir ;;
49esac
50cd "$builddir" ||
51  {
52    echo "$0: cannot determine build directory (unreadable parent dir?)" >&2
53    exit 1
54  }
55# Switch to a temporary directory, to increase the likelihood that ACLs are
56# supported on the current file system. (/tmp is usually locally mounted,
57# whereas the build dir is sometimes NFS-mounted.)
58( cd "$tmp"
59
60  # Prepare tmpfile0.
61  rm -f tmpfile[0-9] tmp.err
62  echo "Simple contents" > tmpfile0
63  chmod 600 tmpfile0
64
65  # Classification of the platform according to the programs available for
66  # manipulating ACLs.
67  # Possible values are:
68  #   linux, cygwin, freebsd, solaris, hpux, hpuxjfs, osf1, aix, macosx, irix, none.
69  # TODO: Support also native Windows platforms (mingw).
70  acl_flavor=none
71  if (getfacl tmpfile0 >/dev/null) 2>/dev/null; then
72    # Platforms with the getfacl and setfacl programs.
73    # Linux, FreeBSD, Solaris, Cygwin.
74    if (setfacl --help >/dev/null) 2>/dev/null; then
75      # Linux, Cygwin.
76      if (LC_ALL=C setfacl --help | grep ' --set-file' >/dev/null) 2>/dev/null; then
77        # Linux.
78        acl_flavor=linux
79      else
80        acl_flavor=cygwin
81      fi
82    else
83      # FreeBSD, Solaris.
84      if (LC_ALL=C setfacl 2>&1 | grep '\-x entries' >/dev/null) 2>/dev/null; then
85        # FreeBSD.
86        acl_flavor=freebsd
87      else
88        # Solaris.
89        acl_flavor=solaris
90      fi
91    fi
92  else
93    if (lsacl / >/dev/null) 2>/dev/null; then
94      # Platforms with the lsacl and chacl programs.
95      # HP-UX, sometimes also IRIX.
96      if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
97        # HP-UX 11.11 or newer.
98        acl_flavor=hpuxjfs
99      else
100        # HP-UX 11.00.
101        acl_flavor=hpux
102      fi
103    else
104      if (getacl tmpfile0 >/dev/null) 2>/dev/null; then
105        # Tru64, NonStop Kernel.
106        if (getacl -m tmpfile0 >/dev/null) 2>/dev/null; then
107          # Tru64.
108          acl_flavor=osf1
109        else
110          # NonStop Kernel.
111          acl_flavor=nsk
112        fi
113      else
114        if (aclget tmpfile0 >/dev/null) 2>/dev/null; then
115          # AIX.
116          acl_flavor=aix
117        else
118          if (fsaclctl -v >/dev/null) 2>/dev/null; then
119            # Mac OS X.
120            acl_flavor=macosx
121          else
122            if test -f /sbin/chacl; then
123              # IRIX.
124              acl_flavor=irix
125            fi
126          fi
127        fi
128      fi
129    fi
130  fi
131
132  # func_test_file_has_acl file expected
133  # tests the result of the file_has_acl function on file, and checks that it
134  # matches the expected value.
135  func_test_file_has_acl ()
136  {
137    res=`${CHECKER} "$builddir"/test-file-has-acl${EXEEXT} "$1"`
138    test "$res" = "$2" || {
139      echo "file_has_acl(\"$1\") returned $res, expected $2" 1>&2
140      exit 1
141    }
142  }
143
144  # func_test_has_acl file expected
145  # tests the result of the file_has_acl function on file, and checks that it
146  # matches the expected value, also taking into account the system's 'ls'
147  # program.
148  case $acl_flavor in
149    freebsd | solaris | hpux | macosx)
150      case $acl_flavor in
151        freebsd | solaris | hpux) acl_ls_option="-ld" ;;
152        macosx)                   acl_ls_option="-lde" ;;
153      esac
154      func_test_has_acl ()
155      {
156        func_test_file_has_acl "$1" "$2"
157        case `/bin/ls $acl_ls_option "$1" | sed 1q` in
158          ??????????+*)
159            test "$2" = yes || {
160              echo "/bin/ls $acl_ls_option $1 shows an ACL, but expected $2" 1>&2
161              exit 1
162            }
163            ;;
164          ??????????" "*)
165            test "$2" = no || {
166              echo "/bin/ls $acl_ls_option $1 shows no ACL, but expected $2" 1>&2
167              exit 1
168            }
169            ;;
170        esac
171      }
172      ;;
173    irix)
174      func_test_has_acl ()
175      {
176        func_test_file_has_acl "$1" "$2"
177        case `/bin/ls -ldD "$1" | sed 1q` in
178          *" []")
179            test "$2" = no || {
180              echo "/bin/ls -ldD $1 shows no ACL, but expected $2" 1>&2
181              exit 1
182            }
183            ;;
184          *)
185            test "$2" = yes || {
186              echo "/bin/ls -ldD $1 shows an ACL, but expected $2" 1>&2
187              exit 1
188            }
189            ;;
190        esac
191      }
192      ;;
193    *)
194      func_test_has_acl ()
195      {
196        func_test_file_has_acl "$1" "$2"
197      }
198      ;;
199  esac
200
201  func_test_has_acl tmpfile0 no
202
203  mkdir tmpdir0
204  func_test_has_acl tmpdir0 no
205
206  if test $acl_flavor != none; then
207    # A POSIX compliant 'id' program.
208    if test -f /usr/xpg4/bin/id; then
209      ID=/usr/xpg4/bin/id
210    else
211      ID=id
212    fi
213    # Use a user and group id different from the current one, to avoid
214    # redundant/ambiguous ACLs.
215    myuid=`$ID -u`
216    mygid=`$ID -g`
217    auid=1
218    if test "$auid" = "$myuid"; then auid=2; fi
219    agid=1
220    if test "$agid" = "$mygid"; then agid=2; fi
221
222    case $acl_flavor in
223      linux | freebsd | solaris)
224
225        # Set an ACL for a user.
226        if setfacl -m user:$auid:1 tmpfile0; then
227
228          func_test_has_acl tmpfile0 yes
229
230          # Remove the ACL for the user.
231          case $acl_flavor in
232            linux)   setfacl -x user:$auid tmpfile0 ;;
233            freebsd) setfacl -x user:$auid:1 tmpfile0 ;;
234            *)       setfacl -d user:$auid:1 tmpfile0 ;;
235          esac
236
237          # On Linux and FreeBSD, the ACL for the mask is implicitly added.
238          # On Solaris, it is always there.
239          case $acl_flavor in
240            linux | freebsd) func_test_has_acl tmpfile0 yes ;;
241            *)               func_test_has_acl tmpfile0 no ;;
242          esac
243
244          # Remove the ACL for the mask, if it was implicitly added.
245          case $acl_flavor in
246            linux | freebsd) setfacl -x mask: tmpfile0 ;;
247            *)               setfacl -d mask: tmpfile0 ;;
248          esac
249
250          func_test_has_acl tmpfile0 no
251
252        fi
253        ;;
254
255      cygwin)
256
257        # Set an ACL for a group.
258        if setfacl -m group:0:1 tmpfile0; then
259
260          func_test_has_acl tmpfile0 yes
261
262          # Remove the ACL for the group.
263          setfacl -d group:0 tmpfile0
264
265          func_test_has_acl tmpfile0 no
266
267        fi
268        ;;
269
270      hpux | hpuxjfs)
271
272        # Set an ACL for a user.
273        orig=`lsacl tmpfile0 | sed -e 's/ tmpfile0$//'`
274        if chacl -r "${orig}($auid.%,--x)" tmpfile0; then
275
276          func_test_has_acl tmpfile0 yes
277
278          # Remove the ACL for the user.
279          chacl -d "($auid.%,--x)" tmpfile0
280
281          func_test_has_acl tmpfile0 no
282
283        else
284          if test $acl_flavor = hpuxjfs; then
285
286            # Set an ACL for a user.
287            setacl -m user:$auid:1 tmpfile0
288
289            func_test_has_acl tmpfile0 yes
290
291            # Remove the ACL for the user.
292            setacl -d user:$auid tmpfile0
293
294            func_test_has_acl tmpfile0 no
295
296          fi
297        fi
298        ;;
299
300      osf1)
301
302        # Set an ACL for a user.
303        setacl -u user:$auid:1 tmpfile0 2> tmp.err
304        cat tmp.err 1>&2
305        if grep 'Error:' tmp.err > /dev/null \
306           || grep 'Operation not supported' tmp.err > /dev/null; then
307          :
308        else
309
310          func_test_has_acl tmpfile0 yes
311
312          # Remove the ACL for the user.
313          setacl -x user:$auid:1 tmpfile0
314
315          func_test_has_acl tmpfile0 no
316
317        fi
318        ;;
319
320      nsk)
321
322        # Set an ACL for a user.
323        setacl -m user:$auid:1 tmpfile0
324
325        func_test_has_acl tmpfile0 yes
326
327        # Remove the ACL for the user.
328        setacl -d user:$auid tmpfile0
329
330        func_test_has_acl tmpfile0 no
331
332        ;;
333
334      aix)
335
336        # Set an ACL for a user.
337        { aclget tmpfile0 | sed -e 's/disabled$/enabled/'; echo "        permit --x u:$auid"; } | aclput tmpfile0
338        if aclget tmpfile0 | grep enabled > /dev/null; then
339
340          func_test_has_acl tmpfile0 yes
341
342          # Remove the ACL for the user.
343          aclget tmpfile0 | grep -v ' u:[^ ]*$' | aclput tmpfile0
344
345          func_test_has_acl tmpfile0 no
346
347        fi
348        ;;
349
350      macosx)
351
352        # Set an ACL for a user.
353        /bin/chmod +a "user:daemon allow execute" tmpfile0
354
355        func_test_has_acl tmpfile0 yes
356
357        # Remove the ACL for the user.
358        /bin/chmod -a "user:daemon allow execute" tmpfile0
359
360        func_test_has_acl tmpfile0 no
361
362        ;;
363
364      irix)
365
366        # Set an ACL for a user.
367        /sbin/chacl user::rw-,group::---,other::---,user:$auid:--x tmpfile0 2> tmp.err
368        cat tmp.err 1>&2
369        if test -s tmp.err; then :; else
370
371          func_test_has_acl tmpfile0 yes
372
373          # Remove the ACL for the user.
374          /sbin/chacl user::rw-,group::---,other::--- tmpfile0
375
376          func_test_has_acl tmpfile0 no
377
378        fi
379        ;;
380
381    esac
382  fi
383
384  rm -f tmpfile[0-9] tmp.err
385  rm -rf tmpdir0
386) || exit 1
387
388rm -rf "$tmp"
389exit 0
390