]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/test/test_acl_platform_nfs4.c
MFC r314571:
[FreeBSD/stable/10.git] / contrib / libarchive / libarchive / test / test_acl_platform_nfs4.c
1 /*-
2  * Copyright (c) 2003-2010 Tim Kientzle
3  * Copyright (c) 2017 Martin Matuska
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 #include "test.h"
27 __FBSDID("$FreeBSD$");
28
29 #if HAVE_POSIX_ACL || HAVE_NFS4_ACL
30 #define _ACL_PRIVATE
31 #include <sys/acl.h>
32 #if HAVE_DARWIN_ACL
33 #include <membership.h>
34 #endif
35 #endif
36
37 #if HAVE_NFS4_ACL
38 struct myacl_t {
39         int type;
40         int permset;
41         int tag;
42         int qual; /* GID or UID of user/group, depending on tag. */
43         const char *name; /* Name of user/group, depending on tag. */
44 };
45
46 static struct myacl_t acls_reg[] = {
47 #if !HAVE_DARWIN_ACL
48         /* For this test, we need the file owner to be able to read and write the ACL. */
49         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
50           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL | ARCHIVE_ENTRY_ACL_WRITE_ACL | ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
51           ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
52 #endif
53         /* An entry for each type. */
54         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
55           ARCHIVE_ENTRY_ACL_USER, 108, "user108" },
56         { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
57           ARCHIVE_ENTRY_ACL_USER, 109, "user109" },
58
59         /* An entry for each permission. */
60         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
61           ARCHIVE_ENTRY_ACL_USER, 112, "user112" },
62         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA,
63           ARCHIVE_ENTRY_ACL_USER, 113, "user113" },
64         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_DATA,
65           ARCHIVE_ENTRY_ACL_USER, 115, "user115" },
66         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_APPEND_DATA,
67           ARCHIVE_ENTRY_ACL_USER, 117, "user117" },
68         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
69           ARCHIVE_ENTRY_ACL_USER, 119, "user119" },
70         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
71           ARCHIVE_ENTRY_ACL_USER, 120, "user120" },
72         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
73           ARCHIVE_ENTRY_ACL_USER, 122, "user122" },
74         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
75           ARCHIVE_ENTRY_ACL_USER, 123, "user123" },
76         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
77           ARCHIVE_ENTRY_ACL_USER, 124, "user124" },
78         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
79           ARCHIVE_ENTRY_ACL_USER, 125, "user125" },
80         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
81           ARCHIVE_ENTRY_ACL_USER, 126, "user126" },
82         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
83           ARCHIVE_ENTRY_ACL_USER, 127, "user127" },
84         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
85           ARCHIVE_ENTRY_ACL_USER, 128, "user128" },
86
87         /* One entry for each qualifier. */
88         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
89           ARCHIVE_ENTRY_ACL_USER, 135, "user135" },
90 //      { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
91 //        ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
92         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
93           ARCHIVE_ENTRY_ACL_GROUP, 136, "group136" },
94 #if !HAVE_DARWIN_ACL
95         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
96           ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
97         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EXECUTE,
98           ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
99 #else   /* MacOS - mode 0654 */
100         { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
101           ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
102         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
103             ARCHIVE_ENTRY_ACL_READ_DATA |
104             ARCHIVE_ENTRY_ACL_WRITE_DATA |
105             ARCHIVE_ENTRY_ACL_APPEND_DATA |
106             ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
107             ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
108             ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
109             ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
110             ARCHIVE_ENTRY_ACL_READ_ACL |
111             ARCHIVE_ENTRY_ACL_WRITE_ACL |
112             ARCHIVE_ENTRY_ACL_WRITE_OWNER |
113             ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
114           ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
115         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
116             ARCHIVE_ENTRY_ACL_READ_DATA |
117             ARCHIVE_ENTRY_ACL_EXECUTE |
118             ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
119             ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
120             ARCHIVE_ENTRY_ACL_READ_ACL |
121             ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
122           ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
123         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
124             ARCHIVE_ENTRY_ACL_READ_DATA |
125             ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
126             ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
127             ARCHIVE_ENTRY_ACL_READ_ACL |
128             ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
129           ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
130 #endif
131 };
132
133 static const int acls_reg_cnt = (int)(sizeof(acls_reg)/sizeof(acls_reg[0]));
134
135 static struct myacl_t acls_dir[] = {
136         /* For this test, we need to be able to read and write the ACL. */
137 #if !HAVE_DARWIN_ACL
138         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_READ_ACL,
139           ARCHIVE_ENTRY_ACL_USER_OBJ, -1, ""},
140 #endif
141
142         /* An entry for each type. */
143         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
144           ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
145         { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
146           ARCHIVE_ENTRY_ACL_USER, 102, "user102" },
147
148         /* An entry for each permission. */
149         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
150           ARCHIVE_ENTRY_ACL_USER, 201, "user201" },
151         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_FILE,
152           ARCHIVE_ENTRY_ACL_USER, 202, "user202" },
153         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY,
154           ARCHIVE_ENTRY_ACL_USER, 203, "user203" },
155         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS,
156           ARCHIVE_ENTRY_ACL_USER, 204, "user204" },
157         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS,
158           ARCHIVE_ENTRY_ACL_USER, 205, "user205" },
159         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE_CHILD,
160           ARCHIVE_ENTRY_ACL_USER, 206, "user206" },
161         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES,
162           ARCHIVE_ENTRY_ACL_USER, 207, "user207" },
163         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES,
164           ARCHIVE_ENTRY_ACL_USER, 208, "user208" },
165         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_DELETE,
166           ARCHIVE_ENTRY_ACL_USER, 209, "user209" },
167         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_READ_ACL,
168           ARCHIVE_ENTRY_ACL_USER, 210, "user210" },
169         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_ACL,
170           ARCHIVE_ENTRY_ACL_USER, 211, "user211" },
171         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_WRITE_OWNER,
172           ARCHIVE_ENTRY_ACL_USER, 212, "user212" },
173         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
174           ARCHIVE_ENTRY_ACL_USER, 213, "user213" },
175
176         /* One entry with each inheritance value. */
177         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
178           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT,
179           ARCHIVE_ENTRY_ACL_USER, 301, "user301" },
180         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
181           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT,
182           ARCHIVE_ENTRY_ACL_USER, 302, "user302" },
183 #if 0
184         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
185           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
186           ARCHIVE_ENTRY_ACL_USER, 303, "user303" },
187         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
188           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY,
189           ARCHIVE_ENTRY_ACL_USER, 304, "user304" },
190         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
191           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
192           ARCHIVE_ENTRY_ACL_USER, 305, "user305" },
193 #endif
194
195 #if 0
196         /* FreeBSD does not support audit entries. */
197         { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
198           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS,
199           ARCHIVE_ENTRY_ACL_USER, 401, "user401" },
200         { ARCHIVE_ENTRY_ACL_TYPE_AUDIT,
201           ARCHIVE_ENTRY_ACL_READ_DATA | ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS,
202           ARCHIVE_ENTRY_ACL_USER, 402, "user402" },
203 #endif
204
205         /* One entry for each qualifier. */
206         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
207           ARCHIVE_ENTRY_ACL_USER, 501, "user501" },
208         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
209           ARCHIVE_ENTRY_ACL_GROUP, 502, "group502" },
210 #if !HAVE_DARWIN_ACL
211         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
212           ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
213         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY,
214           ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
215 #else   /* MacOS - mode 0654 */
216         { ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_EXECUTE,
217           ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
218         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
219             ARCHIVE_ENTRY_ACL_READ_DATA |
220             ARCHIVE_ENTRY_ACL_WRITE_DATA |
221             ARCHIVE_ENTRY_ACL_APPEND_DATA |
222             ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
223             ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
224             ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
225             ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
226             ARCHIVE_ENTRY_ACL_READ_ACL |
227             ARCHIVE_ENTRY_ACL_WRITE_ACL |
228             ARCHIVE_ENTRY_ACL_WRITE_OWNER |
229             ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
230           ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
231         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
232             ARCHIVE_ENTRY_ACL_READ_DATA |
233             ARCHIVE_ENTRY_ACL_EXECUTE |
234             ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
235             ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
236             ARCHIVE_ENTRY_ACL_READ_ACL |
237             ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
238           ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
239         { ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
240             ARCHIVE_ENTRY_ACL_READ_DATA |
241             ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
242             ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
243             ARCHIVE_ENTRY_ACL_READ_ACL |
244             ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
245           ARCHIVE_ENTRY_ACL_EVERYONE, -1, "" }
246 #endif
247 };
248
249 static const int acls_dir_cnt = (int)(sizeof(acls_dir)/sizeof(acls_dir[0]));
250
251 static void
252 set_acls(struct archive_entry *ae, struct myacl_t *acls, int start, int end)
253 {
254         int i;
255
256         archive_entry_acl_clear(ae);
257 #if !HAVE_DARWIN_ACL
258         if (start > 0) {
259                 assertEqualInt(ARCHIVE_OK,
260                         archive_entry_acl_add_entry(ae,
261                             acls[0].type, acls[0].permset, acls[0].tag,
262                             acls[0].qual, acls[0].name));
263         }
264 #endif
265         for (i = start; i < end; i++) {
266                 assertEqualInt(ARCHIVE_OK,
267                     archive_entry_acl_add_entry(ae,
268                         acls[i].type, acls[i].permset, acls[i].tag,
269                         acls[i].qual, acls[i].name));
270         }
271 }
272
273 static int
274 #ifdef HAVE_SUN_NFS4_ACL
275 acl_permset_to_bitmap(uint32_t a_access_mask)
276 #else
277 acl_permset_to_bitmap(acl_permset_t opaque_ps)
278 #endif
279 {
280         static struct { int machine; int portable; } perms[] = {
281 #ifdef HAVE_SUN_NFS4_ACL        /* Solaris NFSv4 ACL permissions */
282                 {ACE_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
283                 {ACE_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
284                 {ACE_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
285                 {ACE_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
286                 {ACE_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
287                 {ACE_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
288                 {ACE_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
289                 {ACE_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
290                 {ACE_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
291                 {ACE_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
292                 {ACE_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
293                 {ACE_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
294                 {ACE_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
295                 {ACE_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
296                 {ACE_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
297                 {ACE_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
298                 {ACE_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
299 #elif HAVE_DARWIN_ACL   /* MacOS NFSv4 ACL permissions */
300                 {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
301                 {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
302                 {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
303                 {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
304                 {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
305                 {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
306                 {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
307                 {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
308                 {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
309                 {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
310                 {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
311                 {ACL_READ_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
312                 {ACL_WRITE_EXTATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
313                 {ACL_READ_SECURITY, ARCHIVE_ENTRY_ACL_READ_ACL},
314                 {ACL_WRITE_SECURITY, ARCHIVE_ENTRY_ACL_WRITE_ACL},
315                 {ACL_CHANGE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
316 #if HAVE_DECL_ACL_SYNCHRONIZE
317                 {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE},
318 #endif
319 #else   /* FreeBSD NFSv4 ACL permissions */
320                 {ACL_EXECUTE, ARCHIVE_ENTRY_ACL_EXECUTE},
321                 {ACL_WRITE, ARCHIVE_ENTRY_ACL_WRITE},
322                 {ACL_READ, ARCHIVE_ENTRY_ACL_READ},
323                 {ACL_READ_DATA, ARCHIVE_ENTRY_ACL_READ_DATA},
324                 {ACL_LIST_DIRECTORY, ARCHIVE_ENTRY_ACL_LIST_DIRECTORY},
325                 {ACL_WRITE_DATA, ARCHIVE_ENTRY_ACL_WRITE_DATA},
326                 {ACL_ADD_FILE, ARCHIVE_ENTRY_ACL_ADD_FILE},
327                 {ACL_APPEND_DATA, ARCHIVE_ENTRY_ACL_APPEND_DATA},
328                 {ACL_ADD_SUBDIRECTORY, ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY},
329                 {ACL_READ_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS},
330                 {ACL_WRITE_NAMED_ATTRS, ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS},
331                 {ACL_DELETE_CHILD, ARCHIVE_ENTRY_ACL_DELETE_CHILD},
332                 {ACL_READ_ATTRIBUTES, ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES},
333                 {ACL_WRITE_ATTRIBUTES, ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES},
334                 {ACL_DELETE, ARCHIVE_ENTRY_ACL_DELETE},
335                 {ACL_READ_ACL, ARCHIVE_ENTRY_ACL_READ_ACL},
336                 {ACL_WRITE_ACL, ARCHIVE_ENTRY_ACL_WRITE_ACL},
337                 {ACL_WRITE_OWNER, ARCHIVE_ENTRY_ACL_WRITE_OWNER},
338                 {ACL_SYNCHRONIZE, ARCHIVE_ENTRY_ACL_SYNCHRONIZE}
339 #endif
340         };
341         int i, permset = 0;
342
343         for (i = 0; i < (int)(sizeof(perms)/sizeof(perms[0])); ++i)
344 #if HAVE_SUN_NFS4_ACL
345                 if (a_access_mask & perms[i].machine)
346 #else
347                 if (acl_get_perm_np(opaque_ps, perms[i].machine))
348 #endif
349                         permset |= perms[i].portable;
350         return permset;
351 }
352
353 static int
354 #if HAVE_SUN_NFS4_ACL
355 acl_flagset_to_bitmap(uint16_t a_flags)
356 #else
357 acl_flagset_to_bitmap(acl_flagset_t opaque_fs)
358 #endif
359 {
360         static struct { int machine; int portable; } flags[] = {
361 #if HAVE_SUN_NFS4_ACL   /* Solaris NFSv4 ACL inheritance flags */
362                 {ACE_FILE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
363                 {ACE_DIRECTORY_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
364                 {ACE_NO_PROPAGATE_INHERIT_ACE, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
365                 {ACE_INHERIT_ONLY_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
366                 {ACE_SUCCESSFUL_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
367                 {ACE_FAILED_ACCESS_ACE_FLAG, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
368 #ifdef ACE_INHERITED_ACE
369                 {ACE_INHERITED_ACE, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED}
370 #endif
371 #elif HAVE_DARWIN_ACL   /* MacOS NFSv4 ACL inheritance flags */
372                 {ACL_ENTRY_INHERITED, ARCHIVE_ENTRY_ACL_ENTRY_INHERITED},
373                 {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
374                 {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
375                 {ACL_ENTRY_LIMIT_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
376                 {ACL_ENTRY_ONLY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY}
377 #else   /* FreeBSD NFSv4 ACL inheritance flags */
378                 {ACL_ENTRY_FILE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT},
379                 {ACL_ENTRY_DIRECTORY_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT},
380                 {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT},
381                 {ACL_ENTRY_SUCCESSFUL_ACCESS, ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS},
382                 {ACL_ENTRY_NO_PROPAGATE_INHERIT, ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS},
383                 {ACL_ENTRY_INHERIT_ONLY, ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY},
384 #endif
385         };
386         int i, flagset = 0;
387
388         for (i = 0; i < (int)(sizeof(flags)/sizeof(flags[0])); ++i)
389 #if HAVE_SUN_NFS4_ACL
390                 if (a_flags & flags[i].machine)
391 #else
392                 if (acl_get_flag_np(opaque_fs, flags[i].machine))
393 #endif
394                         flagset |= flags[i].portable;
395         return flagset;
396 }
397
398 static int
399 #if HAVE_SUN_NFS4_ACL
400 acl_match(ace_t *ace, struct myacl_t *myacl)
401 #else
402 acl_match(acl_entry_t aclent, struct myacl_t *myacl)
403 #endif
404 {
405 #if !HAVE_SUN_NFS4_ACL
406 #if HAVE_DARWIN_ACL
407         void *q;
408         uid_t ugid;
409         int r, idtype;
410 #else
411         gid_t g, *gp;
412         uid_t u, *up;
413         acl_entry_type_t entry_type;
414 #endif  /* !HAVE_DARWIN_ACL */
415         acl_tag_t tag_type;
416         acl_permset_t opaque_ps;
417         acl_flagset_t opaque_fs;
418 #endif  /* !HAVE_SUN_NFS4_ACL */
419         int perms;
420
421 #if HAVE_SUN_NFS4_ACL
422         perms = acl_permset_to_bitmap(ace->a_access_mask) | acl_flagset_to_bitmap(ace->a_flags);
423 #else
424         acl_get_tag_type(aclent, &tag_type);
425 #if !HAVE_DARWIN_ACL
426         acl_get_entry_type_np(aclent, &entry_type);
427 #endif
428
429         /* translate the silly opaque permset to a bitmap */
430         acl_get_permset(aclent, &opaque_ps);
431         acl_get_flagset_np(aclent, &opaque_fs);
432         perms = acl_permset_to_bitmap(opaque_ps) | acl_flagset_to_bitmap(opaque_fs);
433 #endif
434         if (perms != myacl->permset)
435                 return (0);
436
437 #if HAVE_SUN_NFS4_ACL
438         switch (ace->a_type) {
439         case ACE_ACCESS_ALLOWED_ACE_TYPE:
440                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
441                         return (0);
442                 break;
443         case ACE_ACCESS_DENIED_ACE_TYPE:
444                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
445                         return (0);
446                 break;
447         case ACE_SYSTEM_AUDIT_ACE_TYPE:
448                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
449                         return (0);
450                 break;
451         case ACE_SYSTEM_ALARM_ACE_TYPE:
452                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
453                         return (0);
454                 break;
455         default:
456                 return (0);
457         }
458
459         if (ace->a_flags & ACE_OWNER) {
460                 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ)
461                         return (0);
462         } else if (ace->a_flags & ACE_GROUP) {
463                 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ)
464                         return (0);
465         } else if (ace->a_flags & ACE_EVERYONE) {
466                 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE)
467                         return (0);
468         } else if (ace->a_flags & ACE_IDENTIFIER_GROUP) {
469                 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
470                         return (0);
471                 if ((gid_t)myacl->qual != ace->a_who)
472                         return (0);
473         } else {
474                 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
475                         return (0);
476                 if ((uid_t)myacl->qual != ace->a_who)
477                         return (0);
478         }
479 #elif HAVE_DARWIN_ACL
480         r = 0;
481         switch (tag_type) {
482         case ACL_EXTENDED_ALLOW:
483                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
484                         return (0);
485                 break;
486         case ACL_EXTENDED_DENY:
487                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
488                         return (0);
489                 break;
490         default:
491                 return (0);
492         }
493         q = acl_get_qualifier(aclent);
494         if (q == NULL)
495                 return (0);
496         r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
497         acl_free(q);
498         if (r != 0)
499                 return (0);
500         switch (idtype) {
501                 case ID_TYPE_UID:
502                         if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
503                                 return (0);
504                         if ((uid_t)myacl->qual != ugid)
505                                 return (0);
506                         break;
507                 case ID_TYPE_GID:
508                         if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
509                                 return (0);
510                         if ((gid_t)myacl->qual != ugid)
511                                 return (0);
512                         break;
513                 default:
514                         return (0);
515         }
516 #else   /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */
517         switch (entry_type) {
518         case ACL_ENTRY_TYPE_ALLOW:
519                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALLOW)
520                         return (0);
521                 break;
522         case ACL_ENTRY_TYPE_DENY:
523                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_DENY)
524                         return (0);
525                 break;
526         case ACL_ENTRY_TYPE_AUDIT:
527                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_AUDIT)
528                         return (0);
529         case ACL_ENTRY_TYPE_ALARM:
530                 if (myacl->type != ARCHIVE_ENTRY_ACL_TYPE_ALARM)
531                         return (0);
532         default:
533                 return (0);
534         }
535
536         switch (tag_type) {
537         case ACL_USER_OBJ:
538                 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
539                 break;
540         case ACL_USER:
541                 if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
542                         return (0);
543                 up = acl_get_qualifier(aclent);
544                 u = *up;
545                 acl_free(up);
546                 if ((uid_t)myacl->qual != u)
547                         return (0);
548                 break;
549         case ACL_GROUP_OBJ:
550                 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
551                 break;
552         case ACL_GROUP:
553                 if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
554                         return (0);
555                 gp = acl_get_qualifier(aclent);
556                 g = *gp;
557                 acl_free(gp);
558                 if ((gid_t)myacl->qual != g)
559                         return (0);
560                 break;
561         case ACL_MASK:
562                 if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
563                 break;
564         case ACL_EVERYONE:
565                 if (myacl->tag != ARCHIVE_ENTRY_ACL_EVERYONE) return (0);
566                 break;
567         }
568 #endif  /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */
569         return (1);
570 }
571
572 static void
573 compare_acls(
574 #if HAVE_SUN_NFS4_ACL
575     void *aclp,
576     int aclcnt,
577 #else
578     acl_t acl,
579 #endif
580     struct myacl_t *myacls, const char *filename, int start, int end)
581 {
582         int *marker;
583         int matched;
584         int i, n;
585 #if HAVE_SUN_NFS4_ACL
586         int e;
587         ace_t *acl_entry;
588 #else
589         int entry_id = ACL_FIRST_ENTRY;
590         acl_entry_t acl_entry;
591 #endif
592
593         n = end - start;
594         marker = malloc(sizeof(marker[0]) * (n + 1));
595         for (i = 0; i < n; i++)
596                 marker[i] = i + start;
597 #if !HAVE_DARWIN_ACL
598         /* Always include the first ACE. */
599         if (start > 0) {
600           marker[n] = 0;
601           ++n;
602         }
603 #endif
604
605         /*
606          * Iterate over acls in system acl object, try to match each
607          * one with an item in the myacls array.
608          */
609 #if HAVE_SUN_NFS4_ACL
610         for (e = 0; e < aclcnt; e++)
611 #elif HAVE_DARWIN_ACL
612         while (0 == acl_get_entry(acl, entry_id, &acl_entry))
613 #else
614         while (1 == acl_get_entry(acl, entry_id, &acl_entry))
615 #endif
616         {
617 #if HAVE_SUN_NFS4_ACL
618                 acl_entry = &((ace_t *)aclp)[e];
619 #else
620                 /* After the first time... */
621                 entry_id = ACL_NEXT_ENTRY;
622 #endif
623                 /* Search for a matching entry (tag and qualifier) */
624                 for (i = 0, matched = 0; i < n && !matched; i++) {
625                         if (acl_match(acl_entry, &myacls[marker[i]])) {
626                                 /* We found a match; remove it. */
627                                 marker[i] = marker[n - 1];
628                                 n--;
629                                 matched = 1;
630                         }
631                 }
632
633                 failure("ACL entry on file %s that shouldn't be there",
634                     filename);
635                 assert(matched == 1);
636         }
637
638         /* Dump entries in the myacls array that weren't in the system acl. */
639         for (i = 0; i < n; ++i) {
640                 failure(" ACL entry %d missing from %s: "
641                     "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
642                     marker[i], filename,
643                     myacls[marker[i]].type, myacls[marker[i]].permset,
644                     myacls[marker[i]].tag, myacls[marker[i]].qual,
645                     myacls[marker[i]].name);
646                 assert(0); /* Record this as a failure. */
647         }
648         free(marker);
649 }
650
651 static void
652 compare_entry_acls(struct archive_entry *ae, struct myacl_t *myacls, const char *filename, int start, int end)
653 {
654         int *marker;
655         int matched;
656         int i, n;
657         int type, permset, tag, qual;
658         const char *name;
659
660         /* Count ACL entries in myacls array and allocate an indirect array. */
661         n = end - start;
662         marker = malloc(sizeof(marker[0]) * (n + 1));
663         for (i = 0; i < n; i++)
664                 marker[i] = i + start;
665         /* Always include the first ACE. */
666         if (start > 0) {
667           marker[n] = 0;
668           ++n;
669         }
670
671         /*
672          * Iterate over acls in entry, try to match each
673          * one with an item in the myacls array.
674          */
675         assertEqualInt(n, archive_entry_acl_reset(ae,
676             ARCHIVE_ENTRY_ACL_TYPE_NFS4));
677         while (ARCHIVE_OK == archive_entry_acl_next(ae,
678             ARCHIVE_ENTRY_ACL_TYPE_NFS4, &type, &permset, &tag, &qual, &name)) {
679
680                 /* Search for a matching entry (tag and qualifier) */
681                 for (i = 0, matched = 0; i < n && !matched; i++) {
682                         if (tag == myacls[marker[i]].tag
683                             && qual == myacls[marker[i]].qual
684                             && permset == myacls[marker[i]].permset
685                             && type == myacls[marker[i]].type) {
686                                 /* We found a match; remove it. */
687                                 marker[i] = marker[n - 1];
688                                 n--;
689                                 matched = 1;
690                         }
691                 }
692
693                 failure("ACL entry on file that shouldn't be there: "
694                         "type=%#010x,permset=%#010x,tag=%d,qual=%d",
695                         type,permset,tag,qual);
696                 assert(matched == 1);
697         }
698
699         /* Dump entries in the myacls array that weren't in the system acl. */
700         for (i = 0; i < n; ++i) {
701                 failure(" ACL entry %d missing from %s: "
702                     "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
703                     marker[i], filename,
704                     myacls[marker[i]].type, myacls[marker[i]].permset,
705                     myacls[marker[i]].tag, myacls[marker[i]].qual,
706                     myacls[marker[i]].name);
707                 assert(0); /* Record this as a failure. */
708         }
709         free(marker);
710 }
711 #endif  /* HAVE_NFS4_ACL */
712
713 /*
714  * Verify ACL restore-to-disk.  This test is Platform-specific.
715  */
716
717 DEFINE_TEST(test_acl_platform_nfs4)
718 {
719 #if !HAVE_NFS4_ACL
720         skipping("NFS4 ACLs are not supported on this platform");
721 #else
722         char buff[64];
723         int i;
724         struct stat st;
725         struct archive *a;
726         struct archive_entry *ae;
727 #if HAVE_DARWIN_ACL /* On MacOS we skip trivial ACLs in some tests */
728         const int regcnt = acls_reg_cnt - 4;
729         const int dircnt = acls_dir_cnt - 4;
730 #else
731         const int regcnt = acls_reg_cnt;
732         const int dircnt = acls_dir_cnt;
733 #endif
734 #if HAVE_SUN_NFS4_ACL
735         void *aclp;
736         int aclcnt;
737 #else   /* !HAVE_SUN_NFS4_ACL */
738         acl_t acl;
739 #endif
740
741         assertMakeFile("pretest", 0644, "a");
742
743         if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_NFS4) {
744                 skipping("NFS4 ACLs are not writable on this filesystem");
745                 return;
746         }
747
748         /* Create a write-to-disk object. */
749         assert(NULL != (a = archive_write_disk_new()));
750         archive_write_disk_set_options(a,
751             ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
752
753         /* Populate an archive entry with some metadata, including ACL info */
754         ae = archive_entry_new();
755         assert(ae != NULL);
756         archive_entry_set_pathname(ae, "testall");
757         archive_entry_set_filetype(ae, AE_IFREG);
758         archive_entry_set_perm(ae, 0654);
759         archive_entry_set_mtime(ae, 123456, 7890);
760         archive_entry_set_size(ae, 0);
761         set_acls(ae, acls_reg, 0, acls_reg_cnt);
762
763         /* Write the entry to disk, including ACLs. */
764         assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
765
766         /* Likewise for a dir. */
767         archive_entry_set_pathname(ae, "dirall");
768         archive_entry_set_filetype(ae, AE_IFDIR);
769         archive_entry_set_perm(ae, 0654);
770         archive_entry_set_mtime(ae, 123456, 7890);
771         set_acls(ae, acls_dir, 0, acls_dir_cnt);
772         assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
773
774         for (i = 0; i < acls_dir_cnt; ++i) {
775           sprintf(buff, "dir%d", i);
776           archive_entry_set_pathname(ae, buff);
777           archive_entry_set_filetype(ae, AE_IFDIR);
778           archive_entry_set_perm(ae, 0654);
779           archive_entry_set_mtime(ae, 123456 + i, 7891 + i);
780           set_acls(ae, acls_dir, i, i + 1);
781           assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
782         }
783
784         archive_entry_free(ae);
785
786         /* Close the archive. */
787         assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
788         assertEqualInt(ARCHIVE_OK, archive_write_free(a));
789
790         /* Verify the data on disk. */
791         assertEqualInt(0, stat("testall", &st));
792         assertEqualInt(st.st_mtime, 123456);
793 #if HAVE_SUN_NFS4_ACL
794         aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "testall");
795         failure("acl(): errno = %d (%s)", errno, strerror(errno));
796         assert(aclp != NULL);
797 #else
798 #if HAVE_DARWIN_ACL
799         acl = acl_get_file("testall", ACL_TYPE_EXTENDED);
800 #else
801         acl = acl_get_file("testall", ACL_TYPE_NFS4);
802 #endif
803         failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
804         assert(acl != (acl_t)NULL);
805 #endif
806 #if HAVE_SUN_NFS4_ACL
807         compare_acls(aclp, aclcnt, acls_reg, "testall", 0, regcnt);
808         free(aclp);
809         aclp = NULL;
810 #else
811         compare_acls(acl, acls_reg, "testall", 0, regcnt);
812         acl_free(acl);
813 #endif
814
815
816         /* Verify single-permission dirs on disk. */
817         for (i = 0; i < dircnt; ++i) {
818                 sprintf(buff, "dir%d", i);
819                 assertEqualInt(0, stat(buff, &st));
820                 assertEqualInt(st.st_mtime, 123456 + i);
821 #if HAVE_SUN_NFS4_ACL
822                 aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, buff);
823                 failure("acl(): errno = %d (%s)", errno, strerror(errno));
824                 assert(aclp != NULL);
825 #else
826 #if HAVE_DARWIN_ACL
827                 acl = acl_get_file(buff, ACL_TYPE_EXTENDED);
828 #else
829                 acl = acl_get_file(buff, ACL_TYPE_NFS4);
830 #endif
831                 failure("acl_get_file(): errno = %d (%s)", errno,
832                     strerror(errno));
833                 assert(acl != (acl_t)NULL);
834 #endif
835 #if HAVE_SUN_NFS4_ACL
836                 compare_acls(aclp, aclcnt, acls_dir, buff, i, i + 1);
837                 free(aclp);
838                 aclp = NULL;
839 #else
840                 compare_acls(acl, acls_dir, buff, i, i + 1);
841                 acl_free(acl);
842 #endif
843         }
844
845         /* Verify "dirall" on disk. */
846         assertEqualInt(0, stat("dirall", &st));
847         assertEqualInt(st.st_mtime, 123456);
848 #if HAVE_SUN_NFS4_ACL
849         aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, "dirall");
850         failure("acl(): errno = %d (%s)", errno, strerror(errno));
851         assert(aclp != NULL);
852 #else
853 #if HAVE_DARWIN_ACL
854         acl = acl_get_file("dirall", ACL_TYPE_EXTENDED);
855 #else
856         acl = acl_get_file("dirall", ACL_TYPE_NFS4);
857 #endif
858         failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
859         assert(acl != (acl_t)NULL);
860 #endif
861 #if HAVE_SUN_NFS4_ACL
862         compare_acls(aclp, aclcnt, acls_dir, "dirall", 0, dircnt);
863         free(aclp);
864         aclp = NULL;
865 #else
866         compare_acls(acl, acls_dir, "dirall", 0, dircnt);
867         acl_free(acl);
868 #endif
869
870         /* Read and compare ACL via archive_read_disk */
871         a = archive_read_disk_new();
872         assert(a != NULL);
873         ae = archive_entry_new();
874         assert(ae != NULL);
875         archive_entry_set_pathname(ae, "testall");
876         assertEqualInt(ARCHIVE_OK,
877                        archive_read_disk_entry_from_file(a, ae, -1, NULL));
878         compare_entry_acls(ae, acls_reg, "testall", 0, acls_reg_cnt);
879         archive_entry_free(ae);
880         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
881
882         /* Read and compare ACL via archive_read_disk */
883         a = archive_read_disk_new();
884         assert(a != NULL);
885         ae = archive_entry_new();
886         assert(ae != NULL);
887         archive_entry_set_pathname(ae, "dirall");
888         assertEqualInt(ARCHIVE_OK,
889         archive_read_disk_entry_from_file(a, ae, -1, NULL));
890         compare_entry_acls(ae, acls_dir, "dirall", 0, acls_dir_cnt);
891         archive_entry_free(ae);
892         assertEqualInt(ARCHIVE_OK, archive_read_free(a));
893 #endif /* HAVE_NFS4_ACL */
894 }