1248590Smm/*-
2248590Smm * Copyright (c) 2003-2008 Tim Kientzle
3313071Smm * Copyright (c) 2017 Martin Matuska
4248590Smm * All rights reserved.
5248590Smm *
6248590Smm * Redistribution and use in source and binary forms, with or without
7248590Smm * modification, are permitted provided that the following conditions
8248590Smm * are met:
9248590Smm * 1. Redistributions of source code must retain the above copyright
10248590Smm *    notice, this list of conditions and the following disclaimer.
11248590Smm * 2. Redistributions in binary form must reproduce the above copyright
12248590Smm *    notice, this list of conditions and the following disclaimer in the
13248590Smm *    documentation and/or other materials provided with the distribution.
14248590Smm *
15248590Smm * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16248590Smm * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17248590Smm * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18248590Smm * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19248590Smm * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20248590Smm * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21248590Smm * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22248590Smm * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23248590Smm * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24248590Smm * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25248590Smm */
26248590Smm#include "test.h"
27248590Smm__FBSDID("$FreeBSD: head/lib/libarchive/test/test_acl_freebsd.c 189427 2009-03-06 04:21:23Z kientzle $");
28248590Smm
29316338Smm#if ARCHIVE_ACL_POSIX1E
30248590Smm#include <sys/acl.h>
31313071Smm#if HAVE_ACL_GET_PERM
32313071Smm#include <acl/libacl.h>
33313071Smm#define ACL_GET_PERM acl_get_perm
34313071Smm#elif HAVE_ACL_GET_PERM_NP
35313071Smm#define ACL_GET_PERM acl_get_perm_np
36313071Smm#endif
37248590Smm
38310796Smmstatic struct archive_test_acl_t acls2[] = {
39248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_EXECUTE | ARCHIVE_ENTRY_ACL_READ,
40248590Smm	  ARCHIVE_ENTRY_ACL_USER_OBJ, -1, "" },
41248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
42248590Smm	  ARCHIVE_ENTRY_ACL_USER, 77, "user77" },
43248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0,
44248590Smm	  ARCHIVE_ENTRY_ACL_USER, 78, "user78" },
45248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, ARCHIVE_ENTRY_ACL_READ,
46248590Smm	  ARCHIVE_ENTRY_ACL_GROUP_OBJ, -1, "" },
47248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS, 0007,
48248590Smm	  ARCHIVE_ENTRY_ACL_GROUP, 78, "group78" },
49248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
50248590Smm	  ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_EXECUTE,
51248590Smm	  ARCHIVE_ENTRY_ACL_OTHER, -1, "" },
52248590Smm	{ ARCHIVE_ENTRY_ACL_TYPE_ACCESS,
53248590Smm	  ARCHIVE_ENTRY_ACL_WRITE | ARCHIVE_ENTRY_ACL_READ | ARCHIVE_ENTRY_ACL_EXECUTE,
54248590Smm	  ARCHIVE_ENTRY_ACL_MASK, -1, "" },
55248590Smm};
56248590Smm
57248590Smmstatic int
58316338Smm#if ARCHIVE_ACL_SUNOS
59313071Smmacl_entry_get_perm(aclent_t *aclent)
60313071Smm#else
61313071Smmacl_entry_get_perm(acl_entry_t aclent)
62313071Smm#endif
63313071Smm{
64305420Smm	int permset = 0;
65316338Smm#if ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL
66248590Smm	acl_permset_t opaque_ps;
67313071Smm#endif
68248590Smm
69316338Smm#if ARCHIVE_ACL_SUNOS
70313071Smm	if (aclent->a_perm & 1)
71313071Smm		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
72313071Smm	if (aclent->a_perm & 2)
73313071Smm		permset |= ARCHIVE_ENTRY_ACL_WRITE;
74313071Smm	if (aclent->a_perm & 4)
75313071Smm		permset |= ARCHIVE_ENTRY_ACL_READ;
76313071Smm#else
77248590Smm	/* translate the silly opaque permset to a bitmap */
78248590Smm	acl_get_permset(aclent, &opaque_ps);
79313071Smm	if (ACL_GET_PERM(opaque_ps, ACL_EXECUTE))
80248590Smm		permset |= ARCHIVE_ENTRY_ACL_EXECUTE;
81313071Smm	if (ACL_GET_PERM(opaque_ps, ACL_WRITE))
82248590Smm		permset |= ARCHIVE_ENTRY_ACL_WRITE;
83313071Smm	if (ACL_GET_PERM(opaque_ps, ACL_READ))
84248590Smm		permset |= ARCHIVE_ENTRY_ACL_READ;
85313071Smm#endif
86305420Smm	return permset;
87305420Smm}
88248590Smm
89305420Smm#if 0
90305420Smmstatic int
91305420Smmacl_get_specific_entry(acl_t acl, acl_tag_t requested_tag_type, int requested_tag) {
92305420Smm	int entry_id = ACL_FIRST_ENTRY;
93305420Smm	acl_entry_t acl_entry;
94305420Smm	acl_tag_t acl_tag_type;
95305420Smm
96305420Smm	while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
97305420Smm		/* After the first time... */
98305420Smm		entry_id = ACL_NEXT_ENTRY;
99305420Smm
100305420Smm		/* If this matches, return perm mask */
101305420Smm		acl_get_tag_type(acl_entry, &acl_tag_type);
102305420Smm		if (acl_tag_type == requested_tag_type) {
103305420Smm			switch (acl_tag_type) {
104305420Smm			case ACL_USER_OBJ:
105305420Smm				if ((uid_t)requested_tag == *(uid_t *)(acl_get_qualifier(acl_entry))) {
106305420Smm					return acl_entry_get_perm(acl_entry);
107305420Smm				}
108305420Smm				break;
109305420Smm			case ACL_GROUP_OBJ:
110305420Smm				if ((gid_t)requested_tag == *(gid_t *)(acl_get_qualifier(acl_entry))) {
111305420Smm					return acl_entry_get_perm(acl_entry);
112305420Smm				}
113305420Smm				break;
114305420Smm			case ACL_USER:
115305420Smm			case ACL_GROUP:
116305420Smm			case ACL_OTHER:
117305420Smm				return acl_entry_get_perm(acl_entry);
118305420Smm			default:
119305420Smm				failure("Unexpected ACL tag type");
120305420Smm				assert(0);
121305420Smm			}
122305420Smm		}
123305420Smm
124305420Smm
125305420Smm	}
126305420Smm	return -1;
127305420Smm}
128305420Smm#endif
129305420Smm
130316338Smm#if ARCHIVE_ACL_SUNOS
131305420Smmstatic int
132313071Smmacl_match(aclent_t *aclent, struct archive_test_acl_t *myacl)
133316338Smm{
134316338Smm
135316338Smm	if (myacl->permset != acl_entry_get_perm(aclent))
136316338Smm		return (0);
137316338Smm
138316338Smm	switch (aclent->a_type) {
139316338Smm	case DEF_USER_OBJ:
140316338Smm	case USER_OBJ:
141316338Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
142316338Smm		break;
143316338Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
144316338Smm			return (0);
145316338Smm		if ((uid_t)myacl->qual != aclent->a_id)
146316338Smm			return (0);
147316338Smm		break;
148316338Smm	case DEF_GROUP_OBJ:
149316338Smm	case GROUP_OBJ:
150316338Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
151316338Smm		break;
152316338Smm	case DEF_GROUP:
153316338Smm	case GROUP:
154316338Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
155316338Smm			return (0);
156316338Smm		if ((gid_t)myacl->qual != aclent->a_id)
157316338Smm			return (0);
158316338Smm		break;
159316338Smm	case DEF_CLASS_OBJ:
160316338Smm	case CLASS_OBJ:
161316338Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
162316338Smm		break;
163316338Smm	case DEF_OTHER_OBJ:
164316338Smm	case OTHER_OBJ:
165316338Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
166316338Smm		break;
167316338Smm	}
168316338Smm	return (1);
169316338Smm}
170316338Smm
171316338Smm#else	/* ARCHIVE_ACL_FREEBSD || ARCHIVE_ACL_LIBACL */
172316338Smmstatic int
173310796Smmacl_match(acl_entry_t aclent, struct archive_test_acl_t *myacl)
174305420Smm{
175305420Smm	gid_t g, *gp;
176305420Smm	uid_t u, *up;
177305420Smm	acl_tag_t tag_type;
178305420Smm
179305420Smm	if (myacl->permset != acl_entry_get_perm(aclent))
180248590Smm		return (0);
181248590Smm
182305420Smm	acl_get_tag_type(aclent, &tag_type);
183316338Smm	switch (tag_type) {
184248590Smm	case ACL_USER_OBJ:
185248590Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER_OBJ) return (0);
186248590Smm		break;
187248590Smm	case ACL_USER:
188248590Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_USER)
189248590Smm			return (0);
190248590Smm		up = acl_get_qualifier(aclent);
191248590Smm		u = *up;
192248590Smm		acl_free(up);
193248590Smm		if ((uid_t)myacl->qual != u)
194248590Smm			return (0);
195248590Smm		break;
196248590Smm	case ACL_GROUP_OBJ:
197248590Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP_OBJ) return (0);
198248590Smm		break;
199248590Smm	case ACL_GROUP:
200248590Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_GROUP)
201248590Smm			return (0);
202248590Smm		gp = acl_get_qualifier(aclent);
203248590Smm		g = *gp;
204248590Smm		acl_free(gp);
205248590Smm		if ((gid_t)myacl->qual != g)
206248590Smm			return (0);
207248590Smm		break;
208248590Smm	case ACL_MASK:
209248590Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_MASK) return (0);
210248590Smm		break;
211248590Smm	case ACL_OTHER:
212248590Smm		if (myacl->tag != ARCHIVE_ENTRY_ACL_OTHER) return (0);
213248590Smm		break;
214248590Smm	}
215248590Smm	return (1);
216248590Smm}
217316338Smm#endif
218248590Smm
219248590Smmstatic void
220316338Smmcompare_acls(
221316338Smm#if ARCHIVE_ACL_SUNOS
222316338Smm    void *aclp, int aclcnt,
223313071Smm#else
224316338Smm    acl_t acl,
225313071Smm#endif
226316338Smm    struct archive_test_acl_t *myacls, int n)
227248590Smm{
228248590Smm	int *marker;
229248590Smm	int matched;
230310796Smm	int i;
231316338Smm#if ARCHIVE_ACL_SUNOS
232313071Smm	int e;
233313071Smm	aclent_t *acl_entry;
234313071Smm#else
235313071Smm	int entry_id = ACL_FIRST_ENTRY;
236248590Smm	acl_entry_t acl_entry;
237313071Smm#endif
238248590Smm
239248590Smm	/* Count ACL entries in myacls array and allocate an indirect array. */
240310796Smm	marker = malloc(sizeof(marker[0]) * n);
241310796Smm	if (marker == NULL)
242310796Smm		return;
243310796Smm	for (i = 0; i < n; i++)
244310796Smm		marker[i] = i;
245248590Smm
246248590Smm	/*
247248590Smm	 * Iterate over acls in system acl object, try to match each
248248590Smm	 * one with an item in the myacls array.
249248590Smm	 */
250316338Smm#if ARCHIVE_ACL_SUNOS
251315433Smm	for(e = 0; e < aclcnt; e++) {
252315433Smm		acl_entry = &((aclent_t *)aclp)[e];
253313071Smm#else
254248590Smm	while (1 == acl_get_entry(acl, entry_id, &acl_entry)) {
255248590Smm		/* After the first time... */
256248590Smm		entry_id = ACL_NEXT_ENTRY;
257313071Smm#endif
258248590Smm
259248590Smm		/* Search for a matching entry (tag and qualifier) */
260248590Smm		for (i = 0, matched = 0; i < n && !matched; i++) {
261248590Smm			if (acl_match(acl_entry, &myacls[marker[i]])) {
262248590Smm				/* We found a match; remove it. */
263248590Smm				marker[i] = marker[n - 1];
264248590Smm				n--;
265248590Smm				matched = 1;
266248590Smm			}
267248590Smm		}
268248590Smm
269248590Smm		/* TODO: Print out more details in this case. */
270248590Smm		failure("ACL entry on file that shouldn't be there");
271248590Smm		assert(matched == 1);
272248590Smm	}
273248590Smm
274248590Smm	/* Dump entries in the myacls array that weren't in the system acl. */
275248590Smm	for (i = 0; i < n; ++i) {
276248590Smm		failure(" ACL entry missing from file: "
277310796Smm		    "type=%#010x,permset=%#010x,tag=%d,qual=%d,name=``%s''\n",
278248590Smm		    myacls[marker[i]].type, myacls[marker[i]].permset,
279248590Smm		    myacls[marker[i]].tag, myacls[marker[i]].qual,
280248590Smm		    myacls[marker[i]].name);
281248590Smm		assert(0); /* Record this as a failure. */
282248590Smm	}
283248590Smm	free(marker);
284248590Smm}
285248590Smm#endif
286248590Smm
287248590Smm/*
288313071Smm * Verify ACL restore-to-disk.  This test is Platform-specific.
289248590Smm */
290248590Smm
291313071SmmDEFINE_TEST(test_acl_platform_posix1e_restore)
292248590Smm{
293316338Smm#if !ARCHIVE_ACL_POSIX1E
294313071Smm	skipping("POSIX.1e ACLs are not supported on this platform");
295316338Smm#else	/* ARCHIVE_ACL_POSIX1E */
296248590Smm	struct stat st;
297248590Smm	struct archive *a;
298248590Smm	struct archive_entry *ae;
299316338Smm#if ARCHIVE_ACL_SUNOS
300315433Smm	void *aclp;
301315433Smm	int aclcnt;
302313071Smm#else
303248590Smm	acl_t acl;
304313071Smm#endif
305248590Smm
306315433Smm	assertMakeFile("pretest", 0644, "a");
307313071Smm
308315433Smm	if (setTestAcl("pretest") != ARCHIVE_TEST_ACL_TYPE_POSIX1E) {
309315433Smm		skipping("POSIX.1e ACLs are not writable on this filesystem");
310248590Smm		return;
311248590Smm	}
312248590Smm
313248590Smm	/* Create a write-to-disk object. */
314248590Smm	assert(NULL != (a = archive_write_disk_new()));
315248590Smm	archive_write_disk_set_options(a,
316248590Smm	    ARCHIVE_EXTRACT_TIME | ARCHIVE_EXTRACT_PERM | ARCHIVE_EXTRACT_ACL);
317248590Smm
318248590Smm	/* Populate an archive entry with some metadata, including ACL info */
319248590Smm	ae = archive_entry_new();
320248590Smm	assert(ae != NULL);
321248590Smm	archive_entry_set_pathname(ae, "test0");
322248590Smm	archive_entry_set_mtime(ae, 123456, 7890);
323248590Smm	archive_entry_set_size(ae, 0);
324315433Smm	assertEntrySetAcls(ae, acls2, sizeof(acls2)/sizeof(acls2[0]));
325248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
326248590Smm	archive_entry_free(ae);
327248590Smm
328248590Smm	/* Close the archive. */
329248590Smm	assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
330248590Smm	assertEqualInt(ARCHIVE_OK, archive_write_free(a));
331248590Smm
332248590Smm	/* Verify the data on disk. */
333248590Smm	assertEqualInt(0, stat("test0", &st));
334248590Smm	assertEqualInt(st.st_mtime, 123456);
335316338Smm#if ARCHIVE_ACL_SUNOS
336315433Smm	aclp = sunacl_get(GETACL, &aclcnt, 0, "test0");
337315433Smm	failure("acl(): errno = %d (%s)", errno, strerror(errno));
338315433Smm	assert(aclp != NULL);
339313071Smm#else
340248590Smm	acl = acl_get_file("test0", ACL_TYPE_ACCESS);
341313071Smm	failure("acl_get_file(): errno = %d (%s)", errno, strerror(errno));
342248590Smm	assert(acl != (acl_t)NULL);
343313071Smm#endif
344316338Smm#if ARCHIVE_ACL_SUNOS
345315433Smm	compare_acls(aclp, aclcnt, acls2, sizeof(acls2)/sizeof(acls2[0]));
346315433Smm	free(aclp);
347315433Smm	aclp = NULL;
348315433Smm#else
349310796Smm	compare_acls(acl, acls2, sizeof(acls2)/sizeof(acls2[0]));
350248590Smm	acl_free(acl);
351315433Smm#endif
352315433Smm
353316338Smm#endif	/* ARCHIVE_ACL_POSIX1E */
354248590Smm}
355305420Smm
356305420Smm/*
357313071Smm * Verify ACL read-from-disk.  This test is Platform-specific.
358305420Smm */
359313071SmmDEFINE_TEST(test_acl_platform_posix1e_read)
360305420Smm{
361316338Smm#if !ARCHIVE_ACL_POSIX1E
362313071Smm	skipping("POSIX.1e ACLs are not supported on this platform");
363316338Smm#else /* ARCHIVE_ACL_POSIX1E */
364305420Smm	struct archive *a;
365305420Smm	struct archive_entry *ae;
366313071Smm	int n, fd, flags, dflags;
367362134Smm	char *acl_text;
368362134Smm	const char *func, *acl1_text, *acl2_text, *acl3_text;
369316338Smm#if ARCHIVE_ACL_SUNOS
370315433Smm	void *aclp;
371315433Smm	int aclcnt;
372313071Smm#else
373313071Smm	acl_t acl1, acl2, acl3;
374313071Smm#endif
375305420Smm
376305420Smm	/*
377305420Smm	 * Manually construct a directory and two files with
378305420Smm	 * different ACLs.  This also serves to verify that ACLs
379305420Smm	 * are supported on the local filesystem.
380305420Smm	 */
381305420Smm
382305420Smm	/* Create a test file f1 with acl1 */
383316338Smm#if ARCHIVE_ACL_SUNOS
384313071Smm	acl1_text = "user::rwx,"
385313071Smm	    "group::rwx,"
386313071Smm	    "other:rwx,"
387313071Smm	    "user:1:rw-,"
388313071Smm	    "group:15:r-x,"
389313071Smm	    "mask:rwx";
390315433Smm	aclent_t aclp1[] = {
391315433Smm	    { USER_OBJ, -1, 4 | 2 | 1 },
392315433Smm	    { USER, 1, 4 | 2 },
393315433Smm	    { GROUP_OBJ, -1, 4 | 2 | 1 },
394315433Smm	    { GROUP, 15, 4 | 1 },
395315433Smm	    { CLASS_OBJ, -1, 4 | 2 | 1 },
396315433Smm	    { OTHER_OBJ, -1, 4 | 2 | 1 }
397315433Smm	};
398313071Smm#else
399310796Smm	acl1_text = "user::rwx\n"
400310796Smm	    "group::rwx\n"
401310796Smm	    "other::rwx\n"
402310796Smm	    "user:1:rw-\n"
403310796Smm	    "group:15:r-x\n"
404310796Smm	    "mask::rwx";
405305420Smm	acl1 = acl_from_text(acl1_text);
406313071Smm	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
407305420Smm	assert((void *)acl1 != NULL);
408313071Smm#endif
409305420Smm	fd = open("f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
410305420Smm	failure("Could not create test file?!");
411305420Smm	if (!assert(fd >= 0)) {
412316338Smm#if !ARCHIVE_ACL_SUNOS
413305420Smm		acl_free(acl1);
414315433Smm#endif
415305420Smm		return;
416305420Smm	}
417316338Smm#if ARCHIVE_ACL_SUNOS
418313927Smm	/* Check if Solaris filesystem supports POSIX.1e ACLs */
419315433Smm	aclp = sunacl_get(GETACL, &aclcnt, fd, NULL);
420315433Smm	if (aclp == 0)
421305420Smm		close(fd);
422315433Smm	if (errno == ENOSYS || errno == ENOTSUP) {
423313071Smm		skipping("POSIX.1e ACLs are not supported on this filesystem");
424305420Smm		return;
425305420Smm	}
426315433Smm	failure("facl(): errno = %d (%s)", errno, strerror(errno));
427315433Smm	assert(aclp != NULL);
428313071Smm
429315433Smm	func = "facl()";
430315433Smm	n = facl(fd, SETACL, (int)(sizeof(aclp1)/sizeof(aclp1[0])), aclp1);
431313071Smm#else
432313071Smm	func = "acl_set_fd()";
433313071Smm	n = acl_set_fd(fd, acl1);
434313071Smm#endif
435316338Smm#if !ARCHIVE_ACL_SUNOS
436313071Smm	acl_free(acl1);
437315433Smm#endif
438313071Smm
439313071Smm	if (n != 0) {
440316338Smm#if ARCHIVE_ACL_SUNOS
441315433Smm		if (errno == ENOSYS || errno == ENOTSUP)
442313071Smm#else
443313071Smm		if (errno == EOPNOTSUPP || errno == EINVAL)
444313071Smm#endif
445313071Smm		{
446313071Smm			close(fd);
447313071Smm			skipping("POSIX.1e ACLs are not supported on this filesystem");
448313071Smm			return;
449313071Smm		}
450313071Smm	}
451313071Smm	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
452305420Smm	assertEqualInt(0, n);
453313071Smm
454305420Smm	close(fd);
455305420Smm
456305420Smm	assertMakeDir("d", 0700);
457305420Smm
458305420Smm	/*
459305420Smm	 * Create file d/f1 with acl2
460305420Smm	 *
461305420Smm	 * This differs from acl1 in the u:1: and g:15: permissions.
462305420Smm	 *
463305420Smm	 * This file deliberately has the same name but a different ACL.
464305420Smm	 * Github Issue #777 explains how libarchive's directory traversal
465305420Smm	 * did not always correctly enter directories before attempting
466305420Smm	 * to read ACLs, resulting in reading the ACL from a like-named
467305420Smm	 * file in the wrong directory.
468305420Smm	 */
469316338Smm#if ARCHIVE_ACL_SUNOS
470313071Smm	acl2_text = "user::rwx,"
471313071Smm	    "group::rwx,"
472313071Smm	    "other:---,"
473313071Smm	    "user:1:r--,"
474313071Smm	    "group:15:r--,"
475313071Smm	    "mask:rwx";
476315433Smm	aclent_t aclp2[] = {
477315433Smm	    { USER_OBJ, -1, 4 | 2 | 1 },
478315433Smm	    { USER, 1, 4 },
479315433Smm	    { GROUP_OBJ, -1, 4 | 2 | 1},
480315433Smm	    { GROUP, 15, 4 },
481315433Smm	    { CLASS_OBJ, -1, 4 | 2 | 1},
482315433Smm	    { OTHER_OBJ, -1, 0 }
483315433Smm	};
484313071Smm#else
485310796Smm	acl2_text = "user::rwx\n"
486310796Smm	    "group::rwx\n"
487310796Smm	    "other::---\n"
488310796Smm	    "user:1:r--\n"
489310796Smm	    "group:15:r--\n"
490310796Smm	    "mask::rwx";
491305420Smm	acl2 = acl_from_text(acl2_text);
492313071Smm	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
493305420Smm	assert((void *)acl2 != NULL);
494313071Smm#endif
495305420Smm	fd = open("d/f1", O_WRONLY | O_CREAT | O_EXCL, 0777);
496305420Smm	failure("Could not create test file?!");
497305420Smm	if (!assert(fd >= 0)) {
498316338Smm#if !ARCHIVE_ACL_SUNOS
499305420Smm		acl_free(acl2);
500315433Smm#endif
501305420Smm		return;
502305420Smm	}
503316338Smm#if ARCHIVE_ACL_SUNOS
504315433Smm	func = "facl()";
505315433Smm	n = facl(fd, SETACL, (int)(sizeof(aclp2) / sizeof(aclp2[0])), aclp2);
506313071Smm#else
507313071Smm	func = "acl_set_fd()";
508305420Smm	n = acl_set_fd(fd, acl2);
509315433Smm	acl_free(acl2);
510313071Smm#endif
511313071Smm	if (n != 0)
512305420Smm		close(fd);
513313071Smm	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
514305420Smm	assertEqualInt(0, n);
515305420Smm	close(fd);
516305420Smm
517315433Smm	/* Create nested directory d2 with default ACLs */
518315433Smm	assertMakeDir("d/d2", 0755);
519313071Smm
520316338Smm#if ARCHIVE_ACL_SUNOS
521313071Smm	acl3_text = "user::rwx,"
522313071Smm	    "group::r-x,"
523313071Smm	    "other:r-x,"
524313071Smm	    "user:2:r--,"
525313071Smm	    "group:16:-w-,"
526313071Smm	    "mask:rwx,"
527313071Smm	    "default:user::rwx,"
528313071Smm	    "default:user:1:r--,"
529313071Smm	    "default:group::r-x,"
530313071Smm	    "default:group:15:r--,"
531313071Smm	    "default:mask:rwx,"
532313071Smm	    "default:other:r-x";
533315433Smm	aclent_t aclp3[] = {
534315433Smm	    { USER_OBJ, -1, 4 | 2 | 1 },
535315433Smm	    { USER, 2, 4 },
536315433Smm	    { GROUP_OBJ, -1, 4 | 1 },
537315433Smm	    { GROUP, 16, 2 },
538315433Smm	    { CLASS_OBJ, -1, 4 | 2 | 1 },
539315433Smm	    { OTHER_OBJ, -1, 4 | 1 },
540315433Smm	    { USER_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1 },
541315433Smm	    { USER | ACL_DEFAULT, 1, 4 },
542315433Smm	    { GROUP_OBJ | ACL_DEFAULT, -1, 4 | 1 },
543315433Smm	    { GROUP | ACL_DEFAULT, 15, 4 },
544315433Smm	    { CLASS_OBJ | ACL_DEFAULT, -1, 4 | 2 | 1},
545315433Smm	    { OTHER_OBJ | ACL_DEFAULT, -1, 4 | 1 }
546315433Smm	};
547313071Smm#else
548313071Smm	acl3_text = "user::rwx\n"
549313071Smm	    "user:1:r--\n"
550313071Smm	    "group::r-x\n"
551313071Smm	    "group:15:r--\n"
552313071Smm	    "mask::rwx\n"
553313071Smm	    "other::r-x";
554313071Smm	acl3 = acl_from_text(acl3_text);
555313071Smm	failure("acl_from_text(): errno = %d (%s)", errno, strerror(errno));
556313071Smm	assert((void *)acl3 != NULL);
557313071Smm#endif
558313071Smm
559316338Smm#if ARCHIVE_ACL_SUNOS
560315433Smm	func = "acl()";
561315433Smm	n = acl("d/d2", SETACL, (int)(sizeof(aclp3) / sizeof(aclp3[0])), aclp3);
562313071Smm#else
563313071Smm	func = "acl_set_file()";
564315433Smm	n = acl_set_file("d/d2", ACL_TYPE_DEFAULT, acl3);
565315433Smm	acl_free(acl3);
566313071Smm#endif
567313071Smm	failure("%s: errno = %d (%s)", func, errno, strerror(errno));
568313071Smm	assertEqualInt(0, n);
569313071Smm
570305420Smm	/* Create a read-from-disk object. */
571305420Smm	assert(NULL != (a = archive_read_disk_new()));
572305420Smm	assertEqualIntA(a, ARCHIVE_OK, archive_read_disk_open(a, "."));
573305420Smm	assert(NULL != (ae = archive_entry_new()));
574305420Smm
575316338Smm#if ARCHIVE_ACL_SUNOS
576313071Smm	flags = ARCHIVE_ENTRY_ACL_TYPE_POSIX1E
577313071Smm	    | ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA
578313071Smm	    | ARCHIVE_ENTRY_ACL_STYLE_SOLARIS;
579313071Smm	dflags = flags;
580313071Smm#else
581313071Smm	flags = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
582313071Smm	dflags = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
583313071Smm#endif
584313071Smm
585305420Smm	/* Walk the dir until we see both of the files */
586305420Smm	while (ARCHIVE_OK == archive_read_next_header2(a, ae)) {
587305420Smm		archive_read_disk_descend(a);
588305420Smm		if (strcmp(archive_entry_pathname(ae), "./f1") == 0) {
589313071Smm			acl_text = archive_entry_acl_to_text(ae, NULL, flags);
590313071Smm			assertEqualString(acl_text, acl1_text);
591313071Smm			free(acl_text);
592305420Smm		} else if (strcmp(archive_entry_pathname(ae), "./d/f1") == 0) {
593313071Smm			acl_text = archive_entry_acl_to_text(ae, NULL, flags);
594313071Smm			assertEqualString(acl_text, acl2_text);
595313071Smm			free(acl_text);
596315433Smm		} else if (strcmp(archive_entry_pathname(ae), "./d/d2") == 0) {
597313071Smm			acl_text = archive_entry_acl_to_text(ae, NULL, dflags);
598313071Smm			assertEqualString(acl_text, acl3_text);
599313071Smm			free(acl_text);
600305420Smm		}
601305420Smm	}
602305420Smm
603313071Smm	archive_entry_free(ae);
604313071Smm	assertEqualInt(ARCHIVE_OK, archive_free(a));
605316338Smm#endif /* ARCHIVE_ACL_POSIX1E */
606305420Smm}
607