test_acl_platform_posix1e.c revision 316337
1/*-
2 * Copyright (c) 2003-2008 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: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
28
29#if ARCHIVE_ACL_POSIX1E
30#include <sys/acl.h>
31#if HAVE_ACL_GET_PERM
32#include <acl/libacl.h>
33#define ACL_GET_PERM acl_get_perm
34#elif HAVE_ACL_GET_PERM_NP
35#define ACL_GET_PERM acl_get_perm_np
36#endif
37
38static struct archive_test_acl_t acls2[] = {
39	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
40	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
41	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
42	  ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
43	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
44	  ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
45	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
46	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
47	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
48	  ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
49	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
50	  ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
51	  ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
52	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
53	  ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
54	  ARCHIVE_ENTRY_ACL_MASK, -1, "" },
55};
56
57static int
58#if ARCHIVE_ACL_SUNOS
59acl_entry_get_perm(aclent_t *aclent)
60#else
61acl_entry_get_perm(acl_entry_t aclent)
62#endif
63{
64	int permset = 0;
65#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
66	acl_permset_t opaque_ps;
67#endif
68
69#if ARCHIVE_ACL_SUNOS
70	if (aclent->a_perm & 1)
71		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
72	if (aclent->a_perm & 2)
73		permset |= ARCHIVE_ENTRY_ACL_WRITE;
74	if (aclent->a_perm & 4)
75		permset |= ARCHIVE_ENTRY_ACL_READ;
76#else
77	/* translate the silly opaque permset to a bitmap */
78	acl_get_permset(aclent, &opaque_ps);
79	if (ACL_GET_PERM(opaque_ps, ACL_EXECUTE))
80		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
81	if (ACL_GET_PERM(opaque_ps, ACL_WRITE))
82		permset |= ARCHIVE_ENTRY_ACL_WRITE;
83	if (ACL_GET_PERM(opaque_ps, ACL_READ))
84		permset |= ARCHIVE_ENTRY_ACL_READ;
85#endif
86	return permset;
87}
88
89#if 0
90static int
91acl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_tag) {
92	int entry_id = ACL_FIRST_ENTRY;
93	acl_entry_t acl_entry;
94	acl_tag_t acl_tag_type;
95
96	while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
97		/* After the first time... */
98		entry_id = ACL_NEXT_ENTRY;
99
100		/* If this matches, return perm mask */
101		acl_get_tag_type(acl_entry, &acl_tag_type);
102		if (acl_tag_type == requested_tag_type) {
103			switch (acl_tag_type) {
104			case ACL_USER_OBJ:
105				if ((uid_t)requested_tag == *(uid_t *)(acl_get_qualifier(acl_entry))) {
106					return acl_entry_get_perm(acl_entry);
107				}
108				break;
109			case ACL_GROUP_OBJ:
110				if ((gid_t)requested_tag == *(gid_t *)(acl_get_qualifier(acl_entry))) {
111					return acl_entry_get_perm(acl_entry);
112				}
113				break;
114			case ACL_USER:
115			case ACL_GROUP:
116			case ACL_OTHER:
117				return acl_entry_get_perm(acl_entry);
118			default:
119				failure("Unexpected ACL tag type");
120				assert(0);
121			}
122		}
123
124
125	}
126	return -1;
127}
128#endif
129
130#if ARCHIVE_ACL_SUNOS
131static int
132acl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
133{
134
135	if (myacl->permset != acl_entry_get_perm(aclent))
136		return (0);
137
138	switch (aclent->a_type) {
139	case DEF_USER_OBJ:
140	case USER_OBJ:
141		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
142		break;
143		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
144			return (0);
145		if ((uid_t)myacl->qual != aclent->a_id)
146			return (0);
147		break;
148	case DEF_GROUP_OBJ:
149	case GROUP_OBJ:
150		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
151		break;
152	case DEF_GROUP:
153	case GROUP:
154		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
155			return (0);
156		if ((gid_t)myacl->qual != aclent->a_id)
157			return (0);
158		break;
159	case DEF_CLASS_OBJ:
160	case CLASS_OBJ:
161		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
162		break;
163	case DEF_OTHER_OBJ:
164	case OTHER_OBJ:
165		if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
166		break;
167	}
168	return (1);
169}
170
171#else	/* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */
172static int
173acl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
174{
175	gid_t g, *gp;
176	uid_t u, *up;
177	acl_tag_t tag_type;
178
179	if (myacl->permset != acl_entry_get_perm(aclent))
180		return (0);
181
182	acl_get_tag_type(aclent, &tag_type);
183	switch (tag_type) {
184	case ACL_USER_OBJ:
185		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
186		break;
187	case ACL_USER:
188		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
189			return (0);
190		up = acl_get_qualifier(aclent);
191		u = *up;
192		acl_free(up);
193		if ((uid_t)myacl->qual != u)
194			return (0);
195		break;
196	case ACL_GROUP_OBJ:
197		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
198		break;
199	case ACL_GROUP:
200		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
201			return (0);
202		gp = acl_get_qualifier(aclent);
203		g = *gp;
204		acl_free(gp);
205		if ((gid_t)myacl->qual != g)
206			return (0);
207		break;
208	case ACL_MASK:
209		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
210		break;
211	case ACL_OTHER:
212		if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
213		break;
214	}
215	return (1);
216}
217#endif
218
219static void
220compare_acls(
221#if ARCHIVE_ACL_SUNOS
222    void *aclp, int aclcnt,
223#else
224    acl_t acl,
225#endif
226    struct archive_test_acl_t *myacls, int n)
227{
228	int *marker;
229	int matched;
230	int i;
231#if ARCHIVE_ACL_SUNOS
232	int e;
233	aclent_t *acl_entry;
234#else
235	int entry_id = ACL_FIRST_ENTRY;
236	acl_entry_t acl_entry;
237#endif
238
239	/* Count ACL entries in myacls array and allocate an indirect array. */
240	marker = malloc(sizeof(marker[0]) * n);
241	if (marker == NULL)
242		return;
243	for (i = 0; i < n; i++)
244		marker[i] = i;
245
246	/*
247	 * Iterate over acls in system acl object, try to match each
248	 * one with an item in the myacls array.
249	 */
250#if ARCHIVE_ACL_SUNOS
251	for(e = 0; e < aclcnt; e++) {
252		acl_entry = &((aclent_t *)aclp)[e];
253#else
254	while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
255		/* After the first time... */
256		entry_id = ACL_NEXT_ENTRY;
257#endif
258
259		/* Search for a matching entry (tag and qualifier) */
260		for (i = 0, matched = 0; i < n && !matched; i++) {
261			if (acl_match(acl_entry, &myacls[marker[i]])) {
262				/* We found a match; remove it. */
263				marker[i] = marker[n - 1];
264				n--;
265				matched = 1;
266			}
267		}
268
269		/* TODO: Print out more details in this case. */
270		failure("ACL entry on file that shouldn't be there");
271		assert(matched == 1);
272	}
273
274	/* Dump entries in the myacls array that weren't in the system acl. */
275	for (i = 0; i < n; ++i) {
276		failure(" ACL entry missing from file: "
277		    "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
278		    myacls[marker[i]].type, myacls[marker[i]].permset,
279		    myacls[marker[i]].tag, myacls[marker[i]].qual,
280		    myacls[marker[i]].name);
281		assert(0); /* Record this as a failure. */
282	}
283	free(marker);
284}
285#endif
286
287/*
288 * Verify ACL restore-to-disk.  This test is Platform-specific.
289 */
290
291DEFINE_TEST(test_acl_platform_posix1e_restore)
292{
293#if !ARCHIVE_ACL_POSIX1E
294	skipping("POSIX.1e ACLs are not supported on this platform");
295#else	/* ARCHIVE_ACL_POSIX1E */
296	struct stat st;
297	struct archive *a;
298	struct archive_entry *ae;
299#if ARCHIVE_ACL_SUNOS
300	void *aclp;
301	int aclcnt;
302#else
303	acl_t acl;
304#endif
305
306	assertMakeFile("pretest", 0644, "a");
307
308	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) {
309		skipping("POSIX.1e ACLs are not writable on this filesystem");
310		return;
311	}
312
313	/* Create a write-to-disk object. */
314	assert(NULL != (a = archive_write_disk_new()));
315	archive_write_disk_set_options(a,
316	    ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
317
318	/* Populate an archive entry with some metadata, including ACL info */
319	ae = archive_entry_new();
320	assert(ae != NULL);
321	archive_entry_set_pathname(ae, "test0");
322	archive_entry_set_mtime(ae, 123456, 7890);
323	archive_entry_set_size(ae, 0);
324	assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
325	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
326	archive_entry_free(ae);
327
328	/* Close the archive. */
329	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
330	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
331
332	/* Verify the data on disk. */
333	assertEqualInt(0, stat("test0", &st));
334	assertEqualInt(st.st_mtime, 123456);
335#if ARCHIVE_ACL_SUNOS
336	aclp = sunacl_get(GETACL, &aclcnt, 0, "test0");
337	failure("acl(): errno = %d (%s)", errno, strerror(errno));
338	assert(aclp != NULL);
339#else
340	acl = acl_get_file("test0", ACL_TYPE_ACCESS);
341	failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
342	assert(acl != (acl_t)NULL);
343#endif
344#if ARCHIVE_ACL_SUNOS
345	compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0]));
346	free(aclp);
347	aclp = NULL;
348#else
349	compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
350	acl_free(acl);
351#endif
352
353#endif	/* ARCHIVE_ACL_POSIX1E */
354}
355
356/*
357 * Verify ACL read-from-disk.  This test is Platform-specific.
358 */
359DEFINE_TEST(test_acl_platform_posix1e_read)
360{
361#if !ARCHIVE_ACL_POSIX1E
362	skipping("POSIX.1e ACLs are not supported on this platform");
363#else /* ARCHIVE_ACL_POSIX1E */
364	struct archive *a;
365	struct archive_entry *ae;
366	int n, fd, flags, dflags;
367	char *func, *acl_text;
368	const char *acl1_text, *acl2_text, *acl3_text;
369#if ARCHIVE_ACL_SUNOS
370	void *aclp;
371	int aclcnt;
372#else
373	acl_t acl1, acl2, acl3;
374#endif
375
376	/*
377	 * Manually construct a directory and two files with
378	 * different ACLs.  This also serves to verify that ACLs
379	 * are supported on the local filesystem.
380	 */
381
382	/* Create a test file f1 with acl1 */
383#if ARCHIVE_ACL_SUNOS
384	acl1_text = "user::rwx,"
385	    "group::rwx,"
386	    "other:rwx,"
387	    "user:1:rw-,"
388	    "group:15:r-x,"
389	    "mask:rwx";
390	aclent_t aclp1[] = {
391	    { USER_OBJ, -1, 4 | 2 | 1 },
392	    { USER, 1, 4 | 2 },
393	    { GROUP_OBJ, -1, 4 | 2 | 1 },
394	    { GROUP, 15, 4 | 1 },
395	    { CLASS_OBJ, -1, 4 | 2 | 1 },
396	    { OTHER_OBJ, -1, 4 | 2 | 1 }
397	};
398#else
399	acl1_text = "user::rwx\n"
400	    "group::rwx\n"
401	    "other::rwx\n"
402	    "user:1:rw-\n"
403	    "group:15:r-x\n"
404	    "mask::rwx";
405	acl1 = acl_from_text(acl1_text);
406	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
407	assert((void *)acl1 != NULL);
408#endif
409	fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
410	failure("Could not create test file?!");
411	if (!assert(fd >= 0)) {
412#if !ARCHIVE_ACL_SUNOS
413		acl_free(acl1);
414#endif
415		return;
416	}
417#if ARCHIVE_ACL_SUNOS
418	/* Check if Solaris filesystem supports POSIX.1e ACLs */
419	aclp = sunacl_get(GETACL, &aclcnt, fd, NULL);
420	if (aclp == 0)
421		close(fd);
422	if (errno == ENOSYS || errno == ENOTSUP) {
423		skipping("POSIX.1e ACLs are not supported on this filesystem");
424		return;
425	}
426	failure("facl(): errno = %d (%s)", errno, strerror(errno));
427	assert(aclp != NULL);
428
429	func = "facl()";
430	n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), aclp1);
431#else
432	func = "acl_set_fd()";
433	n = acl_set_fd(fd, acl1);
434#endif
435#if !ARCHIVE_ACL_SUNOS
436	acl_free(acl1);
437#endif
438
439	if (n != 0) {
440#if ARCHIVE_ACL_SUNOS
441		if (errno == ENOSYS || errno == ENOTSUP)
442#else
443		if (errno == EOPNOTSUPP || errno == EINVAL)
444#endif
445		{
446			close(fd);
447			skipping("POSIX.1e ACLs are not supported on this filesystem");
448			return;
449		}
450	}
451	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
452	assertEqualInt(0, n);
453
454	close(fd);
455
456	assertMakeDir("d", 0700);
457
458	/*
459	 * Create file d/f1 with acl2
460	 *
461	 * This differs from acl1 in the u:1: and g:15: permissions.
462	 *
463	 * This file deliberately has the same name but a different ACL.
464	 * Github Issue #777 explains how libarchive's directory traversal
465	 * did not always correctly enter directories before attempting
466	 * to read ACLs, resulting in reading the ACL from a like-named
467	 * file in the wrong directory.
468	 */
469#if ARCHIVE_ACL_SUNOS
470	acl2_text = "user::rwx,"
471	    "group::rwx,"
472	    "other:---,"
473	    "user:1:r--,"
474	    "group:15:r--,"
475	    "mask:rwx";
476	aclent_t aclp2[] = {
477	    { USER_OBJ, -1, 4 | 2 | 1 },
478	    { USER, 1, 4 },
479	    { GROUP_OBJ, -1, 4 | 2 | 1},
480	    { GROUP, 15, 4 },
481	    { CLASS_OBJ, -1, 4 | 2 | 1},
482	    { OTHER_OBJ, -1, 0 }
483	};
484#else
485	acl2_text = "user::rwx\n"
486	    "group::rwx\n"
487	    "other::---\n"
488	    "user:1:r--\n"
489	    "group:15:r--\n"
490	    "mask::rwx";
491	acl2 = acl_from_text(acl2_text);
492	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
493	assert((void *)acl2 != NULL);
494#endif
495	fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
496	failure("Could not create test file?!");
497	if (!assert(fd >= 0)) {
498#if !ARCHIVE_ACL_SUNOS
499		acl_free(acl2);
500#endif
501		return;
502	}
503#if ARCHIVE_ACL_SUNOS
504	func = "facl()";
505	n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2);
506#else
507	func = "acl_set_fd()";
508	n = acl_set_fd(fd, acl2);
509	acl_free(acl2);
510#endif
511	if (n != 0)
512		close(fd);
513	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
514	assertEqualInt(0, n);
515	close(fd);
516
517	/* Create nested directory d2 with default ACLs */
518	assertMakeDir("d/d2", 0755);
519
520#if ARCHIVE_ACL_SUNOS
521	acl3_text = "user::rwx,"
522	    "group::r-x,"
523	    "other:r-x,"
524	    "user:2:r--,"
525	    "group:16:-w-,"
526	    "mask:rwx,"
527	    "default:user::rwx,"
528	    "default:user:1:r--,"
529	    "default:group::r-x,"
530	    "default:group:15:r--,"
531	    "default:mask:rwx,"
532	    "default:other:r-x";
533	aclent_t aclp3[] = {
534	    { USER_OBJ, -1, 4 | 2 | 1 },
535	    { USER, 2, 4 },
536	    { GROUP_OBJ, -1, 4 | 1 },
537	    { GROUP, 16, 2 },
538	    { CLASS_OBJ, -1, 4 | 2 | 1 },
539	    { OTHER_OBJ, -1, 4 | 1 },
540	    { USER_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1 },
541	    { USER | ACL_DEFAULT, 1, 4 },
542	    { GROUP_OBJ | ACL_DEFAULT, -1, 4 | 1 },
543	    { GROUP | ACL_DEFAULT, 15, 4 },
544	    { CLASS_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1},
545	    { OTHER_OBJ | ACL_DEFAULT, -1, 4 | 1 }
546	};
547#else
548	acl3_text = "user::rwx\n"
549	    "user:1:r--\n"
550	    "group::r-x\n"
551	    "group:15:r--\n"
552	    "mask::rwx\n"
553	    "other::r-x";
554	acl3 = acl_from_text(acl3_text);
555	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
556	assert((void *)acl3 != NULL);
557#endif
558
559#if ARCHIVE_ACL_SUNOS
560	func = "acl()";
561	n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3);
562#else
563	func = "acl_set_file()";
564	n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3);
565	acl_free(acl3);
566#endif
567	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
568	assertEqualInt(0, n);
569
570	/* Create a read-from-disk object. */
571	assert(NULL != (a = archive_read_disk_new()));
572	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
573	assert(NULL != (ae = archive_entry_new()));
574
575#if ARCHIVE_ACL_SUNOS
576	flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
577	    | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
578	    | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
579	dflags = flags;
580#else
581	flags = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
582	dflags = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
583#endif
584
585	/* Walk the dir until we see both of the files */
586	while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
587		archive_read_disk_descend(a);
588		if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
589			acl_text = archive_entry_acl_to_text(ae, NULL, flags);
590			assertEqualString(acl_text, acl1_text);
591			free(acl_text);
592		} else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) {
593			acl_text = archive_entry_acl_to_text(ae, NULL, flags);
594			assertEqualString(acl_text, acl2_text);
595			free(acl_text);
596		} else if (strcmp(archive_entry_pathname(ae), "./d/d2") == 0) {
597			acl_text = archive_entry_acl_to_text(ae, NULL, dflags);
598			assertEqualString(acl_text, acl3_text);
599			free(acl_text);
600		}
601	}
602
603	archive_entry_free(ae);
604	assertEqualInt(ARCHIVE_OK, archive_free(a));
605#endif /* ARCHIVE_ACL_POSIX1E */
606}
607