/* Test whether two files have the same ACLs.
- Copyright (C) 2008-2010 Free Software Foundation, Inc.
+ Copyright (C) 2008-2013 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
#include <string.h>
#include <sys/stat.h>
-#if HAVE_ACL_GET_FILE || HAVE_ACL || HAVE_ACLX_GET || HAVE_STATACL
+#if HAVE_ACL_GET_FILE || HAVE_FACL || HAVE_GETACL || HAVE_ACLX_GET || HAVE_STATACL || HAVE_ACLSORT
# include <sys/types.h>
# include <sys/acl.h>
#endif
+#if HAVE_ACLV_H
+# include <sys/types.h>
+# include <aclv.h>
+#endif
#include "progname.h"
#include "read-file.h"
}
}
{
-#if HAVE_ACL_GET_FILE /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
+#if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
static const int types[] =
{
ACL_TYPE_ACCESS
-# if HAVE_ACL_TYPE_EXTENDED /* MacOS X */
+# if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
, ACL_TYPE_EXTENDED
# endif
};
}
}
}
-#elif HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
+#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)
{
aclent_t *entries2 = XNMALLOC (count2, aclent_t);
int i;
- if (acl (file1, GETACL, count1, entries1) < count1)
+ if (count1 > 0 && acl (file1, GETACL, count1, entries1) < count1)
{
fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
fflush (stderr);
abort ();
}
- if (acl (file2, GETACL, count2, entries2) < count1)
+ if (count2 > 0 && acl (file2, GETACL, count2, entries2) < count1)
{
fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
fflush (stderr);
fflush (stderr);
abort ();
}
+ {
+ ace_t *entries1 = XNMALLOC (count1, ace_t);
+ ace_t *entries2 = XNMALLOC (count2, ace_t);
+ int ret;
+ int i;
+
+ ret = acl (file1, ACE_GETACL, count1, entries1);
+ if (ret < 0 && errno == EINVAL)
+ count1 = 0;
+ else if (ret < count1)
+ {
+ fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
+ fflush (stderr);
+ abort ();
+ }
+ ret = acl (file2, ACE_GETACL, count2, entries2);
+ if (ret < 0 && errno == EINVAL)
+ count2 = 0;
+ else if (ret < count2)
+ {
+ fprintf (stderr, "error retrieving 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;
+ }
+
+ 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 ACE-ACLs: %d and %d\n",
+ 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)
{
- ace_t *entries1 = XNMALLOC (count1, ace_t);
- ace_t *entries2 = XNMALLOC (count2, ace_t);
+ struct acl_entry *entries1 = XNMALLOC (count1, struct acl_entry);
+ struct acl_entry *entries2 = XNMALLOC (count2, struct acl_entry);
int i;
- if (acl (file1, ACE_GETACL, count1, entries1) < count1)
+ if (getacl (file1, count1, entries1) < count1)
{
- fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
+ fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
fflush (stderr);
abort ();
}
- if (acl (file2, ACE_GETACL, count2, entries2) < count1)
+ if (getacl (file2, count2, entries2) < count1)
{
- fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file2);
+ 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 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)
+ if (entries1[i].uid != entries2[i].uid)
{
- 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);
+ 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].a_access_mask != entries2[i].a_access_mask)
+ if (entries1[i].gid != entries2[i].gid)
{
- 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);
+ 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].a_flags != entries2[i].a_flags)
+ if (entries1[i].mode != entries2[i].mode)
{
- 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);
+ 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;
}
}
}
-# endif
-#elif HAVE_GETACL /* HP-UX */
- int count1;
- int count2;
- count1 = getacl (file1, 0, NULL);
- if (count1 < 0 && (errno == ENOSYS || errno == EOPNOTSUPP))
- count1 = 0;
- count2 = getacl (file2, 0, NULL);
- if (count2 < 0 && (errno == ENOSYS || errno == EOPNOTSUPP))
- count2 = 0;
+# 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)
{
}
else if (count1 > 0)
{
- struct acl_entry *entries1 = XNMALLOC (count1, struct acl_entry);
- struct acl_entry *entries2 = XNMALLOC (count2, struct acl_entry);
+ struct acl *entries1 = XNMALLOC (count1, struct acl);
+ struct acl *entries2 = XNMALLOC (count2, struct acl);
int i;
- if (getacl (file1, count1, entries1) < count1)
+ if (acl ((char *) file1, ACL_GET, count1, entries1) < count1)
{
fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
fflush (stderr);
abort ();
}
- if (getacl (file2, count2, entries2) < count1)
+ if (acl ((char *) file2, ACL_GET, count2, entries2) < count1)
{
fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
fflush (stderr);
}
for (i = 0; i < count1; i++)
{
- if (entries1[i].uid != entries2[i].uid)
+ if (entries1[i].a_type != entries2[i].a_type)
{
- 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);
+ 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].gid != entries2[i].gid)
+ if (entries1[i].a_id != entries2[i].a_id)
{
- 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);
+ 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].mode != entries2[i].mode)
+ 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].mode, (unsigned int) entries2[i].mode);
+ 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)
{
- fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
- fflush (stderr);
- abort ();
- }
- if (aclx_printStr (text1, sizeof (text1), acl1, aclsize1, type1, file1, 0) < 0)
- {
- fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file1);
- fflush (stderr);
- abort ();
+ 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)
{
- fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
- fflush (stderr);
- abort ();
- }
- if (aclx_printStr (text2, sizeof (text2), acl2, aclsize2, type2, file2, 0) < 0)
- {
- fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file2);
- fflush (stderr);
- abort ();
+ 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)
{
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
}