1 /* Test whether two files have the same ACLs.
2    Copyright (C) 2008-2020 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
main(int argc,char * argv[])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 }
715