示例#1
0
static AIXJFS2_ACL_T *aixjfs2_getacl_alloc(const char *fname, acl_type_t *type)
{
	AIXJFS2_ACL_T *acl;
	size_t len = 200;
	mode_t mode;
	int ret;
	uint64_t ctl_flag=0;
	TALLOC_CTX	*mem_ctx;

	mem_ctx = talloc_tos();
	acl = (AIXJFS2_ACL_T *)TALLOC_SIZE(mem_ctx, len);
	if (acl == NULL) {
		errno = ENOMEM;
		return NULL;
	}

	if(type->u64 == ACL_ANY) {
		ctl_flag = ctl_flag | GET_ACLINFO_ONLY;
	}

	ret = aclx_get((char *)fname, ctl_flag, type, acl, &len, &mode);
	if ((ret != 0) && (errno == ENOSPC)) {
		len = aixacl2_getlen(acl, type) + sizeof(AIXJFS2_ACL_T);
		DEBUG(10,("aixjfs2_getacl_alloc - acl_len:%d\n",len));

		acl = (AIXJFS2_ACL_T *)TALLOC_SIZE(mem_ctx, len);
		if (acl == NULL) {
			errno = ENOMEM;
			return NULL;
		}

		ret = aclx_get((char *)fname, ctl_flag, type, acl, &len, &mode);
	}
	if (ret != 0) {
		DEBUG(8, ("aclx_get failed with %s\n", strerror(errno)));
		return NULL;
	}

	return acl;
}
示例#2
0
int
main (int argc, char *argv[])
{
  const char *file1;
  const char *file2;

  set_program_name (argv[0]);

  ASSERT (argc == 3);

  file1 = argv[1];
  file2 = argv[2];

  /* Compare the contents of the two files.  */
  {
    size_t size1;
    char *contents1;
    size_t size2;
    char *contents2;

    contents1 = read_file (file1, &size1);
    if (contents1 == NULL)
      {
        fprintf (stderr, "error reading file %s: errno = %d\n", file1, errno);
        fflush (stderr);
        abort ();
      }
    contents2 = read_file (file2, &size2);
    if (contents2 == NULL)
      {
        fprintf (stderr, "error reading file %s: errno = %d\n", file2, errno);
        fflush (stderr);
        abort ();
      }

    if (size2 != size1)
      {
        fprintf (stderr, "files %s and %s have different sizes\n",
                 file1, file2);
        fflush (stderr);
        abort ();
      }
    if (memcmp (contents1, contents2, size1) != 0)
      {
        fprintf (stderr, "files %s and %s have different contents\n",
                 file1, file2);
        fflush (stderr);
        abort ();
      }
  }

  /* Compare the access permissions of the two files, including ACLs.  */
  {
    struct stat statbuf1;
    struct stat statbuf2;

    if (stat (file1, &statbuf1) < 0)
      {
        fprintf (stderr, "error accessing file %s: errno = %d\n", file1, errno);
        fflush (stderr);
        abort ();
      }
    if (stat (file2, &statbuf2) < 0)
      {
        fprintf (stderr, "error accessing file %s: errno = %d\n", file2, errno);
        fflush (stderr);
        abort ();
      }
    if (statbuf1.st_mode != statbuf2.st_mode)
      {
        fprintf (stderr, "files %s and %s have different access modes: %03o and %03o\n",
                 file1, file2,
                (unsigned int) statbuf1.st_mode, (unsigned int) statbuf2.st_mode);
        return 1;
      }
  }
  {
#if HAVE_ACL_GET_FILE /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
    static const int types[] =
      {
        ACL_TYPE_ACCESS
# if HAVE_ACL_TYPE_EXTENDED /* MacOS X */
        , ACL_TYPE_EXTENDED
# endif
      };
    int t;

    for (t = 0; t < sizeof (types) / sizeof (types[0]); t++)
      {
        int type = types[t];
        acl_t acl1;
        char *text1;
        int errno1;
        acl_t acl2;
        char *text2;
        int errno2;

        acl1 = acl_get_file (file1, type);
        if (acl1 == (acl_t)NULL)
          {
            text1 = NULL;
            errno1 = errno;
          }
        else
          {
            text1 = acl_to_text (acl1, NULL);
            if (text1 == NULL)
              errno1 = errno;
            else
              errno1 = 0;
          }
        acl2 = acl_get_file (file2, type);
        if (acl2 == (acl_t)NULL)
          {
            text2 = NULL;
            errno2 = errno;
          }
        else
          {
            text2 = acl_to_text (acl2, NULL);
            if (text2 == NULL)
              errno2 = errno;
            else
              errno2 = 0;
          }

        if (acl1 != (acl_t)NULL)
          {
            if (acl2 != (acl_t)NULL)
              {
                if (text1 != NULL)
                  {
                    if (text2 != NULL)
                      {
                        if (strcmp (text1, text2) != 0)
                          {
                            fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n",
                                     file1, file2, text1, text2);
                            return 1;
                          }
                      }
                    else
                      {
                        fprintf (stderr, "file %s has a valid ACL, but file %s has an invalid ACL\n",
                                 file1, file2);
                        return 1;
                      }
                  }
                else
                  {
                    if (text2 != NULL)
                      {
                        fprintf (stderr, "file %s has an invalid ACL, but file %s has a valid ACL\n",
                                 file1, file2);
                        return 1;
                      }
                    else
                      {
                        if (errno1 != errno2)
                          {
                            fprintf (stderr, "files %s and %s have differently invalid ACLs, errno = %d vs. %d\n",
                                     file1, file2, errno1, errno2);
                            return 1;
                          }
                      }
                  }
              }
            else
              {
                fprintf (stderr, "file %s has an ACL, but file %s has no ACL\n",
                         file1, file2);
                return 1;
              }
          }
        else
          {
            if (acl2 != (acl_t)NULL)
              {
                fprintf (stderr, "file %s has no ACL, but file %s has an ACL\n",
                         file1, file2);
                return 1;
              }
          }
      }
#elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
  int count1;
  int count2;

  count1 = acl (file1, GETACLCNT, 0, NULL);
  if (count1 < 0 && errno == ENOSYS) /* Can happen on Solaris 10 with ZFS */
    count1 = 0;
  count2 = acl (file2, GETACLCNT, 0, NULL);
  if (count2 < 0 && errno == ENOSYS) /* Can happen on Solaris 10 with ZFS */
    count2 = 0;

  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
    {
      aclent_t *entries1 = XNMALLOC (count1, aclent_t);
      aclent_t *entries2 = XNMALLOC (count2, aclent_t);
      int i;

      if (count1 > 0 && acl (file1, GETACL, count1, entries1) < count1)
        {
          fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
          fflush (stderr);
          abort ();
        }
      if (count2 > 0 && acl (file2, GETACL, 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;
            }
        }
    }
# ifdef ACE_GETACL
  count1 = acl (file1, ACE_GETACLCNT, 0, NULL);
  if (count1 < 0 && errno == EINVAL)
    count1 = 0;
  count2 = acl (file2, ACE_GETACLCNT, 0, NULL);
  if (count2 < 0 && errno == EINVAL)
    count2 = 0;
  if (count1 < 0)
    {
      fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file1);
      fflush (stderr);
      abort ();
    }
  if (count2 < 0)
    {
      fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file2);
      fflush (stderr);
      abort ();
    }
  if (count1 != count2)
    {
      fprintf (stderr, "files %s and %s have different number of ACE-ACLs: %d and %d\n",
               file1, file2, count1, count2);
      return 1;
    }
  else if (count1 > 0)
    {
      ace_t *entries1 = XNMALLOC (count1, ace_t);
      ace_t *entries2 = XNMALLOC (count2, ace_t);
      int i;

      if (acl (file1, ACE_GETACL, count1, entries1) < count1)
        {
          fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
          fflush (stderr);
          abort ();
        }
      if (acl (file2, ACE_GETACL, count2, entries2) < count1)
        {
          fprintf (stderr, "error retrieving the ACE-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 ACE-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_who != entries2[i].a_who)
            {
              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different ids %d and %d\n",
                       file1, file2, i, (int)entries1[i].a_who, (int)entries2[i].a_who);
              return 1;
            }
          if (entries1[i].a_access_mask != entries2[i].a_access_mask)
            {
              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different access masks %03o and %03o\n",
                       file1, file2, i, (unsigned int) entries1[i].a_access_mask, (unsigned int) entries2[i].a_access_mask);
              return 1;
            }
          if (entries1[i].a_flags != entries2[i].a_flags)
            {
              fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different flags 0x%x and 0x%x\n",
                       file1, file2, i, (unsigned int) entries1[i].a_flags, (unsigned int) entries2[i].a_flags);
              return 1;
            }
        }
    }
