1d05f0226Sjoerg /*-
2d05f0226Sjoerg  * Copyright (c) 2003-2009 Tim Kientzle
3d05f0226Sjoerg  * Copyright (c) 2010-2012 Michihiro NAKAJIMA
4d05f0226Sjoerg  * Copyright (c) 2017 Martin Matuska
5d05f0226Sjoerg  * All rights reserved.
6d05f0226Sjoerg  *
7d05f0226Sjoerg  * Redistribution and use in source and binary forms, with or without
8d05f0226Sjoerg  * modification, are permitted provided that the following conditions
9d05f0226Sjoerg  * are met:
10d05f0226Sjoerg  * 1. Redistributions of source code must retain the above copyright
11d05f0226Sjoerg  *    notice, this list of conditions and the following disclaimer.
12d05f0226Sjoerg  * 2. Redistributions in binary form must reproduce the above copyright
13d05f0226Sjoerg  *    notice, this list of conditions and the following disclaimer in the
14d05f0226Sjoerg  *    documentation and/or other materials provided with the distribution.
15d05f0226Sjoerg  *
16d05f0226Sjoerg  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17d05f0226Sjoerg  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18d05f0226Sjoerg  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19d05f0226Sjoerg  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20d05f0226Sjoerg  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21d05f0226Sjoerg  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22d05f0226Sjoerg  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23d05f0226Sjoerg  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24d05f0226Sjoerg  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25d05f0226Sjoerg  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26d05f0226Sjoerg  */
27d05f0226Sjoerg 
28d05f0226Sjoerg #include "archive_platform.h"
29d05f0226Sjoerg 
30d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD
31d05f0226Sjoerg 
32d05f0226Sjoerg #ifdef HAVE_ERRNO_H
33d05f0226Sjoerg #include <errno.h>
34d05f0226Sjoerg #endif
35d05f0226Sjoerg #ifdef HAVE_FCNTL_H
36d05f0226Sjoerg #include <fcntl.h>
37d05f0226Sjoerg #endif
38d05f0226Sjoerg #ifdef HAVE_SYS_TYPES_H
39d05f0226Sjoerg #include <sys/types.h>
40d05f0226Sjoerg #endif
41d05f0226Sjoerg #ifdef HAVE_SYS_ACL_H
42d05f0226Sjoerg #define _ACL_PRIVATE /* For debugging */
43d05f0226Sjoerg #include <sys/acl.h>
44d05f0226Sjoerg #endif
45d05f0226Sjoerg 
46d05f0226Sjoerg #include "archive_entry.h"
47d05f0226Sjoerg #include "archive_private.h"
48d05f0226Sjoerg #include "archive_read_disk_private.h"
49d05f0226Sjoerg #include "archive_write_disk_private.h"
50d05f0226Sjoerg 
51d05f0226Sjoerg typedef struct {
52d05f0226Sjoerg 	const int a_perm;	/* Libarchive permission or flag */
53d05f0226Sjoerg 	const int p_perm;	/* Platform permission or flag */
54d05f0226Sjoerg } acl_perm_map_t;
55d05f0226Sjoerg 
56d05f0226Sjoerg static const acl_perm_map_t acl_posix_perm_map[] = {
57d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
58d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
59d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_READ, ACL_READ},
60d05f0226Sjoerg };
61d05f0226Sjoerg 
62d05f0226Sjoerg static const int acl_posix_perm_map_size =
63d05f0226Sjoerg     (int)(sizeof(acl_posix_perm_map)/sizeof(acl_posix_perm_map[0]));
64d05f0226Sjoerg 
65d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
66d05f0226Sjoerg static const acl_perm_map_t acl_nfs4_perm_map[] = {
67d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
68d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
69d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
70d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
71d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
72d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
73d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
74d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
75d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
76d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
77d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
78d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
79d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
80d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
81d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
82d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
83d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
84d05f0226Sjoerg };
85d05f0226Sjoerg 
86d05f0226Sjoerg static const int acl_nfs4_perm_map_size =
87d05f0226Sjoerg     (int)(sizeof(acl_nfs4_perm_map)/sizeof(acl_nfs4_perm_map[0]));
88d05f0226Sjoerg 
89d05f0226Sjoerg static const acl_perm_map_t acl_nfs4_flag_map[] = {
90d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
91d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
92d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
93d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
94d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
95d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
96*efdd4e46Sjoerg #ifdef ACL_ENTRY_INHERITED
97d05f0226Sjoerg 	{ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
98*efdd4e46Sjoerg #endif
99d05f0226Sjoerg };
100d05f0226Sjoerg 
101d05f0226Sjoerg static const int acl_nfs4_flag_map_size =
102d05f0226Sjoerg     (int)(sizeof(acl_nfs4_flag_map)/sizeof(acl_nfs4_flag_map[0]));
103d05f0226Sjoerg #endif /* ARCHIVE_ACL_FREEBSD_NFS4 */
104d05f0226Sjoerg 
105d05f0226Sjoerg static int
translate_acl(struct archive_read_disk * a,struct archive_entry * entry,acl_t acl,int default_entry_acl_type)106d05f0226Sjoerg translate_acl(struct archive_read_disk *a,
107d05f0226Sjoerg     struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
108d05f0226Sjoerg {
109d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
110d05f0226Sjoerg 	int brand;
111d05f0226Sjoerg 	acl_flagset_t	 acl_flagset;
112d05f0226Sjoerg 	acl_entry_type_t acl_type;
113d05f0226Sjoerg #endif
114d05f0226Sjoerg 	acl_tag_t	 acl_tag;
115d05f0226Sjoerg 	acl_entry_t	 acl_entry;
116d05f0226Sjoerg 	acl_permset_t	 acl_permset;
117d05f0226Sjoerg 	int		 i, entry_acl_type, perm_map_size;
118d05f0226Sjoerg 	const acl_perm_map_t	*perm_map;
119d05f0226Sjoerg 	int		 r, s, ae_id, ae_tag, ae_perm;
120d05f0226Sjoerg 	void		*q;
121d05f0226Sjoerg 	const char	*ae_name;
122d05f0226Sjoerg 
123d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
124d05f0226Sjoerg 	// FreeBSD "brands" ACLs as POSIX.1e or NFSv4
125d05f0226Sjoerg 	// Make sure the "brand" on this ACL is consistent
126d05f0226Sjoerg 	// with the default_entry_acl_type bits provided.
127d05f0226Sjoerg 	if (acl_get_brand_np(acl, &brand) != 0) {
128d05f0226Sjoerg 		archive_set_error(&a->archive, errno,
129d05f0226Sjoerg 		    "Failed to read ACL brand");
130d05f0226Sjoerg 		return (ARCHIVE_WARN);
131d05f0226Sjoerg 	}
132d05f0226Sjoerg 	switch (brand) {
133d05f0226Sjoerg 	case ACL_BRAND_POSIX:
134d05f0226Sjoerg 		switch (default_entry_acl_type) {
135d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
136d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
137d05f0226Sjoerg 			break;
138d05f0226Sjoerg 		default:
139d05f0226Sjoerg 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
140d05f0226Sjoerg 			    "Invalid ACL entry type for POSIX.1e ACL");
141d05f0226Sjoerg 			return (ARCHIVE_WARN);
142d05f0226Sjoerg 		}
143d05f0226Sjoerg 		break;
144d05f0226Sjoerg 	case ACL_BRAND_NFS4:
145d05f0226Sjoerg 		if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
146d05f0226Sjoerg 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
147d05f0226Sjoerg 			    "Invalid ACL entry type for NFSv4 ACL");
148d05f0226Sjoerg 			return (ARCHIVE_WARN);
149d05f0226Sjoerg 		}
150d05f0226Sjoerg 		break;
151d05f0226Sjoerg 	default:
152d05f0226Sjoerg 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
153d05f0226Sjoerg 		    "Unknown ACL brand");
154d05f0226Sjoerg 		return (ARCHIVE_WARN);
155d05f0226Sjoerg 	}
156d05f0226Sjoerg #endif
157d05f0226Sjoerg 
158d05f0226Sjoerg 	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
159d05f0226Sjoerg 	if (s == -1) {
160d05f0226Sjoerg 		archive_set_error(&a->archive, errno,
161d05f0226Sjoerg 		    "Failed to get first ACL entry");
162d05f0226Sjoerg 		return (ARCHIVE_WARN);
163d05f0226Sjoerg 	}
164d05f0226Sjoerg 
165d05f0226Sjoerg 	while (s == 1) {
166d05f0226Sjoerg 		ae_id = -1;
167d05f0226Sjoerg 		ae_name = NULL;
168d05f0226Sjoerg 		ae_perm = 0;
169d05f0226Sjoerg 
170d05f0226Sjoerg 		if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
171d05f0226Sjoerg 			archive_set_error(&a->archive, errno,
172d05f0226Sjoerg 			    "Failed to get ACL tag type");
173d05f0226Sjoerg 			return (ARCHIVE_WARN);
174d05f0226Sjoerg 		}
175d05f0226Sjoerg 		switch (acl_tag) {
176d05f0226Sjoerg 		case ACL_USER:
177d05f0226Sjoerg 			q = acl_get_qualifier(acl_entry);
178d05f0226Sjoerg 			if (q != NULL) {
179d05f0226Sjoerg 				ae_id = (int)*(uid_t *)q;
180d05f0226Sjoerg 				acl_free(q);
181d05f0226Sjoerg 				ae_name = archive_read_disk_uname(&a->archive,
182d05f0226Sjoerg 				    ae_id);
183d05f0226Sjoerg 			}
184d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_USER;
185d05f0226Sjoerg 			break;
186d05f0226Sjoerg 		case ACL_GROUP:
187d05f0226Sjoerg 			q = acl_get_qualifier(acl_entry);
188d05f0226Sjoerg 			if (q != NULL) {
189d05f0226Sjoerg 				ae_id = (int)*(gid_t *)q;
190d05f0226Sjoerg 				acl_free(q);
191d05f0226Sjoerg 				ae_name = archive_read_disk_gname(&a->archive,
192d05f0226Sjoerg 				    ae_id);
193d05f0226Sjoerg 			}
194d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
195d05f0226Sjoerg 			break;
196d05f0226Sjoerg 		case ACL_MASK:
197d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_MASK;
198d05f0226Sjoerg 			break;
199d05f0226Sjoerg 		case ACL_USER_OBJ:
200d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
201d05f0226Sjoerg 			break;
202d05f0226Sjoerg 		case ACL_GROUP_OBJ:
203d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
204d05f0226Sjoerg 			break;
205d05f0226Sjoerg 		case ACL_OTHER:
206d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
207d05f0226Sjoerg 			break;
208d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
209d05f0226Sjoerg 		case ACL_EVERYONE:
210d05f0226Sjoerg 			ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
211d05f0226Sjoerg 			break;
212d05f0226Sjoerg #endif
213d05f0226Sjoerg 		default:
214d05f0226Sjoerg 			/* Skip types that libarchive can't support. */
215d05f0226Sjoerg 			s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
216d05f0226Sjoerg 			continue;
217d05f0226Sjoerg 		}
218d05f0226Sjoerg 
219d05f0226Sjoerg 		// XXX acl_type maps to allow/deny/audit/YYYY bits
220d05f0226Sjoerg 		entry_acl_type = default_entry_acl_type;
221d05f0226Sjoerg 
222d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
223d05f0226Sjoerg 		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
224d05f0226Sjoerg 			/*
225d05f0226Sjoerg 			 * acl_get_entry_type_np() fails with non-NFSv4 ACLs
226d05f0226Sjoerg 			 */
227d05f0226Sjoerg 			if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
228d05f0226Sjoerg 				archive_set_error(&a->archive, errno, "Failed "
229d05f0226Sjoerg 				    "to get ACL type from a NFSv4 ACL entry");
230d05f0226Sjoerg 				return (ARCHIVE_WARN);
231d05f0226Sjoerg 			}
232d05f0226Sjoerg 			switch (acl_type) {
233d05f0226Sjoerg 			case ACL_ENTRY_TYPE_ALLOW:
234d05f0226Sjoerg 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
235d05f0226Sjoerg 				break;
236d05f0226Sjoerg 			case ACL_ENTRY_TYPE_DENY:
237d05f0226Sjoerg 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
238d05f0226Sjoerg 				break;
239d05f0226Sjoerg 			case ACL_ENTRY_TYPE_AUDIT:
240d05f0226Sjoerg 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
241d05f0226Sjoerg 				break;
242d05f0226Sjoerg 			case ACL_ENTRY_TYPE_ALARM:
243d05f0226Sjoerg 				entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
244d05f0226Sjoerg 				break;
245d05f0226Sjoerg 			default:
246d05f0226Sjoerg 				archive_set_error(&a->archive, errno,
247d05f0226Sjoerg 				    "Invalid NFSv4 ACL entry type");
248d05f0226Sjoerg 				return (ARCHIVE_WARN);
249d05f0226Sjoerg 			}
250d05f0226Sjoerg 
251d05f0226Sjoerg 			/*
252d05f0226Sjoerg 			 * Libarchive stores "flag" (NFSv4 inheritance bits)
253d05f0226Sjoerg 			 * in the ae_perm bitmap.
254d05f0226Sjoerg 			 *
255d05f0226Sjoerg 			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
256d05f0226Sjoerg 			 */
257d05f0226Sjoerg 			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
258d05f0226Sjoerg 				archive_set_error(&a->archive, errno,
259d05f0226Sjoerg 				    "Failed to get flagset from a NFSv4 "
260d05f0226Sjoerg 				    "ACL entry");
261d05f0226Sjoerg 				return (ARCHIVE_WARN);
262d05f0226Sjoerg 			}
263d05f0226Sjoerg 			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
264d05f0226Sjoerg 				r = acl_get_flag_np(acl_flagset,
265d05f0226Sjoerg 				    acl_nfs4_flag_map[i].p_perm);
266d05f0226Sjoerg 				if (r == -1) {
267d05f0226Sjoerg 					archive_set_error(&a->archive, errno,
268d05f0226Sjoerg 					    "Failed to check flag in a NFSv4 "
269d05f0226Sjoerg 					    "ACL flagset");
270d05f0226Sjoerg 					return (ARCHIVE_WARN);
271d05f0226Sjoerg 				} else if (r)
272d05f0226Sjoerg 					ae_perm |= acl_nfs4_flag_map[i].a_perm;
273d05f0226Sjoerg 			}
274d05f0226Sjoerg 		}
275d05f0226Sjoerg #endif
276d05f0226Sjoerg 
277d05f0226Sjoerg 		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
278d05f0226Sjoerg 			archive_set_error(&a->archive, errno,
279d05f0226Sjoerg 			    "Failed to get ACL permission set");
280d05f0226Sjoerg 			return (ARCHIVE_WARN);
281d05f0226Sjoerg 		}
282d05f0226Sjoerg 
283d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
284d05f0226Sjoerg 		if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
285d05f0226Sjoerg 			perm_map_size = acl_nfs4_perm_map_size;
286d05f0226Sjoerg 			perm_map = acl_nfs4_perm_map;
287d05f0226Sjoerg 		} else {
288d05f0226Sjoerg #endif
289d05f0226Sjoerg 			perm_map_size = acl_posix_perm_map_size;
290d05f0226Sjoerg 			perm_map = acl_posix_perm_map;
291d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
292d05f0226Sjoerg 		}
293d05f0226Sjoerg #endif
294d05f0226Sjoerg 
295d05f0226Sjoerg 		for (i = 0; i < perm_map_size; ++i) {
296d05f0226Sjoerg 			r = acl_get_perm_np(acl_permset, perm_map[i].p_perm);
297d05f0226Sjoerg 			if (r == -1) {
298d05f0226Sjoerg 				archive_set_error(&a->archive, errno,
299d05f0226Sjoerg 				    "Failed to check permission in an ACL "
300d05f0226Sjoerg 				    "permission set");
301d05f0226Sjoerg 				return (ARCHIVE_WARN);
302d05f0226Sjoerg 			} else if (r)
303d05f0226Sjoerg 				ae_perm |= perm_map[i].a_perm;
304d05f0226Sjoerg 		}
305d05f0226Sjoerg 
306d05f0226Sjoerg 		archive_entry_acl_add_entry(entry, entry_acl_type,
307d05f0226Sjoerg 					    ae_perm, ae_tag,
308d05f0226Sjoerg 					    ae_id, ae_name);
309d05f0226Sjoerg 
310d05f0226Sjoerg 		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
311d05f0226Sjoerg 		if (s == -1) {
312d05f0226Sjoerg 			archive_set_error(&a->archive, errno,
313d05f0226Sjoerg 			    "Failed to get next ACL entry");
314d05f0226Sjoerg 			return (ARCHIVE_WARN);
315d05f0226Sjoerg 		}
316d05f0226Sjoerg 	}
317d05f0226Sjoerg 	return (ARCHIVE_OK);
318d05f0226Sjoerg }
319d05f0226Sjoerg 
320d05f0226Sjoerg static int
set_acl(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl,int ae_requested_type,const char * tname)321d05f0226Sjoerg set_acl(struct archive *a, int fd, const char *name,
322d05f0226Sjoerg     struct archive_acl *abstract_acl,
323d05f0226Sjoerg     int ae_requested_type, const char *tname)
324d05f0226Sjoerg {
325d05f0226Sjoerg 	int		 acl_type = 0;
326d05f0226Sjoerg 	acl_t		 acl;
327d05f0226Sjoerg 	acl_entry_t	 acl_entry;
328d05f0226Sjoerg 	acl_permset_t	 acl_permset;
329d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
330d05f0226Sjoerg 	acl_flagset_t	 acl_flagset;
331d05f0226Sjoerg 	int		 r;
332d05f0226Sjoerg #endif
333d05f0226Sjoerg 	int		 ret;
334d05f0226Sjoerg 	int		 ae_type, ae_permset, ae_tag, ae_id;
335d05f0226Sjoerg 	int		 perm_map_size;
336d05f0226Sjoerg 	const acl_perm_map_t	*perm_map;
337d05f0226Sjoerg 	uid_t		 ae_uid;
338d05f0226Sjoerg 	gid_t		 ae_gid;
339d05f0226Sjoerg 	const char	*ae_name;
340d05f0226Sjoerg 	int		 entries;
341d05f0226Sjoerg 	int		 i;
342d05f0226Sjoerg 
343d05f0226Sjoerg 	ret = ARCHIVE_OK;
344d05f0226Sjoerg 	entries = archive_acl_reset(abstract_acl, ae_requested_type);
345d05f0226Sjoerg 	if (entries == 0)
346d05f0226Sjoerg 		return (ARCHIVE_OK);
347d05f0226Sjoerg 
348d05f0226Sjoerg 
349d05f0226Sjoerg 	switch (ae_requested_type) {
350d05f0226Sjoerg 	case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
351d05f0226Sjoerg 		acl_type = ACL_TYPE_ACCESS;
352d05f0226Sjoerg 		break;
353d05f0226Sjoerg 	case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
354d05f0226Sjoerg 		acl_type = ACL_TYPE_DEFAULT;
355d05f0226Sjoerg 		break;
356d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
357d05f0226Sjoerg 	case ARCHIVE_ENTRY_ACL_TYPE_NFS4:
358d05f0226Sjoerg 		acl_type = ACL_TYPE_NFS4;
359d05f0226Sjoerg 		break;
360d05f0226Sjoerg #endif
361d05f0226Sjoerg 	default:
362d05f0226Sjoerg 		errno = ENOENT;
363d05f0226Sjoerg 		archive_set_error(a, errno, "Unsupported ACL type");
364d05f0226Sjoerg 		return (ARCHIVE_FAILED);
365d05f0226Sjoerg 	}
366d05f0226Sjoerg 
367d05f0226Sjoerg 	acl = acl_init(entries);
368d05f0226Sjoerg 	if (acl == (acl_t)NULL) {
369d05f0226Sjoerg 		archive_set_error(a, errno,
370d05f0226Sjoerg 		    "Failed to initialize ACL working storage");
371d05f0226Sjoerg 		return (ARCHIVE_FAILED);
372d05f0226Sjoerg 	}
373d05f0226Sjoerg 
374d05f0226Sjoerg 	while (archive_acl_next(a, abstract_acl, ae_requested_type, &ae_type,
375d05f0226Sjoerg 		   &ae_permset, &ae_tag, &ae_id, &ae_name) == ARCHIVE_OK) {
376d05f0226Sjoerg 		if (acl_create_entry(&acl, &acl_entry) != 0) {
377d05f0226Sjoerg 			archive_set_error(a, errno,
378d05f0226Sjoerg 			    "Failed to create a new ACL entry");
379d05f0226Sjoerg 			ret = ARCHIVE_FAILED;
380d05f0226Sjoerg 			goto exit_free;
381d05f0226Sjoerg 		}
382d05f0226Sjoerg 		switch (ae_tag) {
383d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_USER:
384d05f0226Sjoerg 			ae_uid = archive_write_disk_uid(a, ae_name, ae_id);
385d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_USER);
386d05f0226Sjoerg 			acl_set_qualifier(acl_entry, &ae_uid);
387d05f0226Sjoerg 			break;
388d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_GROUP:
389d05f0226Sjoerg 			ae_gid = archive_write_disk_gid(a, ae_name, ae_id);
390d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_GROUP);
391d05f0226Sjoerg 			acl_set_qualifier(acl_entry, &ae_gid);
392d05f0226Sjoerg 			break;
393d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_USER_OBJ:
394d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_USER_OBJ);
395d05f0226Sjoerg 			break;
396d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_GROUP_OBJ:
397d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_GROUP_OBJ);
398d05f0226Sjoerg 			break;
399d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_MASK:
400d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_MASK);
401d05f0226Sjoerg 			break;
402d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_OTHER:
403d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_OTHER);
404d05f0226Sjoerg 			break;
405d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
406d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_EVERYONE:
407d05f0226Sjoerg 			acl_set_tag_type(acl_entry, ACL_EVERYONE);
408d05f0226Sjoerg 			break;
409d05f0226Sjoerg #endif
410d05f0226Sjoerg 		default:
411d05f0226Sjoerg 			archive_set_error(a, ARCHIVE_ERRNO_MISC,
412d05f0226Sjoerg 			    "Unsupported ACL tag");
413d05f0226Sjoerg 			ret = ARCHIVE_FAILED;
414d05f0226Sjoerg 			goto exit_free;
415d05f0226Sjoerg 		}
416d05f0226Sjoerg 
417d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
418d05f0226Sjoerg 		r = 0;
419d05f0226Sjoerg 		switch (ae_type) {
420d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_ALLOW:
421d05f0226Sjoerg 			r = acl_set_entry_type_np(acl_entry,
422d05f0226Sjoerg 			    ACL_ENTRY_TYPE_ALLOW);
423d05f0226Sjoerg 			break;
424d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_DENY:
425d05f0226Sjoerg 			r = acl_set_entry_type_np(acl_entry,
426d05f0226Sjoerg 			    ACL_ENTRY_TYPE_DENY);
427d05f0226Sjoerg 			break;
428d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_AUDIT:
429d05f0226Sjoerg 			r = acl_set_entry_type_np(acl_entry,
430d05f0226Sjoerg 			    ACL_ENTRY_TYPE_AUDIT);
431d05f0226Sjoerg 			break;
432d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_ALARM:
433d05f0226Sjoerg 			r = acl_set_entry_type_np(acl_entry,
434d05f0226Sjoerg 			    ACL_ENTRY_TYPE_ALARM);
435d05f0226Sjoerg 			break;
436d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
437d05f0226Sjoerg 		case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
438d05f0226Sjoerg 			// These don't translate directly into the system ACL.
439d05f0226Sjoerg 			break;
440d05f0226Sjoerg 		default:
441d05f0226Sjoerg 			archive_set_error(a, ARCHIVE_ERRNO_MISC,
442d05f0226Sjoerg 			    "Unsupported ACL entry type");
443d05f0226Sjoerg 			ret = ARCHIVE_FAILED;
444d05f0226Sjoerg 			goto exit_free;
445d05f0226Sjoerg 		}
446d05f0226Sjoerg 
447d05f0226Sjoerg 		if (r != 0) {
448d05f0226Sjoerg 			archive_set_error(a, errno,
449d05f0226Sjoerg 			    "Failed to set ACL entry type");
450d05f0226Sjoerg 			ret = ARCHIVE_FAILED;
451d05f0226Sjoerg 			goto exit_free;
452d05f0226Sjoerg 		}
453d05f0226Sjoerg #endif
454d05f0226Sjoerg 
455d05f0226Sjoerg 		if (acl_get_permset(acl_entry, &acl_permset) != 0) {
456d05f0226Sjoerg 			archive_set_error(a, errno,
457d05f0226Sjoerg 			    "Failed to get ACL permission set");
458d05f0226Sjoerg 			ret = ARCHIVE_FAILED;
459d05f0226Sjoerg 			goto exit_free;
460d05f0226Sjoerg 		}
461d05f0226Sjoerg 		if (acl_clear_perms(acl_permset) != 0) {
462d05f0226Sjoerg 			archive_set_error(a, errno,
463d05f0226Sjoerg 			    "Failed to clear ACL permissions");
464d05f0226Sjoerg 			ret = ARCHIVE_FAILED;
465d05f0226Sjoerg 			goto exit_free;
466d05f0226Sjoerg 		}
467d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
468d05f0226Sjoerg 		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
469d05f0226Sjoerg 			perm_map_size = acl_nfs4_perm_map_size;
470d05f0226Sjoerg 			perm_map = acl_nfs4_perm_map;
471d05f0226Sjoerg 		} else {
472d05f0226Sjoerg #endif
473d05f0226Sjoerg 			perm_map_size = acl_posix_perm_map_size;
474d05f0226Sjoerg 			perm_map = acl_posix_perm_map;
475d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
476d05f0226Sjoerg 		}
477d05f0226Sjoerg #endif
478d05f0226Sjoerg 
479d05f0226Sjoerg 		for (i = 0; i < perm_map_size; ++i) {
480d05f0226Sjoerg 			if (ae_permset & perm_map[i].a_perm) {
481d05f0226Sjoerg 				if (acl_add_perm(acl_permset,
482d05f0226Sjoerg 				    perm_map[i].p_perm) != 0) {
483d05f0226Sjoerg 					archive_set_error(a, errno,
484d05f0226Sjoerg 					    "Failed to add ACL permission");
485d05f0226Sjoerg 					ret = ARCHIVE_FAILED;
486d05f0226Sjoerg 					goto exit_free;
487d05f0226Sjoerg 				}
488d05f0226Sjoerg 			}
489d05f0226Sjoerg 		}
490d05f0226Sjoerg 
491d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
492d05f0226Sjoerg 		if (ae_requested_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
493d05f0226Sjoerg 			/*
494d05f0226Sjoerg 			 * acl_get_flagset_np() fails with non-NFSv4 ACLs
495d05f0226Sjoerg 			 */
496d05f0226Sjoerg 			if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
497d05f0226Sjoerg 				archive_set_error(a, errno,
498d05f0226Sjoerg 				    "Failed to get flagset from an NFSv4 "
499d05f0226Sjoerg 				    "ACL entry");
500d05f0226Sjoerg 				ret = ARCHIVE_FAILED;
501d05f0226Sjoerg 				goto exit_free;
502d05f0226Sjoerg 			}
503d05f0226Sjoerg 			if (acl_clear_flags_np(acl_flagset) != 0) {
504d05f0226Sjoerg 				archive_set_error(a, errno,
505d05f0226Sjoerg 				    "Failed to clear flags from an NFSv4 "
506d05f0226Sjoerg 				    "ACL flagset");
507d05f0226Sjoerg 				ret = ARCHIVE_FAILED;
508d05f0226Sjoerg 				goto exit_free;
509d05f0226Sjoerg 			}
510d05f0226Sjoerg 			for (i = 0; i < acl_nfs4_flag_map_size; ++i) {
511d05f0226Sjoerg 				if (ae_permset & acl_nfs4_flag_map[i].a_perm) {
512d05f0226Sjoerg 					if (acl_add_flag_np(acl_flagset,
513d05f0226Sjoerg 					    acl_nfs4_flag_map[i].p_perm) != 0) {
514d05f0226Sjoerg 						archive_set_error(a, errno,
515d05f0226Sjoerg 						    "Failed to add flag to "
516d05f0226Sjoerg 						    "NFSv4 ACL flagset");
517d05f0226Sjoerg 						ret = ARCHIVE_FAILED;
518d05f0226Sjoerg 						goto exit_free;
519d05f0226Sjoerg 					}
520d05f0226Sjoerg 				}
521d05f0226Sjoerg 			}
522d05f0226Sjoerg 		}
523d05f0226Sjoerg #endif
524d05f0226Sjoerg 	}
525d05f0226Sjoerg 
526d05f0226Sjoerg 	/* Try restoring the ACL through 'fd' if we can. */
527d05f0226Sjoerg 	if (fd >= 0) {
528d05f0226Sjoerg 		if (acl_set_fd_np(fd, acl, acl_type) == 0)
529d05f0226Sjoerg 			ret = ARCHIVE_OK;
530d05f0226Sjoerg 		else {
531d05f0226Sjoerg 			if (errno == EOPNOTSUPP) {
532d05f0226Sjoerg 				/* Filesystem doesn't support ACLs */
533d05f0226Sjoerg 				ret = ARCHIVE_OK;
534d05f0226Sjoerg 			} else {
535d05f0226Sjoerg 				archive_set_error(a, errno,
536d05f0226Sjoerg 				    "Failed to set acl on fd: %s", tname);
537d05f0226Sjoerg 				ret = ARCHIVE_WARN;
538d05f0226Sjoerg 			}
539d05f0226Sjoerg 		}
540d05f0226Sjoerg 	}
541d05f0226Sjoerg #if HAVE_ACL_SET_LINK_NP
542d05f0226Sjoerg 	else if (acl_set_link_np(name, acl_type, acl) != 0)
543d05f0226Sjoerg #else
544d05f0226Sjoerg 	/* FreeBSD older than 8.0 */
545d05f0226Sjoerg 	else if (acl_set_file(name, acl_type, acl) != 0)
546d05f0226Sjoerg #endif
547d05f0226Sjoerg 	{
548d05f0226Sjoerg 		if (errno == EOPNOTSUPP) {
549d05f0226Sjoerg 			/* Filesystem doesn't support ACLs */
550d05f0226Sjoerg 			ret = ARCHIVE_OK;
551d05f0226Sjoerg 		} else {
552d05f0226Sjoerg 			archive_set_error(a, errno, "Failed to set acl: %s",
553d05f0226Sjoerg 			    tname);
554d05f0226Sjoerg 			ret = ARCHIVE_WARN;
555d05f0226Sjoerg 		}
556d05f0226Sjoerg 	}
557d05f0226Sjoerg exit_free:
558d05f0226Sjoerg 	acl_free(acl);
559d05f0226Sjoerg 	return (ret);
560d05f0226Sjoerg }
561d05f0226Sjoerg 
562d05f0226Sjoerg int
archive_read_disk_entry_setup_acls(struct archive_read_disk * a,struct archive_entry * entry,int * fd)563d05f0226Sjoerg archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
564d05f0226Sjoerg     struct archive_entry *entry, int *fd)
565d05f0226Sjoerg {
566d05f0226Sjoerg 	const char	*accpath;
567d05f0226Sjoerg 	acl_t		acl;
568d05f0226Sjoerg 	int		r;
569d05f0226Sjoerg 
570d05f0226Sjoerg 	accpath = NULL;
571d05f0226Sjoerg 
572d05f0226Sjoerg 	if (*fd < 0) {
573d05f0226Sjoerg 		accpath = archive_read_disk_entry_setup_path(a, entry, fd);
574d05f0226Sjoerg 		if (accpath == NULL)
575d05f0226Sjoerg 			return (ARCHIVE_WARN);
576d05f0226Sjoerg 	}
577d05f0226Sjoerg 
578d05f0226Sjoerg 	archive_entry_acl_clear(entry);
579d05f0226Sjoerg 
580d05f0226Sjoerg 	acl = NULL;
581d05f0226Sjoerg 
582d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
583d05f0226Sjoerg 	/* Try NFSv4 ACL first. */
584d05f0226Sjoerg 	if (*fd >= 0)
585d05f0226Sjoerg 		acl = acl_get_fd_np(*fd, ACL_TYPE_NFS4);
586d05f0226Sjoerg 	else if (!a->follow_symlinks)
587d05f0226Sjoerg 		acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
588d05f0226Sjoerg 	else
589d05f0226Sjoerg 		acl = acl_get_file(accpath, ACL_TYPE_NFS4);
590d05f0226Sjoerg 
591d05f0226Sjoerg 	/* Ignore "trivial" ACLs that just mirror the file mode. */
592d05f0226Sjoerg 	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
593d05f0226Sjoerg 		acl_free(acl);
594d05f0226Sjoerg 		acl = NULL;
595d05f0226Sjoerg 		return (ARCHIVE_OK);
596d05f0226Sjoerg 	}
597d05f0226Sjoerg 
598d05f0226Sjoerg 	if (acl != NULL) {
599d05f0226Sjoerg 		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
600d05f0226Sjoerg 		acl_free(acl);
601d05f0226Sjoerg 		acl = NULL;
602d05f0226Sjoerg 
603d05f0226Sjoerg 		if (r != ARCHIVE_OK) {
604d05f0226Sjoerg 			archive_set_error(&a->archive, errno,
605d05f0226Sjoerg 			    "Couldn't translate NFSv4 ACLs");
606d05f0226Sjoerg 		}
607d05f0226Sjoerg 
608d05f0226Sjoerg 		return (r);
609d05f0226Sjoerg 	}
610d05f0226Sjoerg #endif
611d05f0226Sjoerg 
612d05f0226Sjoerg 	/* Retrieve access ACL from file. */
613d05f0226Sjoerg 	if (*fd >= 0)
614d05f0226Sjoerg 		acl = acl_get_fd_np(*fd, ACL_TYPE_ACCESS);
615d05f0226Sjoerg #if HAVE_ACL_GET_LINK_NP
616d05f0226Sjoerg 	else if (!a->follow_symlinks)
617d05f0226Sjoerg 		acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
618d05f0226Sjoerg #else
619d05f0226Sjoerg 	else if ((!a->follow_symlinks)
620d05f0226Sjoerg 	    && (archive_entry_filetype(entry) == AE_IFLNK))
621d05f0226Sjoerg 		/* We can't get the ACL of a symlink, so we assume it can't
622d05f0226Sjoerg 		   have one. */
623d05f0226Sjoerg 		acl = NULL;
624d05f0226Sjoerg #endif
625d05f0226Sjoerg 	else
626d05f0226Sjoerg 		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
627d05f0226Sjoerg 
628d05f0226Sjoerg #if HAVE_ACL_IS_TRIVIAL_NP
629d05f0226Sjoerg 	/* Ignore "trivial" ACLs that just mirror the file mode. */
630d05f0226Sjoerg 	if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
631d05f0226Sjoerg 		acl_free(acl);
632d05f0226Sjoerg 		acl = NULL;
633d05f0226Sjoerg 	}
634d05f0226Sjoerg #endif
635d05f0226Sjoerg 
636d05f0226Sjoerg 	if (acl != NULL) {
637d05f0226Sjoerg 		r = translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
638d05f0226Sjoerg 		acl_free(acl);
639d05f0226Sjoerg 		acl = NULL;
640d05f0226Sjoerg 
641d05f0226Sjoerg 		if (r != ARCHIVE_OK) {
642d05f0226Sjoerg 			archive_set_error(&a->archive, errno,
643d05f0226Sjoerg 			    "Couldn't translate access ACLs");
644d05f0226Sjoerg 			return (r);
645d05f0226Sjoerg 		}
646d05f0226Sjoerg 	}
647d05f0226Sjoerg 
648d05f0226Sjoerg 	/* Only directories can have default ACLs. */
649d05f0226Sjoerg 	if (S_ISDIR(archive_entry_mode(entry))) {
650d05f0226Sjoerg 		if (*fd >= 0)
651d05f0226Sjoerg 			acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
652d05f0226Sjoerg 		else
653d05f0226Sjoerg 			acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
654d05f0226Sjoerg 		if (acl != NULL) {
655d05f0226Sjoerg 			r = translate_acl(a, entry, acl,
656d05f0226Sjoerg 			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
657d05f0226Sjoerg 			acl_free(acl);
658d05f0226Sjoerg 			if (r != ARCHIVE_OK) {
659d05f0226Sjoerg 				archive_set_error(&a->archive, errno,
660d05f0226Sjoerg 				    "Couldn't translate default ACLs");
661d05f0226Sjoerg 				return (r);
662d05f0226Sjoerg 			}
663d05f0226Sjoerg 		}
664d05f0226Sjoerg 	}
665d05f0226Sjoerg 	return (ARCHIVE_OK);
666d05f0226Sjoerg }
667d05f0226Sjoerg 
668d05f0226Sjoerg int
archive_write_disk_set_acls(struct archive * a,int fd,const char * name,struct archive_acl * abstract_acl,__LA_MODE_T mode)669d05f0226Sjoerg archive_write_disk_set_acls(struct archive *a, int fd, const char *name,
670d05f0226Sjoerg     struct archive_acl *abstract_acl, __LA_MODE_T mode)
671d05f0226Sjoerg {
672d05f0226Sjoerg 	int		ret = ARCHIVE_OK;
673d05f0226Sjoerg 
674d05f0226Sjoerg 	(void)mode;	/* UNUSED */
675d05f0226Sjoerg 
676d05f0226Sjoerg 	if ((archive_acl_types(abstract_acl)
677d05f0226Sjoerg 	    & ARCHIVE_ENTRY_ACL_TYPE_POSIX1E) != 0) {
678d05f0226Sjoerg 		if ((archive_acl_types(abstract_acl)
679d05f0226Sjoerg 		    & ARCHIVE_ENTRY_ACL_TYPE_ACCESS) != 0) {
680d05f0226Sjoerg 			ret = set_acl(a, fd, name, abstract_acl,
681d05f0226Sjoerg 			    ARCHIVE_ENTRY_ACL_TYPE_ACCESS, "access");
682d05f0226Sjoerg 			if (ret != ARCHIVE_OK)
683d05f0226Sjoerg 				return (ret);
684d05f0226Sjoerg 		}
685d05f0226Sjoerg 		if ((archive_acl_types(abstract_acl)
686d05f0226Sjoerg 		    & ARCHIVE_ENTRY_ACL_TYPE_DEFAULT) != 0)
687d05f0226Sjoerg 			ret = set_acl(a, fd, name, abstract_acl,
688d05f0226Sjoerg 			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT, "default");
689d05f0226Sjoerg 
690d05f0226Sjoerg 		/* Simultaneous POSIX.1e and NFSv4 is not supported */
691d05f0226Sjoerg 		return (ret);
692d05f0226Sjoerg 	}
693d05f0226Sjoerg #if ARCHIVE_ACL_FREEBSD_NFS4
694d05f0226Sjoerg 	else if ((archive_acl_types(abstract_acl) &
695d05f0226Sjoerg 	    ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) {
696d05f0226Sjoerg 		ret = set_acl(a, fd, name, abstract_acl,
697d05f0226Sjoerg 		    ARCHIVE_ENTRY_ACL_TYPE_NFS4, "nfs4");
698d05f0226Sjoerg 	}
699d05f0226Sjoerg #endif
700d05f0226Sjoerg 	return (ret);
701d05f0226Sjoerg }
702d05f0226Sjoerg #endif	/* ARCHIVE_ACL_FREEBSD */
703