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