# endif
#elif HAVE_GETACL /* HP-UX */
  int count1;
  int count2;

  count1 = getacl (file1, 0, NULL);
  if (count1 < 0
      && (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP))
    count1 = 0;
  count2 = getacl (file2, 0, NULL);
  if (count2 < 0
      && (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP))
    count2 = 0;

  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_entry *entries1 = XNMALLOC (count1, struct acl_entry);
      struct acl_entry *entries2 = XNMALLOC (count2, struct acl_entry);
      int i;

      if (getacl (file1, count1, entries1) < count1)
        {
          fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
          fflush (stderr);
          abort ();
        }
      if (getacl (file2, 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].uid != entries2[i].uid)
            {
              fprintf (stderr, "files %s and %s: different ACL entry #%d: different uids %d and %d\n",
                       file1, file2, i, (int)entries1[i].uid, (int)entries2[i].uid);
              return 1;
            }
          if (entries1[i].gid != entries2[i].gid)
            {
              fprintf (stderr, "files %s and %s: different ACL entry #%d: different gids %d and %d\n",
                       file1, file2, i, (int)entries1[i].gid, (int)entries2[i].gid);
              return 1;
            }
          if (entries1[i].mode != entries2[i].mode)
            {
              fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
                       file1, file2, i, (unsigned int) entries1[i].mode, (unsigned int) entries2[i].mode);
              return 1;
            }
        }
    }

