1 /*-
2  * Copyright (c) 2016 Martin Matuska
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "test.h"
26 
27 /*
28  * Test converting ACLs to text, both wide and non-wide
29  *
30  * This should work on all systems, regardless of whether local
31  * filesystems support ACLs or not.
32  */
33 
34 static struct archive_test_acl_t acls0[] = {
35 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
36 	    ARCHIVE_ENTRY_ACL_EXECUTE |
37 	    ARCHIVE_ENTRY_ACL_READ |
38 	    ARCHIVE_ENTRY_ACL_WRITE,
39 	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
40 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
41 	    ARCHIVE_ENTRY_ACL_EXECUTE |
42 	    ARCHIVE_ENTRY_ACL_READ,
43 	  ARCHIVE_ENTRY_ACL_USER, 100, "user100" },
44 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
45 	  ARCHIVE_ENTRY_ACL_USER, 1000, "user1000" },
46 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
47 	    ARCHIVE_ENTRY_ACL_EXECUTE |
48 	    ARCHIVE_ENTRY_ACL_READ,
49 	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
50 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
51 	    ARCHIVE_ENTRY_ACL_EXECUTE |
52 	    ARCHIVE_ENTRY_ACL_READ |
53 	    ARCHIVE_ENTRY_ACL_WRITE,
54 	  ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
55 	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
56 	    ARCHIVE_ENTRY_ACL_READ |
57 	    ARCHIVE_ENTRY_ACL_EXECUTE,
58 	  ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
59 	{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
60 	    ARCHIVE_ENTRY_ACL_EXECUTE |
61 	    ARCHIVE_ENTRY_ACL_READ,
62 	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
63 	{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
64 	    ARCHIVE_ENTRY_ACL_EXECUTE |
65 	    ARCHIVE_ENTRY_ACL_READ,
66 	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
67 	{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0,
68 	  ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
69 	{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
70 	    ARCHIVE_ENTRY_ACL_EXECUTE |
71 	    ARCHIVE_ENTRY_ACL_READ,
72 	  ARCHIVE_ENTRY_ACL_USER, 101, "user101"},
73 	{ ARCHIVE_ENTRY_ACL_TYPE_DEFAULT,
74 	    ARCHIVE_ENTRY_ACL_EXECUTE,
75 	  ARCHIVE_ENTRY_ACL_GROUP, 79, "group79" },
76 };
77 
78 static struct archive_test_acl_t acls1[] = {
79 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
80 	    ARCHIVE_ENTRY_ACL_READ_DATA |
81 	    ARCHIVE_ENTRY_ACL_WRITE_DATA |
82 	    ARCHIVE_ENTRY_ACL_APPEND_DATA |
83 	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
84 	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
85 	    ARCHIVE_ENTRY_ACL_READ_ACL |
86 	    ARCHIVE_ENTRY_ACL_WRITE_OWNER,
87 	  ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
88 	{ ARCHIVE_ENTRY_ACL_TYPE_DENY,
89 	    ARCHIVE_ENTRY_ACL_WRITE_DATA |
90 	    ARCHIVE_ENTRY_ACL_APPEND_DATA |
91 	    ARCHIVE_ENTRY_ACL_DELETE_CHILD |
92 	    ARCHIVE_ENTRY_ACL_DELETE |
93 	    ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT |
94 	    ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT |
95 	    ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY |
96 	    ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT,
97 	  ARCHIVE_ENTRY_ACL_USER, 101, "user101" },
98 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
99 	    ARCHIVE_ENTRY_ACL_READ_DATA |
100 	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
101 	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
102 	    ARCHIVE_ENTRY_ACL_READ_ACL |
103 	    ARCHIVE_ENTRY_ACL_ENTRY_INHERITED,
104 	  ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
105 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
106 	    ARCHIVE_ENTRY_ACL_READ_DATA |
107 	    ARCHIVE_ENTRY_ACL_WRITE_DATA |
108 	    ARCHIVE_ENTRY_ACL_EXECUTE |
109 	    ARCHIVE_ENTRY_ACL_APPEND_DATA |
110 	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
111 	    ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
112 	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
113 	    ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
114 	    ARCHIVE_ENTRY_ACL_READ_ACL |
115 	    ARCHIVE_ENTRY_ACL_WRITE_ACL |
116 	    ARCHIVE_ENTRY_ACL_WRITE_OWNER,
117 	  ARCHIVE_ENTRY_ACL_USER_OBJ, 0, "" },
118 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
119 	    ARCHIVE_ENTRY_ACL_READ_DATA |
120 	    ARCHIVE_ENTRY_ACL_WRITE_DATA |
121 	    ARCHIVE_ENTRY_ACL_APPEND_DATA |
122 	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
123 	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
124 	    ARCHIVE_ENTRY_ACL_READ_ACL,
125 	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0, "" },
126 	{ ARCHIVE_ENTRY_ACL_TYPE_ALLOW,
127 	    ARCHIVE_ENTRY_ACL_READ_DATA |
128 	    ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
129 	    ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
130 	    ARCHIVE_ENTRY_ACL_READ_ACL |
131 	    ARCHIVE_ENTRY_ACL_SYNCHRONIZE,
132 	  ARCHIVE_ENTRY_ACL_EVERYONE, 0, "" },
133 };
134 
135 const char* acltext[] = {
136 	"user::rwx\n"
137 	"group::r-x\n"
138 	"other::r-x\n"
139 	"user:user100:r-x\n"
140 	"user:user1000:---\n"
141 	"group:group78:rwx\n"
142 	"default:user::r-x\n"
143 	"default:group::r-x\n"
144 	"default:other::---\n"
145 	"default:user:user101:r-x\n"
146 	"default:group:group79:--x",
147 
148 	"user::rwx\n"
149 	"group::r-x\n"
150 	"other::r-x\n"
151 	"user:user100:r-x:100\n"
152 	"user:user1000:---:1000\n"
153 	"group:group78:rwx:78\n"
154 	"default:user::r-x\n"
155 	"default:group::r-x\n"
156 	"default:other::---\n"
157 	"default:user:user101:r-x:101\n"
158 	"default:group:group79:--x:79",
159 
160 	"u::rwx\n"
161 	"g::r-x\n"
162 	"o::r-x\n"
163 	"u:user100:r-x:100\n"
164 	"u:user1000:---:1000\n"
165 	"g:group78:rwx:78\n"
166 	"d:user::r-x\n"
167 	"d:group::r-x\n"
168 	"d:other::---\n"
169 	"d:user:user101:r-x:101\n"
170 	"d:group:group79:--x:79",
171 
172 	"user::rwx\n"
173 	"group::r-x\n"
174 	"other::r-x\n"
175 	"user:user100:r-x\n"
176 	"user:user1000:---\n"
177 	"group:group78:rwx",
178 
179 	"user::rwx,"
180 	"group::r-x,"
181 	"other::r-x,"
182 	"user:user100:r-x,"
183 	"user:user1000:---,"
184 	"group:group78:rwx",
185 
186 	"user::rwx\n"
187 	"group::r-x\n"
188 	"other::r-x\n"
189 	"user:user100:r-x:100\n"
190 	"user:user1000:---:1000\n"
191 	"group:group78:rwx:78",
192 
193 	"user::r-x\n"
194 	"group::r-x\n"
195 	"other::---\n"
196 	"user:user101:r-x\n"
197 	"group:group79:--x",
198 
199 	"user::r-x\n"
200 	"group::r-x\n"
201 	"other::---\n"
202 	"user:user101:r-x:101\n"
203 	"group:group79:--x:79",
204 
205 	"default:user::r-x\n"
206 	"default:group::r-x\n"
207 	"default:other::---\n"
208 	"default:user:user101:r-x\n"
209 	"default:group:group79:--x",
210 
211 	"user:user77:rw-p--a-R-c-o-:-------:allow\n"
212 	"user:user101:-w-pdD--------:fdin---:deny\n"
213 	"group:group78:r-----a-R-c---:------I:allow\n"
214 	"owner@:rwxp--aARWcCo-:-------:allow\n"
215 	"group@:rw-p--a-R-c---:-------:allow\n"
216 	"everyone@:r-----a-R-c--s:-------:allow",
217 
218 	"user:user77:rw-p--a-R-c-o-:-------:allow:77\n"
219 	"user:user101:-w-pdD--------:fdin---:deny:101\n"
220 	"group:group78:r-----a-R-c---:------I:allow:78\n"
221 	"owner@:rwxp--aARWcCo-:-------:allow\n"
222 	"group@:rw-p--a-R-c---:-------:allow\n"
223 	"everyone@:r-----a-R-c--s:-------:allow",
224 
225 	"user:user77:rwpaRco::allow:77\n"
226 	"user:user101:wpdD:fdin:deny:101\n"
227 	"group:group78:raRc:I:allow:78\n"
228 	"owner@:rwxpaARWcCo::allow\n"
229 	"group@:rwpaRc::allow\n"
230 	"everyone@:raRcs::allow"
231 };
232 
233 static wchar_t *
234 convert_s_to_ws(const char *s)
235 {
236 	size_t len;
237 	wchar_t *ws = NULL;
238 
239 	if (s != NULL) {
240 		len = strlen(s) + 1;
241 		ws = malloc(len * sizeof(wchar_t));
242 		assert(mbstowcs(ws, s, len) != (size_t)-1);
243 	}
244 
245 	return (ws);
246 }
247 
248 static void
249 compare_acl_text(struct archive_entry *ae, int flags, const char *s)
250 {
251 	char *text;
252 	wchar_t *wtext;
253 	wchar_t *ws;
254 	ssize_t slen;
255 
256 	ws = convert_s_to_ws(s);
257 
258 	text = archive_entry_acl_to_text(ae, &slen, flags);
259 	assertEqualString(text, s);
260 	if (text != NULL)
261 		assertEqualInt(strlen(text), slen);
262 	wtext = archive_entry_acl_to_text_w(ae, &slen, flags);
263 	assertEqualWString(wtext, ws);
264 	if (wtext != NULL) {
265 		assertEqualInt(wcslen(wtext), slen);
266 	}
267 	free(text);
268 	free(wtext);
269 	free(ws);
270 }
271 
272 DEFINE_TEST(test_acl_from_text)
273 {
274 	struct archive_entry *ae;
275 	wchar_t *ws = NULL;
276 
277 	/* Create an empty archive_entry. */
278 	assert((ae = archive_entry_new()) != NULL);
279 
280 	/* 1a. Read POSIX.1e access ACLs from text */
281 	assertEqualInt(ARCHIVE_OK,
282 	    archive_entry_acl_from_text(ae, acltext[5],
283 	    ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
284 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
285 	    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755);
286 	assertEqualInt(6, archive_entry_acl_reset(ae,
287 	    ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
288 
289 	/* 1b. Now read POSIX.1e default ACLs and append them */
290 	assertEqualInt(ARCHIVE_OK,
291 	    archive_entry_acl_from_text(ae, acltext[7],
292 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
293 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
294 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
295 	assertEqualInt(11, archive_entry_acl_reset(ae,
296 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
297 	archive_entry_acl_clear(ae);
298 
299 	/* 1a and 1b with wide strings */
300 	ws = convert_s_to_ws(acltext[5]);
301 
302 	assertEqualInt(ARCHIVE_OK,
303 	    archive_entry_acl_from_text_w(ae, ws,
304 	    ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
305 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
306 	    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0755);
307 	assertEqualInt(6, archive_entry_acl_reset(ae,
308 	    ARCHIVE_ENTRY_ACL_TYPE_ACCESS));
309 
310 	free(ws);
311 	ws = convert_s_to_ws(acltext[7]);
312 
313 	assertEqualInt(ARCHIVE_OK,
314 	    archive_entry_acl_from_text_w(ae, ws,
315 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
316 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
317 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
318 	assertEqualInt(11, archive_entry_acl_reset(ae,
319 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
320 	archive_entry_acl_clear(ae);
321 
322 	/* 2. Read POSIX.1e default ACLs from text */
323 	assertEqualInt(ARCHIVE_OK,
324 	    archive_entry_acl_from_text(ae, acltext[7],
325 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
326 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
327 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0);
328 	assertEqualInt(5, archive_entry_acl_reset(ae,
329 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
330 	archive_entry_acl_clear(ae);
331 
332 	/* ws is still acltext[7] */
333 	assertEqualInt(ARCHIVE_OK,
334 	    archive_entry_acl_from_text_w(ae, ws,
335 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
336 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
337 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, 0);
338 	assertEqualInt(5, archive_entry_acl_reset(ae,
339 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT));
340 	archive_entry_acl_clear(ae);
341 
342 	/* 3. Read POSIX.1e access and default ACLs from text */
343 	assertEqualInt(ARCHIVE_OK,
344 	    archive_entry_acl_from_text(ae, acltext[1],
345 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
346 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
347 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
348 	assertEqualInt(11, archive_entry_acl_reset(ae,
349 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
350 	archive_entry_acl_clear(ae);
351 
352 	free(ws);
353 	ws = convert_s_to_ws(acltext[1]);
354 	assertEqualInt(ARCHIVE_OK,
355 	    archive_entry_acl_from_text_w(ae, ws,
356 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
357 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
358 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
359 	assertEqualInt(11, archive_entry_acl_reset(ae,
360 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
361 	archive_entry_acl_clear(ae);
362 
363 	/* 4. Read POSIX.1e access and default ACLs from text (short form) */
364 	assertEqualInt(ARCHIVE_OK,
365 	    archive_entry_acl_from_text(ae, acltext[2],
366 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
367 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
368 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
369 	assertEqualInt(11, archive_entry_acl_reset(ae,
370 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
371 	archive_entry_acl_clear(ae);
372 
373 	free(ws);
374 	ws = convert_s_to_ws(acltext[2]);
375 	assertEqualInt(ARCHIVE_OK,
376 	    archive_entry_acl_from_text_w(ae, ws,
377 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
378 	assertEntryCompareAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]),
379 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E, 0755);
380 	assertEqualInt(11, archive_entry_acl_reset(ae,
381 	    ARCHIVE_ENTRY_ACL_TYPE_POSIX1E));
382 	archive_entry_acl_clear(ae);
383 
384 	/* 5. Read NFSv4 ACLs from text */
385 	assertEqualInt(ARCHIVE_OK,
386 	    archive_entry_acl_from_text(ae, acltext[10],
387 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4));
388 	assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
389 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
390 	assertEqualInt(6, archive_entry_acl_reset(ae,
391 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4));
392 	archive_entry_acl_clear(ae);
393 
394 	free(ws);
395 	ws = convert_s_to_ws(acltext[10]);
396 
397 	assertEqualInt(ARCHIVE_OK,
398 	    archive_entry_acl_from_text_w(ae, ws,
399 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4));
400 	assertEntryCompareAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]),
401 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4, 0);
402 	assertEqualInt(6, archive_entry_acl_reset(ae,
403 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4));
404 	archive_entry_acl_clear(ae);
405 
406 	free(ws);
407 	archive_entry_free(ae);
408 }
409 
410 DEFINE_TEST(test_acl_to_text)
411 {
412 	struct archive_entry *ae;
413 
414 	/* Create an empty archive_entry. */
415 	assert((ae = archive_entry_new()) != NULL);
416 
417 	/* Write POSIX.1e ACLs  */
418 	assertEntrySetAcls(ae, acls0, sizeof(acls0)/sizeof(acls0[0]));
419 
420 	/* No flags should give output like getfacl(1) on linux */
421 	compare_acl_text(ae, 0, acltext[0]);
422 
423 	/* This should give the same output as previous test */
424 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
425 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, acltext[0]);
426 
427 	/* This should give the same output as previous two tests */
428 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
429 	    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
430 	    ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[0]);
431 
432 	/* POSIX.1e access and default ACLs with appended ID */
433 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[1]);
434 
435 	/* POSIX.1e access acls only, like getfacl(1) on FreeBSD */
436 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS, acltext[3]);
437 
438 	/* POSIX.1e access acls separated with comma */
439 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
440 	    ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA,
441 	    acltext[4]);
442 
443 	/* POSIX.1e access acls with appended user or group ID */
444 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_ACCESS |
445 	    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[5]);
446 
447 	/* POSIX.1e default acls */
448 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, acltext[6]);
449 
450 	/* POSIX.1e default acls with appended user or group ID */
451 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
452 	    ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[7]);
453 
454 	/* POSIX.1e default acls prefixed with default: */
455 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_TYPE_DEFAULT |
456 	    ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT, acltext[8]);
457 
458 	/* Write NFSv4 ACLs */
459 	assertEntrySetAcls(ae, acls1, sizeof(acls1)/sizeof(acls1[0]));
460 
461 	/* NFSv4 ACLs like getfacl(1) on FreeBSD */
462 	compare_acl_text(ae, 0, acltext[9]);
463 
464 	/* NFSv4 ACLs like "getfacl -i" on FreeBSD */
465 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID, acltext[10]);
466 
467 	/* NFSv4 ACLs like "getfacl -i" on FreeBSD with stripped minus chars */
468 	compare_acl_text(ae, ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID |
469 	    ARCHIVE_ENTRY_ACL_STYLE_COMPACT, acltext[11]);
470 
471 	archive_entry_free(ae);
472 }
473