Bump to 1.14.1
[platform/upstream/augeas.git] / tests / test-sameacls.c
1 /* Test whether two files have the same ACLs.
2    Copyright (C) 2008-2016 Free Software Foundation, Inc.
3
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.
8
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.
13
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/>.  */
16
17 /* Written by Bruno Haible <bruno@clisp.org>, 2008.  */
18
19 #include <config.h>
20
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/stat.h>
26
27 #if HAVE_ACL_GET_FILE || HAVE_FACL || HAVE_GETACL || HAVE_ACLX_GET || HAVE_STATACL || HAVE_ACLSORT
28 # include <sys/types.h>
29 # include <sys/acl.h>
30 #endif
31 #if HAVE_ACLV_H
32 # include <sys/types.h>
33 # include <aclv.h>
34 #endif
35
36 #include "read-file.h"
37 #include "xalloc.h"
38 #include "macros.h"
39
40 int
41 main (int argc, char *argv[])
42 {
43   const char *file1;
44   const char *file2;
45
46   ASSERT (argc == 3);
47
48   file1 = argv[1];
49   file2 = argv[2];
50
51   /* Compare the contents of the two files.  */
52   {
53     size_t size1;
54     char *contents1;
55     size_t size2;
56     char *contents2;
57
58     contents1 = read_file (file1, &size1);
59     if (contents1 == NULL)
60       {
61         fprintf (stderr, "error reading file %s: errno = %d\n", file1, errno);
62         fflush (stderr);
63         abort ();
64       }
65     contents2 = read_file (file2, &size2);
66     if (contents2 == NULL)
67       {
68         fprintf (stderr, "error reading file %s: errno = %d\n", file2, errno);
69         fflush (stderr);
70         abort ();
71       }
72
73     if (size2 != size1)
74       {
75         fprintf (stderr, "files %s and %s have different sizes\n",
76                  file1, file2);
77         fflush (stderr);
78         abort ();
79       }
80     if (memcmp (contents1, contents2, size1) != 0)
81       {
82         fprintf (stderr, "files %s and %s have different contents\n",
83                  file1, file2);
84         fflush (stderr);
85         abort ();
86       }
87   }
88
89   /* Compare the access permissions of the two files, including ACLs.  */
90   {
91     struct stat statbuf1;
92     struct stat statbuf2;
93
94     if (stat (file1, &statbuf1) < 0)
95       {
96         fprintf (stderr, "error accessing file %s: errno = %d\n", file1, errno);
97         fflush (stderr);
98         abort ();
99       }
100     if (stat (file2, &statbuf2) < 0)
101       {
102         fprintf (stderr, "error accessing file %s: errno = %d\n", file2, errno);
103         fflush (stderr);
104         abort ();
105       }
106     if (statbuf1.st_mode != statbuf2.st_mode)
107       {
108         fprintf (stderr, "files %s and %s have different access modes: %03o and %03o\n",
109                  file1, file2,
110                 (unsigned int) statbuf1.st_mode, (unsigned int) statbuf2.st_mode);
111         return 1;
112       }
113   }
114   {
115 #if HAVE_ACL_GET_FILE /* Linux, FreeBSD, Mac OS X, IRIX, Tru64 */
116     static const int types[] =
117       {
118         ACL_TYPE_ACCESS
119 # if HAVE_ACL_TYPE_EXTENDED /* Mac OS X */
120         , ACL_TYPE_EXTENDED
121 # endif
122       };
123     int t;
124
125     for (t = 0; t < sizeof (types) / sizeof (types[0]); t++)
126       {
127         int type = types[t];
128         acl_t acl1;
129         char *text1;
130         int errno1;
131         acl_t acl2;
132         char *text2;
133         int errno2;
134
135         acl1 = acl_get_file (file1, type);
136         if (acl1 == (acl_t)NULL)
137           {
138             text1 = NULL;
139             errno1 = errno;
140           }
141         else
142           {
143             text1 = acl_to_text (acl1, NULL);
144             if (text1 == NULL)
145               errno1 = errno;
146             else
147               errno1 = 0;
148           }
149         acl2 = acl_get_file (file2, type);
150         if (acl2 == (acl_t)NULL)
151           {
152             text2 = NULL;
153             errno2 = errno;
154           }
155         else
156           {
157             text2 = acl_to_text (acl2, NULL);
158             if (text2 == NULL)
159               errno2 = errno;
160             else
161               errno2 = 0;
162           }
163
164         if (acl1 != (acl_t)NULL)
165           {
166             if (acl2 != (acl_t)NULL)
167               {
168                 if (text1 != NULL)
169                   {
170                     if (text2 != NULL)
171                       {
172                         if (strcmp (text1, text2) != 0)
173                           {
174                             fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n",
175                                      file1, file2, text1, text2);
176                             return 1;
177                           }
178                       }
179                     else
180                       {
181                         fprintf (stderr, "file %s has a valid ACL, but file %s has an invalid ACL\n",
182                                  file1, file2);
183                         return 1;
184                       }
185                   }
186                 else
187                   {
188                     if (text2 != NULL)
189                       {
190                         fprintf (stderr, "file %s has an invalid ACL, but file %s has a valid ACL\n",
191                                  file1, file2);
192                         return 1;
193                       }
194                     else
195                       {
196                         if (errno1 != errno2)
197                           {
198                             fprintf (stderr, "files %s and %s have differently invalid ACLs, errno = %d vs. %d\n",
199                                      file1, file2, errno1, errno2);
200                             return 1;
201                           }
202                       }
203                   }
204               }
205             else
206               {
207                 fprintf (stderr, "file %s has an ACL, but file %s has no ACL\n",
208                          file1, file2);
209                 return 1;
210               }
211           }
212         else
213           {
214             if (acl2 != (acl_t)NULL)
215               {
216                 fprintf (stderr, "file %s has no ACL, but file %s has an ACL\n",
217                          file1, file2);
218                 return 1;
219               }
220           }
221       }
222 #elif HAVE_FACL && defined GETACL /* Solaris, Cygwin, not HP-UX */
223   int count1;
224   int count2;
225
226   count1 = acl (file1, GETACLCNT, 0, NULL);
227   if (count1 < 0 && errno == ENOSYS) /* Can happen on Solaris 10 with ZFS */
228     count1 = 0;
229   count2 = acl (file2, GETACLCNT, 0, NULL);
230   if (count2 < 0 && errno == ENOSYS) /* Can happen on Solaris 10 with ZFS */
231     count2 = 0;
232
233   if (count1 < 0)
234     {
235       fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
236       fflush (stderr);
237       abort ();
238     }
239   if (count2 < 0)
240     {
241       fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
242       fflush (stderr);
243       abort ();
244     }
245   if (count1 != count2)
246     {
247       fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
248                file1, file2, count1, count2);
249       return 1;
250     }
251   else
252     {
253       aclent_t *entries1 = XNMALLOC (count1, aclent_t);
254       aclent_t *entries2 = XNMALLOC (count2, aclent_t);
255       int i;
256
257       if (count1 > 0 && acl (file1, GETACL, count1, entries1) < count1)
258         {
259           fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
260           fflush (stderr);
261           abort ();
262         }
263       if (count2 > 0 && acl (file2, GETACL, count2, entries2) < count1)
264         {
265           fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
266           fflush (stderr);
267           abort ();
268         }
269       for (i = 0; i < count1; i++)
270         {
271           if (entries1[i].a_type != entries2[i].a_type)
272             {
273               fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n",
274                        file1, file2, i, entries1[i].a_type, entries2[i].a_type);
275               return 1;
276             }
277           if (entries1[i].a_id != entries2[i].a_id)
278             {
279               fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n",
280                        file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id);
281               return 1;
282             }
283           if (entries1[i].a_perm != entries2[i].a_perm)
284             {
285               fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
286                        file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm);
287               return 1;
288             }
289         }
290     }
291 # ifdef ACE_GETACL
292   count1 = acl (file1, ACE_GETACLCNT, 0, NULL);
293   if (count1 < 0 && errno == EINVAL)
294     count1 = 0;
295   count2 = acl (file2, ACE_GETACLCNT, 0, NULL);
296   if (count2 < 0 && errno == EINVAL)
297     count2 = 0;
298   if (count1 < 0)
299     {
300       fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file1);
301       fflush (stderr);
302       abort ();
303     }
304   if (count2 < 0)
305     {
306       fprintf (stderr, "error accessing the ACE-ACLs of file %s\n", file2);
307       fflush (stderr);
308       abort ();
309     }
310   {
311     ace_t *entries1 = XNMALLOC (count1, ace_t);
312     ace_t *entries2 = XNMALLOC (count2, ace_t);
313     int ret;
314     int i;
315
316     ret = acl (file1, ACE_GETACL, count1, entries1);
317     if (ret < 0 && errno == EINVAL)
318       count1 = 0;
319     else if (ret < count1)
320       {
321         fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file1);
322         fflush (stderr);
323         abort ();
324       }
325     ret = acl (file2, ACE_GETACL, count2, entries2);
326     if (ret < 0 && errno == EINVAL)
327       count2 = 0;
328     else if (ret < count2)
329       {
330         fprintf (stderr, "error retrieving the ACE-ACLs of file %s\n", file2);
331         fflush (stderr);
332         abort ();
333       }
334
335     if (count1 != count2)
336       {
337         fprintf (stderr, "files %s and %s have different number of ACE-ACLs: %d and %d\n",
338                  file1, file2, count1, count2);
339         return 1;
340       }
341
342     for (i = 0; i < count1; i++)
343       {
344         if (entries1[i].a_type != entries2[i].a_type)
345           {
346             fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different types %d and %d\n",
347                      file1, file2, i, entries1[i].a_type, entries2[i].a_type);
348             return 1;
349           }
350         if (entries1[i].a_who != entries2[i].a_who)
351           {
352             fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different ids %d and %d\n",
353                      file1, file2, i, (int)entries1[i].a_who, (int)entries2[i].a_who);
354             return 1;
355           }
356         if (entries1[i].a_access_mask != entries2[i].a_access_mask)
357           {
358             fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different access masks %03o and %03o\n",
359                      file1, file2, i, (unsigned int) entries1[i].a_access_mask, (unsigned int) entries2[i].a_access_mask);
360             return 1;
361           }
362         if (entries1[i].a_flags != entries2[i].a_flags)
363           {
364             fprintf (stderr, "files %s and %s: different ACE-ACL entry #%d: different flags 0x%x and 0x%x\n",
365                      file1, file2, i, (unsigned int) entries1[i].a_flags, (unsigned int) entries2[i].a_flags);
366             return 1;
367           }
368       }
369   }
370 # endif
371 #elif HAVE_GETACL /* HP-UX */
372   int count1;
373   int count2;
374
375   count1 = getacl (file1, 0, NULL);
376   if (count1 < 0
377       && (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP))
378     count1 = 0;
379   count2 = getacl (file2, 0, NULL);
380   if (count2 < 0
381       && (errno == ENOSYS || errno == EOPNOTSUPP || errno == ENOTSUP))
382     count2 = 0;
383
384   if (count1 < 0)
385     {
386       fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
387       fflush (stderr);
388       abort ();
389     }
390   if (count2 < 0)
391     {
392       fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
393       fflush (stderr);
394       abort ();
395     }
396   if (count1 != count2)
397     {
398       fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
399                file1, file2, count1, count2);
400       return 1;
401     }
402   else if (count1 > 0)
403     {
404       struct acl_entry *entries1 = XNMALLOC (count1, struct acl_entry);
405       struct acl_entry *entries2 = XNMALLOC (count2, struct acl_entry);
406       int i;
407
408       if (getacl (file1, count1, entries1) < count1)
409         {
410           fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
411           fflush (stderr);
412           abort ();
413         }
414       if (getacl (file2, count2, entries2) < count1)
415         {
416           fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
417           fflush (stderr);
418           abort ();
419         }
420       for (i = 0; i < count1; i++)
421         {
422           if (entries1[i].uid != entries2[i].uid)
423             {
424               fprintf (stderr, "files %s and %s: different ACL entry #%d: different uids %d and %d\n",
425                        file1, file2, i, (int)entries1[i].uid, (int)entries2[i].uid);
426               return 1;
427             }
428           if (entries1[i].gid != entries2[i].gid)
429             {
430               fprintf (stderr, "files %s and %s: different ACL entry #%d: different gids %d and %d\n",
431                        file1, file2, i, (int)entries1[i].gid, (int)entries2[i].gid);
432               return 1;
433             }
434           if (entries1[i].mode != entries2[i].mode)
435             {
436               fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
437                        file1, file2, i, (unsigned int) entries1[i].mode, (unsigned int) entries2[i].mode);
438               return 1;
439             }
440         }
441     }
442
443 # if HAVE_ACLV_H /* HP-UX >= 11.11 */
444   {
445     struct acl dummy_entries[NACLVENTRIES];
446
447     count1 = acl ((char *) file1, ACL_CNT, NACLVENTRIES, dummy_entries);
448     if (count1 < 0
449         && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL))
450       count1 = 0;
451     count2 = acl ((char *) file2, ACL_CNT, NACLVENTRIES, dummy_entries);
452     if (count2 < 0
453         && (errno == ENOSYS || errno == EOPNOTSUPP || errno == EINVAL))
454       count2 = 0;
455   }
456
457   if (count1 < 0)
458     {
459       fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
460       fflush (stderr);
461       abort ();
462     }
463   if (count2 < 0)
464     {
465       fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
466       fflush (stderr);
467       abort ();
468     }
469   if (count1 != count2)
470     {
471       fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
472                file1, file2, count1, count2);
473       return 1;
474     }
475   else if (count1 > 0)
476     {
477       struct acl *entries1 = XNMALLOC (count1, struct acl);
478       struct acl *entries2 = XNMALLOC (count2, struct acl);
479       int i;
480
481       if (acl ((char *) file1, ACL_GET, count1, entries1) < count1)
482         {
483           fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
484           fflush (stderr);
485           abort ();
486         }
487       if (acl ((char *) file2, ACL_GET, count2, entries2) < count1)
488         {
489           fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
490           fflush (stderr);
491           abort ();
492         }
493       for (i = 0; i < count1; i++)
494         {
495           if (entries1[i].a_type != entries2[i].a_type)
496             {
497               fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n",
498                        file1, file2, i, entries1[i].a_type, entries2[i].a_type);
499               return 1;
500             }
501           if (entries1[i].a_id != entries2[i].a_id)
502             {
503               fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n",
504                        file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id);
505               return 1;
506             }
507           if (entries1[i].a_perm != entries2[i].a_perm)
508             {
509               fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
510                        file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm);
511               return 1;
512             }
513         }
514     }
515 # endif
516 #elif HAVE_ACLX_GET /* AIX */
517   acl_type_t type1;
518   char acl1[1000];
519   size_t aclsize1 = sizeof (acl1);
520   mode_t mode1;
521   char text1[1000];
522   size_t textsize1 = sizeof (text1);
523   acl_type_t type2;
524   char acl2[1000];
525   size_t aclsize2 = sizeof (acl2);
526   mode_t mode2;
527   char text2[1000];
528   size_t textsize2 = sizeof (text2);
529
530   /* The docs say that type1 being 0 is equivalent to ACL_ANY, but it is not
531      true, in AIX 5.3.  */
532   type1.u64 = ACL_ANY;
533   if (aclx_get (file1, 0, &type1, acl1, &aclsize1, &mode1) < 0)
534     {
535       if (errno == ENOSYS)
536         text1[0] = '\0';
537       else
538         {
539           fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
540           fflush (stderr);
541           abort ();
542         }
543     }
544   else
545     if (aclx_printStr (text1, &textsize1, acl1, aclsize1, type1, file1, 0) < 0)
546       {
547         fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file1);
548         fflush (stderr);
549         abort ();
550       }
551
552   /* The docs say that type2 being 0 is equivalent to ACL_ANY, but it is not
553      true, in AIX 5.3.  */
554   type2.u64 = ACL_ANY;
555   if (aclx_get (file2, 0, &type2, acl2, &aclsize2, &mode2) < 0)
556     {
557       if (errno == ENOSYS)
558         text2[0] = '\0';
559       else
560         {
561           fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
562           fflush (stderr);
563           abort ();
564         }
565     }
566   else
567     if (aclx_printStr (text2, &textsize2, acl2, aclsize2, type2, file2, 0) < 0)
568       {
569         fprintf (stderr, "cannot convert the ACLs of file %s to text\n", file2);
570         fflush (stderr);
571         abort ();
572       }
573
574   if (strcmp (text1, text2) != 0)
575     {
576       fprintf (stderr, "files %s and %s have different ACLs:\n%s\n%s\n",
577                file1, file2, text1, text2);
578       return 1;
579     }
580 #elif HAVE_STATACL /* older AIX */
581   union { struct acl a; char room[4096]; } acl1;
582   union { struct acl a; char room[4096]; } acl2;
583   unsigned int i;
584
585   if (statacl (file1, STX_NORMAL, &acl1.a, sizeof (acl1)) < 0)
586     {
587       fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
588       fflush (stderr);
589       abort ();
590     }
591   if (statacl (file2, STX_NORMAL, &acl2.a, sizeof (acl2)) < 0)
592     {
593       fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
594       fflush (stderr);
595       abort ();
596     }
597
598   if (acl1.a.acl_len != acl2.a.acl_len)
599     {
600       fprintf (stderr, "files %s and %s have different ACL lengths: %u and %u\n",
601                file1, file2, acl1.a.acl_len, acl2.a.acl_len);
602       return 1;
603     }
604   if (acl1.a.acl_mode != acl2.a.acl_mode)
605     {
606       fprintf (stderr, "files %s and %s have different ACL modes: %03o and %03o\n",
607                file1, file2, acl1.a.acl_mode, acl2.a.acl_mode);
608       return 1;
609     }
610   if (acl1.a.u_access != acl2.a.u_access
611       || acl1.a.g_access != acl2.a.g_access
612       || acl1.a.o_access != acl2.a.o_access)
613     {
614       fprintf (stderr, "files %s and %s have different ACL access masks: %03o %03o %03o and %03o %03o %03o\n",
615                file1, file2,
616                acl1.a.u_access, acl1.a.g_access, acl1.a.o_access,
617                acl2.a.u_access, acl2.a.g_access, acl2.a.o_access);
618       return 1;
619     }
620   if (memcmp (acl1.a.acl_ext, acl2.a.acl_ext, acl1.a.acl_len) != 0)
621     {
622       fprintf (stderr, "files %s and %s have different ACL entries\n",
623                file1, file2);
624       return 1;
625     }
626 #elif HAVE_ACLSORT /* NonStop Kernel */
627   int count1;
628   int count2;
629
630   count1 = acl ((char *) file1, ACL_CNT, NACLENTRIES, NULL);
631   count2 = acl ((char *) file2, ACL_CNT, NACLENTRIES, NULL);
632
633   if (count1 < 0)
634     {
635       fprintf (stderr, "error accessing the ACLs of file %s\n", file1);
636       fflush (stderr);
637       abort ();
638     }
639   if (count2 < 0)
640     {
641       fprintf (stderr, "error accessing the ACLs of file %s\n", file2);
642       fflush (stderr);
643       abort ();
644     }
645   if (count1 != count2)
646     {
647       fprintf (stderr, "files %s and %s have different number of ACLs: %d and %d\n",
648                file1, file2, count1, count2);
649       return 1;
650     }
651   else if (count1 > 0)
652     {
653       struct acl *entries1 = XNMALLOC (count1, struct acl);
654       struct acl *entries2 = XNMALLOC (count2, struct acl);
655       int i;
656
657       if (acl ((char *) file1, ACL_GET, count1, entries1) < count1)
658         {
659           fprintf (stderr, "error retrieving the ACLs of file %s\n", file1);
660           fflush (stderr);
661           abort ();
662         }
663       if (acl ((char *) file2, ACL_GET, count2, entries2) < count1)
664         {
665           fprintf (stderr, "error retrieving the ACLs of file %s\n", file2);
666           fflush (stderr);
667           abort ();
668         }
669       for (i = 0; i < count1; i++)
670         {
671           if (entries1[i].a_type != entries2[i].a_type)
672             {
673               fprintf (stderr, "files %s and %s: different ACL entry #%d: different types %d and %d\n",
674                        file1, file2, i, entries1[i].a_type, entries2[i].a_type);
675               return 1;
676             }
677           if (entries1[i].a_id != entries2[i].a_id)
678             {
679               fprintf (stderr, "files %s and %s: different ACL entry #%d: different ids %d and %d\n",
680                        file1, file2, i, (int)entries1[i].a_id, (int)entries2[i].a_id);
681               return 1;
682             }
683           if (entries1[i].a_perm != entries2[i].a_perm)
684             {
685               fprintf (stderr, "files %s and %s: different ACL entry #%d: different permissions %03o and %03o\n",
686                        file1, file2, i, (unsigned int) entries1[i].a_perm, (unsigned int) entries2[i].a_perm);
687               return 1;
688             }
689         }
690     }
691 #endif
692   }
693
694   return 0;
695 }