# if HAVE_ACLV_H /* HP-UX >= 11.11 */
  {
    struct acl dummy_entries[NACLVENTRIES];

    count1 = acl ((char *) file1, ACL_CNT, NACLVENTRIES, dummy_entries);
    if (count1 < 0
        && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL))
      count1 = 0;
    count2 = acl ((char *) file2, ACL_CNT, NACLVENTRIES, dummy_entries);
    if (count2 < 0
        && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL))
      count2 = 0;
  }

  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
#elif HAVE_ACLX_GET /* AIX */
  acl_type_t type1;
  char acl1[1000];
  size_t aclsize1 = sizeof (acl1);
  mode_t mode1;
  char text1[1000];
  size_t textsize1 = sizeof (text1);
  acl_type_t type2;
  char acl2[1000];
  size_t aclsize2 = sizeof (acl2);
  mode_t mode2;
  char text2[1000];
  size_t textsize2 = sizeof (text2);

  /* The docs say that type1 being 0 is equivalent to ACL_ANY, but it is not
     true, in AIX 5.3.  */
  type1.u64 = ACL_ANY;
  if (aclx_get (file1, 0, &type1, acl1, &aclsize1, &mode1) < 0)
    {
      if (errno == ENOSYS)
        text1[0] = '\0';
      else
        {
          fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
          fflush (stderr);
          abort ();
        }
    }
  else
    if (aclx_printStr (text1, &textsize1, acl1, aclsize1, type1, file1, 0) < 0)
      {
        fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file1);
        fflush (stderr);
        abort ();
      }

  /* The docs say that type2 being 0 is equivalent to ACL_ANY, but it is not
     true, in AIX 5.3.  */
  type2.u64 = ACL_ANY;
  if (aclx_get (file2, 0, &type2, acl2, &aclsize2, &mode2) < 0)
    {
      if (errno == ENOSYS)
        text2[0] = '\0';
      else
        {
          fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
          fflush (stderr);
          abort ();
        }
    }
  else
    if (aclx_printStr (text2, &textsize2, acl2, aclsize2, type2, file2, 0) < 0)
      {
        fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file2);
        fflush (stderr);
        abort ();
      }

  if (strcmp (text1, text2) != 0)
    {
      fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n",
               file1, file2, text1, text2);
      return 1;
    }
