6dca5d9d8966176c42f8c7a56e265dc0675cebd4
[debian/tar] / gnu / file-has-acl.c
1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
3 /* Test whether a file has a nontrivial access control list.
4
5    Copyright (C) 2002-2003, 2005-2013 Free Software Foundation, Inc.
6
7    This program is free software: you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20    Written by Paul Eggert, Andreas Grünbacher, and Bruno Haible.  */
21
22 /* Without this pragma, gcc 4.7.0 20120126 may suggest that the
23    file_has_acl function might be candidate for attribute 'const'  */
24 #if (__GNUC__ == 4 && 6 <= __GNUC_MINOR__) || 4 < __GNUC__
25 # pragma GCC diagnostic ignored "-Wsuggest-attribute=const"
26 #endif
27
28 #include <config.h>
29
30 #include "acl.h"
31
32 #include "acl-internal.h"
33
34
35 #if USE_ACL && HAVE_ACL_GET_FILE
36
37 # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
38
39 /* ACL is an ACL, from a file, stored as type ACL_TYPE_EXTENDED.
40    Return 1 if the given ACL is non-trivial.
41    Return 0 if it is trivial.  */
42 int
43 acl_extended_nontrivial (acl_t acl)
44 {
45   /* acl is non-trivial if it is non-empty.  */
46   return (acl_entries (acl) > 0);
47 }
48
49 # else /* Linux, FreeBSD, IRIX, Tru64 */
50
51 /* ACL is an ACL, from a file, stored as type ACL_TYPE_ACCESS.
52    Return 1 if the given ACL is non-trivial.
53    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.
54    Return -1 and set errno upon failure to determine it.  */
55 int
56 acl_access_nontrivial (acl_t acl)
57 {
58   /* acl is non-trivial if it has some entries other than for "user::",
59      "group::", and "other::".  Normally these three should be present
60      at least, allowing us to write
61         return (3 < acl_entries (acl));
62      but the following code is more robust.  */
63 #  if HAVE_ACL_FIRST_ENTRY /* Linux, FreeBSD */
64
65   acl_entry_t ace;
66   int got_one;
67
68   for (got_one = acl_get_entry (acl, ACL_FIRST_ENTRY, &ace);
69        got_one > 0;
70        got_one = acl_get_entry (acl, ACL_NEXT_ENTRY, &ace))
71     {
72       acl_tag_t tag;
73       if (acl_get_tag_type (ace, &tag) < 0)
74         return -1;
75       if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
76         return 1;
77     }
78   return got_one;
79
80 #  else /* IRIX, Tru64 */
81 #   if HAVE_ACL_TO_SHORT_TEXT /* IRIX */
82   /* Don't use acl_get_entry: it is undocumented.  */
83
84   int count = acl->acl_cnt;
85   int i;
86
87   for (i = 0; i < count; i++)
88     {
89       acl_entry_t ace = &acl->acl_entry[i];
90       acl_tag_t tag = ace->ae_tag;
91
92       if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ
93             || tag == ACL_OTHER_OBJ))
94         return 1;
95     }
96   return 0;
97
98 #   endif
99 #   if HAVE_ACL_FREE_TEXT /* Tru64 */
100   /* Don't use acl_get_entry: it takes only one argument and does not work.  */
101
102   int count = acl->acl_num;
103   acl_entry_t ace;
104
105   for (ace = acl->acl_first; count > 0; ace = ace->next, count--)
106     {
107       acl_tag_t tag;
108       acl_perm_t perm;
109
110       tag = ace->entry->acl_type;
111       if (!(tag == ACL_USER_OBJ || tag == ACL_GROUP_OBJ || tag == ACL_OTHER))
112         return 1;
113
114       perm = ace->entry->acl_perm;
115       /* On Tru64, perm can also contain non-standard bits such as
116          PERM_INSERT, PERM_DELETE, PERM_MODIFY, PERM_LOOKUP, ... */
117       if ((perm & ~(ACL_READ | ACL_WRITE | ACL_EXECUTE)) != 0)
118         return 1;
119     }
120   return 0;
121
122 #   endif
123 #  endif
124 }
125
126 # endif
127
128
129 #elif USE_ACL && HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
130
131 /* Test an ACL retrieved with GETACL.
132    Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
133    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
134 int
135 acl_nontrivial (int count, aclent_t *entries)
136 {
137   int i;
138
139   for (i = 0; i < count; i++)
140     {
141       aclent_t *ace = &entries[i];
142
143       /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
144          If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
145          We don't need to check ace->a_id in these cases.  */
146       if (!(ace->a_type == USER_OBJ
147             || ace->a_type == GROUP_OBJ
148             || ace->a_type == OTHER_OBJ
149             /* Note: Cygwin does not return a CLASS_OBJ ("mask:") entry
150                sometimes.  */
151             || ace->a_type == CLASS_OBJ))
152         return 1;
153     }
154   return 0;
155 }
156
157 # ifdef ACE_GETACL
158
159 /* A shortcut for a bitmask.  */
160 #  define NEW_ACE_WRITEA_DATA (NEW_ACE_WRITE_DATA | NEW_ACE_APPEND_DATA)
161
162 /* Test an ACL retrieved with ACE_GETACL.
163    Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
164    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
165 int
166 acl_ace_nontrivial (int count, ace_t *entries)
167 {
168   int i;
169
170   /* The flags in the ace_t structure changed in a binary incompatible way
171      when ACL_NO_TRIVIAL etc. were introduced in <sys/acl.h> version 1.15.
172      How to distinguish the two conventions at runtime?
173      In the old convention, usually three ACEs have a_flags = ACE_OWNER /
174      ACE_GROUP / ACE_OTHER, in the range 0x0100..0x0400.  In the new
175      convention, these values are not used.  */
176   int old_convention = 0;
177
178   for (i = 0; i < count; i++)
179     if (entries[i].a_flags & (OLD_ACE_OWNER | OLD_ACE_GROUP | OLD_ACE_OTHER))
180       {
181         old_convention = 1;
182         break;
183       }
184
185   if (old_convention)
186     /* Running on Solaris 10.  */
187     for (i = 0; i < count; i++)
188       {
189         ace_t *ace = &entries[i];
190
191         /* Note:
192            If ace->a_flags = ACE_OWNER, ace->a_who is the st_uid from stat().
193            If ace->a_flags = ACE_GROUP, ace->a_who is the st_gid from stat().
194            We don't need to check ace->a_who in these cases.  */
195         if (!(ace->a_type == OLD_ALLOW
196               && (ace->a_flags == OLD_ACE_OWNER
197                   || ace->a_flags == OLD_ACE_GROUP
198                   || ace->a_flags == OLD_ACE_OTHER)))
199           return 1;
200       }
201   else
202     {
203       /* Running on Solaris 10 (newer version) or Solaris 11.  */
204       unsigned int access_masks[6] =
205         {
206           0, /* owner@ deny */
207           0, /* owner@ allow */
208           0, /* group@ deny */
209           0, /* group@ allow */
210           0, /* everyone@ deny */
211           0  /* everyone@ allow */
212         };
213
214       for (i = 0; i < count; i++)
215         {
216           ace_t *ace = &entries[i];
217           unsigned int index1;
218           unsigned int index2;
219
220           if (ace->a_type == NEW_ACE_ACCESS_ALLOWED_ACE_TYPE)
221             index1 = 1;
222           else if (ace->a_type == NEW_ACE_ACCESS_DENIED_ACE_TYPE)
223             index1 = 0;
224           else
225             return 1;
226
227           if (ace->a_flags == NEW_ACE_OWNER)
228             index2 = 0;
229           else if (ace->a_flags == (NEW_ACE_GROUP | NEW_ACE_IDENTIFIER_GROUP))
230             index2 = 2;
231           else if (ace->a_flags == NEW_ACE_EVERYONE)
232             index2 = 4;
233           else
234             return 1;
235
236           access_masks[index1 + index2] |= ace->a_access_mask;
237         }
238
239       /* The same bit shouldn't be both allowed and denied.  */
240       if (access_masks[0] & access_masks[1])
241         return 1;
242       if (access_masks[2] & access_masks[3])
243         return 1;
244       if (access_masks[4] & access_masks[5])
245         return 1;
246
247       /* Check minimum masks.  */
248       if ((NEW_ACE_WRITE_NAMED_ATTRS
249            | NEW_ACE_WRITE_ATTRIBUTES
250            | NEW_ACE_WRITE_ACL
251            | NEW_ACE_WRITE_OWNER)
252           & ~ access_masks[1])
253         return 1;
254       access_masks[1] &= ~(NEW_ACE_WRITE_NAMED_ATTRS
255                            | NEW_ACE_WRITE_ATTRIBUTES
256                            | NEW_ACE_WRITE_ACL
257                            | NEW_ACE_WRITE_OWNER);
258       if ((NEW_ACE_READ_NAMED_ATTRS
259            | NEW_ACE_READ_ATTRIBUTES
260            | NEW_ACE_READ_ACL
261            | NEW_ACE_SYNCHRONIZE)
262           & ~ access_masks[5])
263         return 1;
264       access_masks[5] &= ~(NEW_ACE_READ_NAMED_ATTRS
265                            | NEW_ACE_READ_ATTRIBUTES
266                            | NEW_ACE_READ_ACL
267                            | NEW_ACE_SYNCHRONIZE);
268
269       /* Check the allowed or denied bits.  */
270       switch ((access_masks[0] | access_masks[1])
271               & ~(NEW_ACE_READ_NAMED_ATTRS
272                   | NEW_ACE_READ_ATTRIBUTES
273                   | NEW_ACE_READ_ACL
274                   | NEW_ACE_SYNCHRONIZE))
275         {
276         case 0:
277         case NEW_ACE_READ_DATA:
278         case                     NEW_ACE_WRITEA_DATA:
279         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
280         case                                           NEW_ACE_EXECUTE:
281         case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
282         case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
283         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
284           break;
285         default:
286           return 1;
287         }
288       switch ((access_masks[2] | access_masks[3])
289               & ~(NEW_ACE_READ_NAMED_ATTRS
290                   | NEW_ACE_READ_ATTRIBUTES
291                   | NEW_ACE_READ_ACL
292                   | NEW_ACE_SYNCHRONIZE))
293         {
294         case 0:
295         case NEW_ACE_READ_DATA:
296         case                     NEW_ACE_WRITEA_DATA:
297         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
298         case                                           NEW_ACE_EXECUTE:
299         case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
300         case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
301         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
302           break;
303         default:
304           return 1;
305         }
306       switch ((access_masks[4] | access_masks[5])
307               & ~(NEW_ACE_WRITE_NAMED_ATTRS
308                   | NEW_ACE_WRITE_ATTRIBUTES
309                   | NEW_ACE_WRITE_ACL
310                   | NEW_ACE_WRITE_OWNER))
311         {
312         case 0:
313         case NEW_ACE_READ_DATA:
314         case                     NEW_ACE_WRITEA_DATA:
315         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA:
316         case                                           NEW_ACE_EXECUTE:
317         case NEW_ACE_READ_DATA |                       NEW_ACE_EXECUTE:
318         case                     NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
319         case NEW_ACE_READ_DATA | NEW_ACE_WRITEA_DATA | NEW_ACE_EXECUTE:
320           break;
321         default:
322           return 1;
323         }
324
325       /* Check that the NEW_ACE_WRITE_DATA and NEW_ACE_APPEND_DATA bits are
326          either both allowed or both denied.  */
327       if (((access_masks[0] & NEW_ACE_WRITE_DATA) != 0)
328           != ((access_masks[0] & NEW_ACE_APPEND_DATA) != 0))
329         return 1;
330       if (((access_masks[2] & NEW_ACE_WRITE_DATA) != 0)
331           != ((access_masks[2] & NEW_ACE_APPEND_DATA) != 0))
332         return 1;
333       if (((access_masks[4] & NEW_ACE_WRITE_DATA) != 0)
334           != ((access_masks[4] & NEW_ACE_APPEND_DATA) != 0))
335         return 1;
336     }
337
338   return 0;
339 }
340
341 # endif
342
343 #elif USE_ACL && HAVE_GETACL /* HP-UX */
344
345 /* Return 1 if the given ACL is non-trivial.
346    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
347 int
348 acl_nontrivial (int count, struct acl_entry *entries, struct stat *sb)
349 {
350   int i;
351
352   for (i = 0; i < count; i++)
353     {
354       struct acl_entry *ace = &entries[i];
355
356       if (!((ace->uid == sb->st_uid && ace->gid == ACL_NSGROUP)
357             || (ace->uid == ACL_NSUSER && ace->gid == sb->st_gid)
358             || (ace->uid == ACL_NSUSER && ace->gid == ACL_NSGROUP)))
359         return 1;
360     }
361   return 0;
362 }
363
364 # if HAVE_ACLV_H /* HP-UX >= 11.11 */
365
366 /* Return 1 if the given ACL is non-trivial.
367    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
368 int
369 aclv_nontrivial (int count, struct acl *entries)
370 {
371   int i;
372
373   for (i = 0; i < count; i++)
374     {
375       struct acl *ace = &entries[i];
376
377       /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
378          If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
379          We don't need to check ace->a_id in these cases.  */
380       if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
381             || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
382             || ace->a_type == CLASS_OBJ
383             || ace->a_type == OTHER_OBJ))
384         return 1;
385     }
386   return 0;
387 }
388
389 # endif
390
391 #elif USE_ACL && (HAVE_ACLX_GET || HAVE_STATACL) /* AIX */
392
393 /* Return 1 if the given ACL is non-trivial.
394    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
395 int
396 acl_nontrivial (struct acl *a)
397 {
398   /* The normal way to iterate through an ACL is like this:
399        struct acl_entry *ace;
400        for (ace = a->acl_ext; ace != acl_last (a); ace = acl_nxt (ace))
401          {
402            struct ace_id *aei;
403            switch (ace->ace_type)
404              {
405              case ACC_PERMIT:
406              case ACC_DENY:
407              case ACC_SPECIFY:
408                ...;
409              }
410            for (aei = ace->ace_id; aei != id_last (ace); aei = id_nxt (aei))
411              ...
412          }
413    */
414   return (acl_last (a) != a->acl_ext ? 1 : 0);
415 }
416
417 # if HAVE_ACLX_GET && defined ACL_AIX_WIP /* newer AIX */
418
419 /* Return 1 if the given ACL is non-trivial.
420    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
421 int
422 acl_nfs4_nontrivial (nfs4_acl_int_t *a)
423 {
424 #  if 1 /* let's try this first */
425   return (a->aclEntryN > 0 ? 1 : 0);
426 #  else
427   int count = a->aclEntryN;
428   int i;
429
430   for (i = 0; i < count; i++)
431     {
432       nfs4_ace_int_t *ace = &a->aclEntry[i];
433
434       if (!((ace->flags & ACE4_ID_SPECIAL) != 0
435             && (ace->aceWho.special_whoid == ACE4_WHO_OWNER
436                 || ace->aceWho.special_whoid == ACE4_WHO_GROUP
437                 || ace->aceWho.special_whoid == ACE4_WHO_EVERYONE)
438             && ace->aceType == ACE4_ACCESS_ALLOWED_ACE_TYPE
439             && ace->aceFlags == 0
440             && (ace->aceMask & ~(ACE4_READ_DATA | ACE4_LIST_DIRECTORY
441                                  | ACE4_WRITE_DATA | ACE4_ADD_FILE
442                                  | ACE4_EXECUTE)) == 0))
443         return 1;
444     }
445   return 0;
446 #  endif
447 }
448
449 # endif
450
451 #elif USE_ACL && HAVE_ACLSORT /* NonStop Kernel */
452
453 /* Test an ACL retrieved with ACL_GET.
454    Return 1 if the given ACL, consisting of COUNT entries, is non-trivial.
455    Return 0 if it is trivial, i.e. equivalent to a simple stat() mode.  */
456 int
457 acl_nontrivial (int count, struct acl *entries)
458 {
459   int i;
460
461   for (i = 0; i < count; i++)
462     {
463       struct acl *ace = &entries[i];
464
465       /* Note: If ace->a_type = USER_OBJ, ace->a_id is the st_uid from stat().
466          If ace->a_type = GROUP_OBJ, ace->a_id is the st_gid from stat().
467          We don't need to check ace->a_id in these cases.  */
468       if (!(ace->a_type == USER_OBJ /* no need to check ace->a_id here */
469             || ace->a_type == GROUP_OBJ /* no need to check ace->a_id here */
470             || ace->a_type == CLASS_OBJ
471             || ace->a_type == OTHER_OBJ))
472         return 1;
473     }
474   return 0;
475 }
476
477 #endif
478
479
480 /* Return 1 if NAME has a nontrivial access control list, 0 if NAME
481    only has no or a base access control list, and -1 (setting errno)
482    on error.  SB must be set to the stat buffer of NAME, obtained
483    through stat() or lstat().  */
484
485 int
486 file_has_acl (char const *name, struct stat const *sb)
487 {
488 #if USE_ACL
489   if (! S_ISLNK (sb->st_mode))
490     {
491 # if HAVE_ACL_GET_FILE
492
493       /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
494       /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
495       int ret;
496
497       if (HAVE_ACL_EXTENDED_FILE) /* Linux */
498         {
499           /* On Linux, acl_extended_file is an optimized function: It only
500              makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
501              ACL_TYPE_DEFAULT.  */
502           ret = acl_extended_file (name);
503         }
504       else /* FreeBSD, Mac OS X, IRIX, Tru64 */
505         {
506 #  if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
507           /* On Mac OS X, acl_get_file (name, ACL_TYPE_ACCESS)
508              and acl_get_file (name, ACL_TYPE_DEFAULT)
509              always return NULL / EINVAL.  There is no point in making
510              these two useless calls.  The real ACL is retrieved through
511              acl_get_file (name, ACL_TYPE_EXTENDED).  */
512           acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
513           if (acl)
514             {
515               ret = acl_extended_nontrivial (acl);
516               acl_free (acl);
517             }
518           else
519             ret = -1;
520 #  else /* FreeBSD, IRIX, Tru64 */
521           acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
522           if (acl)
523             {
524               int saved_errno;
525
526               ret = acl_access_nontrivial (acl);
527               saved_errno = errno;
528               acl_free (acl);
529               errno = saved_errno;
530 #   if HAVE_ACL_FREE_TEXT /* Tru64 */
531               /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
532                  returns NULL with errno not set.  There is no point in
533                  making this call.  */
534 #   else /* FreeBSD, IRIX */
535               /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
536                  and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
537                  either both succeed or both fail; it depends on the
538                  file system.  Therefore there is no point in making the second
539                  call if the first one already failed.  */
540               if (ret == 0 && S_ISDIR (sb->st_mode))
541                 {
542                   acl = acl_get_file (name, ACL_TYPE_DEFAULT);
543                   if (acl)
544                     {
545                       ret = (0 < acl_entries (acl));
546                       acl_free (acl);
547                     }
548                   else
549                     ret = -1;
550                 }
551 #   endif
552             }
553           else
554             ret = -1;
555 #  endif
556         }
557       if (ret < 0)
558         return - acl_errno_valid (errno);
559       return ret;
560
561 # elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
562
563 #  if defined ACL_NO_TRIVIAL
564
565       /* Solaris 10 (newer version), which has additional API declared in
566          <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
567          acl_fromtext, ...).  */
568       return acl_trivial (name);
569
570 #  else /* Solaris, Cygwin, general case */
571
572       /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
573          of Unixware.  The acl() call returns the access and default ACL both
574          at once.  */
575       {
576         /* Initially, try to read the entries into a stack-allocated buffer.
577            Use malloc if it does not fit.  */
578         enum
579           {
580             alloc_init = 4000 / sizeof (aclent_t), /* >= 3 */
581             alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (aclent_t))
582           };
583         aclent_t buf[alloc_init];
584         size_t alloc = alloc_init;
585         aclent_t *entries = buf;
586         aclent_t *malloced = NULL;
587         int count;
588
589         for (;;)
590           {
591             count = acl (name, GETACL, alloc, entries);
592             if (count < 0 && errno == ENOSPC)
593               {
594                 /* Increase the size of the buffer.  */
595                 free (malloced);
596                 if (alloc > alloc_max / 2)
597                   {
598                     errno = ENOMEM;
599                     return -1;
600                   }
601                 alloc = 2 * alloc; /* <= alloc_max */
602                 entries = malloced =
603                   (aclent_t *) malloc (alloc * sizeof (aclent_t));
604                 if (entries == NULL)
605                   {
606                     errno = ENOMEM;
607                     return -1;
608                   }
609                 continue;
610               }
611             break;
612           }
613         if (count < 0)
614           {
615             if (errno == ENOSYS || errno == ENOTSUP)
616               ;
617             else
618               {
619                 int saved_errno = errno;
620                 free (malloced);
621                 errno = saved_errno;
622                 return -1;
623               }
624           }
625         else if (count == 0)
626           ;
627         else
628           {
629             /* Don't use MIN_ACL_ENTRIES:  It's set to 4 on Cygwin, but Cygwin
630                returns only 3 entries for files with no ACL.  But this is safe:
631                If there are more than 4 entries, there cannot be only the
632                "user::", "group::", "other:", and "mask:" entries.  */
633             if (count > 4)
634               {
635                 free (malloced);
636                 return 1;
637               }
638
639             if (acl_nontrivial (count, entries))
640               {
641                 free (malloced);
642                 return 1;
643               }
644           }
645         free (malloced);
646       }
647
648 #   ifdef ACE_GETACL
649       /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
650          file systems (whereas the other ones are used in UFS file systems).  */
651       {
652         /* Initially, try to read the entries into a stack-allocated buffer.
653            Use malloc if it does not fit.  */
654         enum
655           {
656             alloc_init = 4000 / sizeof (ace_t), /* >= 3 */
657             alloc_max = MIN (INT_MAX, SIZE_MAX / sizeof (ace_t))
658           };
659         ace_t buf[alloc_init];
660         size_t alloc = alloc_init;
661         ace_t *entries = buf;
662         ace_t *malloced = NULL;
663         int count;
664
665         for (;;)
666           {
667             count = acl (name, ACE_GETACL, alloc, entries);
668             if (count < 0 && errno == ENOSPC)
669               {
670                 /* Increase the size of the buffer.  */
671                 free (malloced);
672                 if (alloc > alloc_max / 2)
673                   {
674                     errno = ENOMEM;
675                     return -1;
676                   }
677                 alloc = 2 * alloc; /* <= alloc_max */
678                 entries = malloced = (ace_t *) malloc (alloc * sizeof (ace_t));
679                 if (entries == NULL)
680                   {
681                     errno = ENOMEM;
682                     return -1;
683                   }
684                 continue;
685               }
686             break;
687           }
688         if (count < 0)
689           {
690             if (errno == ENOSYS || errno == EINVAL)
691               ;
692             else
693               {
694                 int saved_errno = errno;
695                 free (malloced);
696                 errno = saved_errno;
697                 return -1;
698               }
699           }
700         else if (count == 0)
701           ;
702         else
703           {
704             /* In the old (original Solaris 10) convention:
705                If there are more than 3 entries, there cannot be only the
706                ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
707                In the newer Solaris 10 and Solaris 11 convention:
708                If there are more than 6 entries, there cannot be only the
709                ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
710                NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
711                NEW_ACE_ACCESS_DENIED_ACE_TYPE.  */
712             if (count > 6)
713               {
714                 free (malloced);
715                 return 1;
716               }
717
718             if (acl_ace_nontrivial (count, entries))
719               {
720                 free (malloced);
721                 return 1;
722               }
723           }
724         free (malloced);
725       }
726 #   endif
727
728       return 0;
729 #  endif
730
731 # elif HAVE_GETACL /* HP-UX */
732
733       {
734         struct acl_entry entries[NACLENTRIES];
735         int count;
736
737         count = getacl (name, NACLENTRIES, entries);
738
739         if (count < 0)
740           {
741             /* ENOSYS is seen on newer HP-UX versions.
742                EOPNOTSUPP is typically seen on NFS mounts.
743                ENOTSUP was seen on Quantum StorNext file systems (cvfs).  */
744             if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
745               ;
746             else
747               return -1;
748           }
749         else if (count == 0)
750           return 0;
751         else /* count > 0 */
752           {
753             if (count > NACLENTRIES)
754               /* If NACLENTRIES cannot be trusted, use dynamic memory
755                  allocation.  */
756               abort ();
757
758             /* If there are more than 3 entries, there cannot be only the
759                (uid,%), (%,gid), (%,%) entries.  */
760             if (count > 3)
761               return 1;
762
763             {
764               struct stat statbuf;
765
766               if (stat (name, &statbuf) < 0)
767                 return -1;
768
769               return acl_nontrivial (count, entries, &statbuf);
770             }
771           }
772       }
773
774 #  if HAVE_ACLV_H /* HP-UX >= 11.11 */
775
776       {
777         struct acl entries[NACLVENTRIES];
778         int count;
779
780         count = acl ((char *) name, ACL_GET, NACLVENTRIES, entries);
781
782         if (count < 0)
783           {
784             /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
785                EINVAL is seen on NFS in HP-UX 11.31.  */
786             if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
787               ;
788             else
789               return -1;
790           }
791         else if (count == 0)
792           return 0;
793         else /* count > 0 */
794           {
795             if (count > NACLVENTRIES)
796               /* If NACLVENTRIES cannot be trusted, use dynamic memory
797                  allocation.  */
798               abort ();
799
800             /* If there are more than 4 entries, there cannot be only the
801                four base ACL entries.  */
802             if (count > 4)
803               return 1;
804
805             return aclv_nontrivial (count, entries);
806           }
807       }
808
809 #  endif
810
811 # elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */
812
813       acl_type_t type;
814       char aclbuf[1024];
815       void *acl = aclbuf;
816       size_t aclsize = sizeof (aclbuf);
817       mode_t mode;
818
819       for (;;)
820         {
821           /* The docs say that type being 0 is equivalent to ACL_ANY, but it
822              is not true, in AIX 5.3.  */
823           type.u64 = ACL_ANY;
824           if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
825             break;
826           if (errno == ENOSYS)
827             return 0;
828           if (errno != ENOSPC)
829             {
830               if (acl != aclbuf)
831                 {
832                   int saved_errno = errno;
833                   free (acl);
834                   errno = saved_errno;
835                 }
836               return -1;
837             }
838           aclsize = 2 * aclsize;
839           if (acl != aclbuf)
840             free (acl);
841           acl = malloc (aclsize);
842           if (acl == NULL)
843             {
844               errno = ENOMEM;
845               return -1;
846             }
847         }
848
849       if (type.u64 == ACL_AIXC)
850         {
851           int result = acl_nontrivial ((struct acl *) acl);
852           if (acl != aclbuf)
853             free (acl);
854           return result;
855         }
856       else if (type.u64 == ACL_NFS4)
857         {
858           int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
859           if (acl != aclbuf)
860             free (acl);
861           return result;
862         }
863       else
864         {
865           /* A newer type of ACL has been introduced in the system.
866              We should better support it.  */
867           if (acl != aclbuf)
868             free (acl);
869           errno = EINVAL;
870           return -1;
871         }
872
873 # elif HAVE_STATACL /* older AIX */
874
875       union { struct acl a; char room[4096]; } u;
876
877       if (statacl (name, STX_NORMAL, &u.a, sizeof (u)) < 0)
878         return -1;
879
880       return acl_nontrivial (&u.a);
881
882 # elif HAVE_ACLSORT /* NonStop Kernel */
883
884       {
885         struct acl entries[NACLENTRIES];
886         int count;
887
888         count = acl ((char *) name, ACL_GET, NACLENTRIES, entries);
889
890         if (count < 0)
891           {
892             if (errno == ENOSYS || errno == ENOTSUP)
893               ;
894             else
895               return -1;
896           }
897         else if (count == 0)
898           return 0;
899         else /* count > 0 */
900           {
901             if (count > NACLENTRIES)
902               /* If NACLENTRIES cannot be trusted, use dynamic memory
903                  allocation.  */
904               abort ();
905
906             /* If there are more than 4 entries, there cannot be only the
907                four base ACL entries.  */
908             if (count > 4)
909               return 1;
910
911             return acl_nontrivial (count, entries);
912           }
913       }
914
915 # endif
916     }
917 #endif
918
919   return 0;
920 }