1 /* Test whether two files have the same ACLs.
2 Copyright (C) 2008 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>, 2008. */
27 #if HAVE_ACL_GET_FILE || HAVE_ACL || HAVE_ACLX_GET || HAVE_STATACL
28 # include <sys/types.h>
32 #include "read-file.h"
35 #define ASSERT(expr) \
40 fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
48 main (int argc, char *argv[])
58 /* Compare the contents of the two files. */
65 contents1 = read_file (file1, &size1);
66 if (contents1 == NULL)
68 fprintf (stderr, "error reading file %s: errno = %d\n", file1, errno);
72 contents2 = read_file (file2, &size2);
73 if (contents2 == NULL)
75 fprintf (stderr, "error reading file %s: errno = %d\n", file2, errno);
82 fprintf (stderr, "files %s and %s have different sizes\n",
87 if (memcmp (contents1, contents2, size1) != 0)
89 fprintf (stderr, "files %s and %s have different contents\n",
96 /* Compare the access permissions of the two files, including ACLs. */
101 if (stat (file1, &statbuf1) < 0)
103 fprintf (stderr, "error accessing file %s: errno = %d\n", file1, errno);
107 if (stat (file2, &statbuf2) < 0)
109 fprintf (stderr, "error accessing file %s: errno = %d\n", file2, errno);
113 if (statbuf1.st_mode != statbuf2.st_mode)
115 fprintf (stderr, "files %s and %s have different access modes: %03o and %03o\n",
117 (unsigned int) statbuf1.st_mode, (unsigned int) statbuf2.st_mode);
122 #if HAVE_ACL_GET_FILE /* Linux, FreeBSD, MacOS X, IRIX, Tru64 */
130 acl1 = acl_get_file (file1, ACL_TYPE_ACCESS);
131 if (acl1 == (acl_t)NULL)
138 text1 = acl_to_text (acl1, NULL);
144 acl2 = acl_get_file (file2, ACL_TYPE_ACCESS);
145 if (acl2 == (acl_t)NULL)
152 text2 = acl_to_text (acl2, NULL);
159 if (acl1 != (acl_t)NULL)
161 if (acl2 != (acl_t)NULL)
167 if (strcmp (text1, text2) != 0)
169 fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n",
170 file1, file2, text1, text2);
176 fprintf (stderr, "file %s has a valid ACL, but file %s has an invalid ACL\n",
185 fprintf (stderr, "file %s has an invalid ACL, but file %s has a valid ACL\n",
191 if (errno1 != errno2)
193 fprintf (stderr, "files %s and %s have differently invalid ACLs, errno = %d vs. %d\n",
194 file1, file2, errno1, errno2);
202 fprintf (stderr, "file %s has an ACL, but file %s has no ACL\n",
209 if (acl2 != (acl_t)NULL)
211 fprintf (stderr, "file %s has no ACL, but file %s has an ACL\n",
216 #elif HAVE_ACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
220 count1 = acl (file1, GETACLCNT, 0, NULL);
221 count2 = acl (file2, GETACLCNT, 0, NULL);
223 if (count1 != count2)
227 fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
233 fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
237 fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
238 file1, file2, count1, count2);
243 aclent_t *entries1 = XNMALLOC (count1, aclent_t);
244 aclent_t *entries2 = XNMALLOC (count2, aclent_t);
247 if (acl (file1, GETACL, count1, entries1) < count1)
249 fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
253 if (acl (file2, GETACL, count2, entries2) < count1)
255 fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
259 for (i = 0; i < count1; i++)
261 if (entries1[i].a_type != entries2[i].a_type)
263 fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n",
264 file1, file2, i, entries1[i].a_type, entries2[i].a_type);
267 if (entries1[i].a_id != entries2[i].a_id)
269 fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n",
270 file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id);
273 if (entries1[i].a_perm != entries2[i].a_perm)
275 fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
276 file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm);
282 count1 = acl (file1, ACE_GETACLCNT, 0, NULL);
283 count2 = acl (file2, ACE_GETACLCNT, 0, NULL);
284 if (count1 != count2)
288 fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file1);
294 fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file2);
298 fprintf (stderr, "files %s and %s have different number of ACE-ACLs: %d and %d\n",
299 file1, file2, count1, count2);
304 ace_t *entries1 = XNMALLOC (count1, ace_t);
305 ace_t *entries2 = XNMALLOC (count2, ace_t);
308 if (acl (file1, ACE_GETACL, count1, entries1) < count1)
310 fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
314 if (acl (file2, ACE_GETACL, count2, entries2) < count1)
316 fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file2);
320 for (i = 0; i < count1; i++)
322 if (entries1[i].a_type != entries2[i].a_type)
324 fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different types %d and %d\n",
325 file1, file2, i, entries1[i].a_type, entries2[i].a_type);
328 if (entries1[i].a_who != entries2[i].a_who)
330 fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different ids %d and %d\n",
331 file1, file2, i, (int)entries1[i].a_who, (int)entries2[i].a_who);
334 if (entries1[i].a_access_mask != entries2[i].a_access_mask)
336 fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different access masks %03o and %03o\n",
337 file1, file2, i, (unsigned int) entries1[i].a_access_mask, (unsigned int) entries2[i].a_access_mask);
340 if (entries1[i].a_flags != entries2[i].a_flags)
342 fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different flags 0x%x and 0x%x\n",
343 file1, file2, i, (unsigned int) entries1[i].a_flags, (unsigned int) entries2[i].a_flags);
349 #elif HAVE_GETACL /* HP-UX */
353 count1 = getacl (file1, 0, NULL);
354 count2 = getacl (file2, 0, NULL);
356 if (count1 != count2)
360 fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
366 fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
370 fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
371 file1, file2, count1, count2);
376 struct acl_entry *entries1 = XNMALLOC (count1, struct acl_entry);
377 struct acl_entry *entries2 = XNMALLOC (count2, struct acl_entry);
380 if (getacl (file1, count1, entries1) < count1)
382 fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
386 if (getacl (file2, count2, entries2) < count1)
388 fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
392 for (i = 0; i < count1; i++)
394 if (entries1[i].uid != entries2[i].uid)
396 fprintf (stderr, "files %s and %s: different ACL entry #%d: different uids %d and %d\n",
397 file1, file2, i, (int)entries1[i].uid, (int)entries2[i].uid);
400 if (entries1[i].gid != entries2[i].gid)
402 fprintf (stderr, "files %s and %s: different ACL entry #%d: different gids %d and %d\n",
403 file1, file2, i, (int)entries1[i].gid, (int)entries2[i].gid);
406 if (entries1[i].mode != entries2[i].mode)
408 fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
409 file1, file2, i, (unsigned int) entries1[i].mode, (unsigned int) entries2[i].mode);
414 #elif HAVE_ACLX_GET /* AIX */
417 size_t aclsize1 = sizeof (acl1);
422 size_t aclsize2 = sizeof (acl2);
426 if (aclx_get (file1, 0, &type1, acl1, &aclsize1, &mode1) < 0)
428 fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
432 if (aclx_printStr (text1, sizeof (text1), acl1, aclsize1, type1, file1, 0) < 0)
434 fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file1);
439 if (aclx_get (file2, 0, &type2, acl2, &aclsize2, &mode2) < 0)
441 fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
445 if (aclx_printStr (text2, sizeof (text2), acl2, aclsize2, type2, file2, 0) < 0)
447 fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file2);
452 if (strcmp (text1, text2) != 0)
454 fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n",
455 file1, file2, text1, text2);
458 #elif HAVE_STATACL /* older AIX */
459 union { struct acl a; char room[4096]; } acl1;
460 union { struct acl a; char room[4096]; } acl2;
463 if (statacl (file1, STX_NORMAL, &acl1.a, sizeof (acl1)) < 0)
465 fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
469 if (statacl (file2, STX_NORMAL, &acl2.a, sizeof (acl2)) < 0)
471 fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
476 if (acl1.a.acl_len != acl2.a.acl_len)
478 fprintf (stderr, "files %s and %s have different ACL lengths: %u and %u\n",
479 file1, file2, acl1.a.acl_len, acl2.a.acl_len);
482 if (acl1.a.acl_mode != acl2.a.acl_mode)
484 fprintf (stderr, "files %s and %s have different ACL modes: %03o and %03o\n",
485 file1, file2, acl1.a.acl_mode, acl2.a.acl_mode);
488 if (acl1.a.u_access != acl2.a.u_access
489 || acl1.a.g_access != acl2.a.g_access
490 || acl1.a.o_access != acl2.a.o_access)
492 fprintf (stderr, "files %s and %s have different ACL access masks: %03o %03o %03o and %03o %03o %03o\n",
494 acl1.a.u_access, acl1.a.g_access, acl1.a.o_access,
495 acl2.a.u_access, acl2.a.g_access, acl2.a.o_access);
498 if (memcmp (acl1.a.acl_ext, acl2.a.acl_ext, acl1.a.acl_len) != 0)
500 fprintf (stderr, "files %s and %s have different ACL entries\n",