#elif HAVE_STATACL /* older AIX */
  union { struct acl a; char room[4096]; } acl1;
  union { struct acl a; char room[4096]; } acl2;
  unsigned int i;

  if (statacl (file1, STX_NORMAL, &acl1.a, sizeof (acl1)) < 0)
    {
      fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
      fflush (stderr);
      abort ();
    }
  if (statacl (file2, STX_NORMAL, &acl2.a, sizeof (acl2)) < 0)
    {
      fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
      fflush (stderr);
      abort ();
    }

  if (acl1.a.acl_len != acl2.a.acl_len)
    {
      fprintf (stderr, "files %s and %s have different ACL lengths: %u and %u\n",
               file1, file2, acl1.a.acl_len, acl2.a.acl_len);
      return 1;
    }
  if (acl1.a.acl_mode != acl2.a.acl_mode)
    {
      fprintf (stderr, "files %s and %s have different ACL modes: %03o and %03o\n",
               file1, file2, acl1.a.acl_mode, acl2.a.acl_mode);
      return 1;
    }
  if (acl1.a.u_access != acl2.a.u_access
      || acl1.a.g_access != acl2.a.g_access
      || acl1.a.o_access != acl2.a.o_access)
    {
      fprintf (stderr, "files %s and %s have different ACL access masks: %03o %03o %03o and %03o %03o %03o\n",
               file1, file2,
               acl1.a.u_access, acl1.a.g_access, acl1.a.o_access,
               acl2.a.u_access, acl2.a.g_access, acl2.a.o_access);
      return 1;
    }
  if (memcmp (acl1.a.acl_ext, acl2.a.acl_ext, acl1.a.acl_len) != 0)
    {
      fprintf (stderr, "files %s and %s have different ACL entries\n",
               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
  }

  return 0;
}
示例#3
0
int
file_has_acl (char const *name, struct stat const *sb)
{
#if USE_ACL
  if (! S_ISLNK (sb->st_mode))
    {
# if HAVE_ACL_GET_FILE

      /* POSIX 1003.1e (draft 17 -- abandoned) specific version.  */
      /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
      int ret;

      if (HAVE_ACL_EXTENDED_FILE) /* Linux */
        {
          /* On Linux, acl_extended_file is an optimized function: It only
             makes two calls to getxattr(), one for ACL_TYPE_ACCESS, one for
             ACL_TYPE_DEFAULT.  */
          ret = acl_extended_file (name);
        }
      else /* FreeBSD, MacOS X, IRIX, Tru64 */
        {
#  if HAVE_ACL_TYPE_EXTENDED /* MacOS X */
          /* On MacOS X, acl_get_file (name, ACL_TYPE_ACCESS)
             and acl_get_file (name, ACL_TYPE_DEFAULT)
             always return NULL / EINVAL.  There is no point in making
             these two useless calls.  The real ACL is retrieved through
             acl_get_file (name, ACL_TYPE_EXTENDED).  */
          acl_t acl = acl_get_file (name, ACL_TYPE_EXTENDED);
          if (acl)
            {
              ret = acl_extended_nontrivial (acl);
              acl_free (acl);
            }
          else
            ret = -1;
#  else /* FreeBSD, IRIX, Tru64 */
          acl_t acl = acl_get_file (name, ACL_TYPE_ACCESS);
          if (acl)
            {
              int saved_errno;

              ret = acl_access_nontrivial (acl);
              saved_errno = errno;
              acl_free (acl);
              errno = saved_errno;
#   if HAVE_ACL_FREE_TEXT /* Tru64 */
              /* On OSF/1, acl_get_file (name, ACL_TYPE_DEFAULT) always
                 returns NULL with errno not set.  There is no point in
                 making this call.  */
#   else /* FreeBSD, IRIX */
              /* On Linux, FreeBSD, IRIX, acl_get_file (name, ACL_TYPE_ACCESS)
                 and acl_get_file (name, ACL_TYPE_DEFAULT) on a directory
                 either both succeed or both fail; it depends on the
                 file system.  Therefore there is no point in making the second
                 call if the first one already failed.  */
              if (ret == 0 && S_ISDIR (sb->st_mode))
                {
                  acl = acl_get_file (name, ACL_TYPE_DEFAULT);
                  if (acl)
                    {
                      ret = (0 < acl_entries (acl));
                      acl_free (acl);
                    }
                  else
                    ret = -1;
                }
#   endif
            }
          else
            ret = -1;
#  endif
        }
      if (ret < 0)
        return ACL_NOT_WELL_SUPPORTED (errno) ? 0 : -1;
      return ret;

# 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
         <sys/acl.h> (acl_t) and implemented in libsec (acl_set, acl_trivial,
         acl_fromtext, ...).  */
      return acl_trivial (name);

#  else /* Solaris, Cygwin, general case */

      /* Solaris 2.5 through Solaris 10, Cygwin, and contemporaneous versions
         of Unixware.  The acl() call returns the access and default ACL both
         at once.  */
      int count;
      {
        aclent_t *entries;

        for (;;)
          {
            count = acl (name, GETACLCNT, 0, NULL);

            if (count < 0)
              {
                if (errno == ENOSYS || errno == ENOTSUP)
                  break;
                else
                  return -1;
              }

            if (count == 0)
              break;

            /* Don't use MIN_ACL_ENTRIES:  It's set to 4 on Cygwin, but Cygwin
               returns only 3 entries for files with no ACL.  But this is safe:
               If there are more than 4 entries, there cannot be only the
               "user::", "group::", "other:", and "mask:" entries.  */
            if (count > 4)
              return 1;

            entries = (aclent_t *) malloc (count * sizeof (aclent_t));
            if (entries == NULL)
              {
                errno = ENOMEM;
                return -1;
              }
            if (acl (name, GETACL, count, entries) == count)
              {
                if (acl_nontrivial (count, entries))
                  {
                    free (entries);
                    return 1;
                  }
                free (entries);
                break;
              }
            /* Huh? The number of ACL entries changed since the last call.
               Repeat.  */
            free (entries);
          }
      }

#   ifdef ACE_GETACL
      /* Solaris also has a different variant of ACLs, used in ZFS and NFSv4
         file systems (whereas the other ones are used in UFS file systems).  */
      {
        ace_t *entries;

        for (;;)
          {
            count = acl (name, ACE_GETACLCNT, 0, NULL);

            if (count < 0)
              {
                if (errno == ENOSYS || errno == EINVAL)
                  break;
                else
                  return -1;
              }

            if (count == 0)
              break;

            /* In the old (original Solaris 10) convention:
               If there are more than 3 entries, there cannot be only the
               ACE_OWNER, ACE_GROUP, ACE_OTHER entries.
               In the newer Solaris 10 and Solaris 11 convention:
               If there are more than 6 entries, there cannot be only the
               ACE_OWNER, ACE_GROUP, ACE_EVERYONE entries, each once with
               NEW_ACE_ACCESS_ALLOWED_ACE_TYPE and once with
               NEW_ACE_ACCESS_DENIED_ACE_TYPE.  */
            if (count > 6)
              return 1;

            entries = (ace_t *) malloc (count * sizeof (ace_t));
            if (entries == NULL)
              {
                errno = ENOMEM;
                return -1;
              }
            if (acl (name, ACE_GETACL, count, entries) == count)
              {
                if (acl_ace_nontrivial (count, entries))
                  {
                    free (entries);
                    return 1;
                  }
                free (entries);
                break;
              }
            /* Huh? The number of ACL entries changed since the last call.
               Repeat.  */
            free (entries);
          }
      }
#   endif

      return 0;
#  endif

# elif HAVE_GETACL /* HP-UX */

      for (;;)
        {
          int count;
          struct acl_entry entries[NACLENTRIES];

          count = getacl (name, 0, NULL);

          if (count < 0)
            {
              /* ENOSYS is seen on newer HP-UX versions.
                 EOPNOTSUPP is typically seen on NFS mounts.
                 ENOTSUP was seen on Quantum StorNext file systems (cvfs).  */
              if (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP)
                break;
              else
                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 3 entries, there cannot be only the
             (uid,%), (%,gid), (%,%) entries.  */
          if (count > 3)
            return 1;

          if (getacl (name, count, entries) == count)
            {
              struct stat statbuf;

              if (stat (name, &statbuf) < 0)
                return -1;

              return acl_nontrivial (count, entries, &statbuf);
            }
          /* Huh? The number of ACL entries changed since the last call.
             Repeat.  */
        }

#  if HAVE_ACLV_H /* HP-UX >= 11.11 */

      for (;;)
        {
          int count;
          struct acl entries[NACLVENTRIES];

          count = acl ((char *) name, ACL_CNT, NACLVENTRIES, entries);

          if (count < 0)
            {
              /* EOPNOTSUPP is seen on NFS in HP-UX 11.11, 11.23.
                 EINVAL is seen on NFS in HP-UX 11.31.  */
              if (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL)
                break;
              else
                return -1;
            }

          if (count == 0)
            return 0;

          if (count > NACLVENTRIES)
            /* If NACLVENTRIES 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 aclv_nontrivial (count, entries);
          /* Huh? The number of ACL entries changed since the last call.
             Repeat.  */
        }

#  endif

# elif HAVE_ACLX_GET && defined ACL_AIX_WIP /* AIX */

      acl_type_t type;
      char aclbuf[1024];
      void *acl = aclbuf;
      size_t aclsize = sizeof (aclbuf);
      mode_t mode;

      for (;;)
        {
          /* The docs say that type being 0 is equivalent to ACL_ANY, but it
             is not true, in AIX 5.3.  */
          type.u64 = ACL_ANY;
          if (aclx_get (name, 0, &type, aclbuf, &aclsize, &mode) >= 0)
            break;
          if (errno == ENOSYS)
            return 0;
          if (errno != ENOSPC)
            {
              if (acl != aclbuf)
                {
                  int saved_errno = errno;
                  free (acl);
                  errno = saved_errno;
                }
              return -1;
            }
          aclsize = 2 * aclsize;
          if (acl != aclbuf)
            free (acl);
          acl = malloc (aclsize);
          if (acl == NULL)
            {
              errno = ENOMEM;
              return -1;
            }
        }

      if (type.u64 == ACL_AIXC)
        {
          int result = acl_nontrivial ((struct acl *) acl);
          if (acl != aclbuf)
            free (acl);
          return result;
        }
      else if (type.u64 == ACL_NFS4)
        {
          int result = acl_nfs4_nontrivial ((nfs4_acl_int_t *) acl);
          if (acl != aclbuf)
            free (acl);
          return result;
        }
      else
        {
          /* A newer type of ACL has been introduced in the system.
             We should better support it.  */
          if (acl != aclbuf)
            free (acl);
          errno = EINVAL;
          return -1;
        }

# elif HAVE_STATACL /* older AIX */

      union { struct acl a; char room[4096]; } u;

      if (statacl (name, STX_NORMAL, &u.a, sizeof (u)) < 0)
        return -1;

      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)
            {
              if (errno == ENOSYS || errno == ENOTSUP)
                break;
              else
                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

  return 0;
}