Sun Mar 12 06:48:36 2017 UTC ()
Merge a15c7f7b496ba4cefbcaf6f8ac637db4f3009a58:

 Solaris: use aclp instead of acl to not shadow global acl()


(joerg)
diff -r1.7 -r1.8 pkgsrc/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c

cvs diff -r1.7 -r1.8 pkgsrc/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c (switch to unified diff)

--- pkgsrc/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c 2017/03/12 06:45:16 1.7
+++ pkgsrc/archivers/libarchive/files/libarchive/archive_read_disk_entry_from_file.c 2017/03/12 06:48:36 1.8
@@ -1,1695 +1,1712 @@ @@ -1,1695 +1,1712 @@
1/*- 1/*-
2 * Copyright (c) 2003-2009 Tim Kientzle 2 * Copyright (c) 2003-2009 Tim Kientzle
3 * Copyright (c) 2010-2012 Michihiro NAKAJIMA 3 * Copyright (c) 2010-2012 Michihiro NAKAJIMA
4 * Copyright (c) 2016 Martin Matuska 4 * Copyright (c) 2016 Martin Matuska
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * Redistribution and use in source and binary forms, with or without 7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions 8 * modification, are permitted provided that the following conditions
9 * are met: 9 * are met:
10 * 1. Redistributions of source code must retain the above copyright 10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer. 11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright 12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the 13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution. 14 * documentation and/or other materials provided with the distribution.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28#include "archive_platform.h" 28#include "archive_platform.h"
29__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $"); 29__FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
30 30
31/* This is the tree-walking code for POSIX systems. */ 31/* This is the tree-walking code for POSIX systems. */
32#if !defined(_WIN32) || defined(__CYGWIN__) 32#if !defined(_WIN32) || defined(__CYGWIN__)
33 33
34#ifdef HAVE_SYS_TYPES_H 34#ifdef HAVE_SYS_TYPES_H
35/* Mac OSX requires sys/types.h before sys/acl.h. */ 35/* Mac OSX requires sys/types.h before sys/acl.h. */
36#include <sys/types.h> 36#include <sys/types.h>
37#endif 37#endif
38#ifdef HAVE_SYS_ACL_H 38#ifdef HAVE_SYS_ACL_H
39#include <sys/acl.h> 39#include <sys/acl.h>
40#endif 40#endif
41#ifdef HAVE_DARWIN_ACL 41#ifdef HAVE_DARWIN_ACL
42#include <membership.h> 42#include <membership.h>
43#include <grp.h> 43#include <grp.h>
44#include <pwd.h> 44#include <pwd.h>
45#endif 45#endif
46#ifdef HAVE_SYS_EXTATTR_H 46#ifdef HAVE_SYS_EXTATTR_H
47#include <sys/extattr.h> 47#include <sys/extattr.h>
48#endif 48#endif
49#ifdef HAVE_SYS_IOCTL_H 49#ifdef HAVE_SYS_IOCTL_H
50#include <sys/ioctl.h> 50#include <sys/ioctl.h>
51#endif 51#endif
52#ifdef HAVE_SYS_PARAM_H 52#ifdef HAVE_SYS_PARAM_H
53#include <sys/param.h> 53#include <sys/param.h>
54#endif 54#endif
55#ifdef HAVE_SYS_STAT_H 55#ifdef HAVE_SYS_STAT_H
56#include <sys/stat.h> 56#include <sys/stat.h>
57#endif 57#endif
58#if defined(HAVE_SYS_XATTR_H) 58#if defined(HAVE_SYS_XATTR_H)
59#include <sys/xattr.h> 59#include <sys/xattr.h>
60#elif defined(HAVE_ATTR_XATTR_H) 60#elif defined(HAVE_ATTR_XATTR_H)
61#include <attr/xattr.h> 61#include <attr/xattr.h>
62#endif 62#endif
63#ifdef HAVE_SYS_EA_H 63#ifdef HAVE_SYS_EA_H
64#include <sys/ea.h> 64#include <sys/ea.h>
65#endif 65#endif
66#ifdef HAVE_ACL_LIBACL_H 66#ifdef HAVE_ACL_LIBACL_H
67#include <acl/libacl.h> 67#include <acl/libacl.h>
68#endif 68#endif
69#ifdef HAVE_COPYFILE_H 69#ifdef HAVE_COPYFILE_H
70#include <copyfile.h> 70#include <copyfile.h>
71#endif 71#endif
72#ifdef HAVE_ERRNO_H 72#ifdef HAVE_ERRNO_H
73#include <errno.h> 73#include <errno.h>
74#endif 74#endif
75#ifdef HAVE_FCNTL_H 75#ifdef HAVE_FCNTL_H
76#include <fcntl.h> 76#include <fcntl.h>
77#endif 77#endif
78#ifdef HAVE_LIMITS_H 78#ifdef HAVE_LIMITS_H
79#include <limits.h> 79#include <limits.h>
80#endif 80#endif
81#ifdef HAVE_LINUX_TYPES_H 81#ifdef HAVE_LINUX_TYPES_H
82#include <linux/types.h> 82#include <linux/types.h>
83#endif 83#endif
84#ifdef HAVE_LINUX_FIEMAP_H 84#ifdef HAVE_LINUX_FIEMAP_H
85#include <linux/fiemap.h> 85#include <linux/fiemap.h>
86#endif 86#endif
87#ifdef HAVE_LINUX_FS_H 87#ifdef HAVE_LINUX_FS_H
88#include <linux/fs.h> 88#include <linux/fs.h>
89#endif 89#endif
90/* 90/*
91 * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h. 91 * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
92 * As the include guards don't agree, the order of include is important. 92 * As the include guards don't agree, the order of include is important.
93 */ 93 */
94#ifdef HAVE_LINUX_EXT2_FS_H 94#ifdef HAVE_LINUX_EXT2_FS_H
95#include <linux/ext2_fs.h> /* for Linux file flags */ 95#include <linux/ext2_fs.h> /* for Linux file flags */
96#endif 96#endif
97#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__) 97#if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
98#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */ 98#include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
99#endif 99#endif
100#ifdef HAVE_PATHS_H 100#ifdef HAVE_PATHS_H
101#include <paths.h> 101#include <paths.h>
102#endif 102#endif
103#ifdef HAVE_UNISTD_H 103#ifdef HAVE_UNISTD_H
104#include <unistd.h> 104#include <unistd.h>
105#endif 105#endif
106 106
107#include "archive.h" 107#include "archive.h"
108#include "archive_entry.h" 108#include "archive_entry.h"
109#include "archive_private.h" 109#include "archive_private.h"
110#include "archive_read_disk_private.h" 110#include "archive_read_disk_private.h"
111 111
112#ifndef O_CLOEXEC 112#ifndef O_CLOEXEC
113#define O_CLOEXEC 0 113#define O_CLOEXEC 0
114#endif 114#endif
115 115
116/* 116/*
117 * Linux and FreeBSD plug this obvious hole in POSIX.1e in 117 * Linux and FreeBSD plug this obvious hole in POSIX.1e in
118 * different ways. 118 * different ways.
119 */ 119 */
120#if HAVE_ACL_GET_PERM 120#if HAVE_ACL_GET_PERM
121#define ACL_GET_PERM acl_get_perm 121#define ACL_GET_PERM acl_get_perm
122#elif HAVE_ACL_GET_PERM_NP 122#elif HAVE_ACL_GET_PERM_NP
123#define ACL_GET_PERM acl_get_perm_np 123#define ACL_GET_PERM acl_get_perm_np
124#endif 124#endif
125 125
126/* NFSv4 platform ACL type */ 126/* NFSv4 platform ACL type */
127#if HAVE_DARWIN_ACL 127#if HAVE_DARWIN_ACL
128#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED 128#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_EXTENDED
129#elif HAVE_FREEBSD_NFS4_ACL 129#elif HAVE_FREEBSD_NFS4_ACL
130#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4 130#define ARCHIVE_PLATFORM_ACL_TYPE_NFS4 ACL_TYPE_NFS4
131#endif 131#endif
132 132
133static int setup_acls(struct archive_read_disk *, 133static int setup_acls(struct archive_read_disk *,
134 struct archive_entry *, int *fd); 134 struct archive_entry *, int *fd);
135static int setup_mac_metadata(struct archive_read_disk *, 135static int setup_mac_metadata(struct archive_read_disk *,
136 struct archive_entry *, int *fd); 136 struct archive_entry *, int *fd);
137static int setup_xattrs(struct archive_read_disk *, 137static int setup_xattrs(struct archive_read_disk *,
138 struct archive_entry *, int *fd); 138 struct archive_entry *, int *fd);
139static int setup_sparse(struct archive_read_disk *, 139static int setup_sparse(struct archive_read_disk *,
140 struct archive_entry *, int *fd); 140 struct archive_entry *, int *fd);
141#if defined(HAVE_LINUX_FIEMAP_H) 141#if defined(HAVE_LINUX_FIEMAP_H)
142static int setup_sparse_fiemap(struct archive_read_disk *, 142static int setup_sparse_fiemap(struct archive_read_disk *,
143 struct archive_entry *, int *fd); 143 struct archive_entry *, int *fd);
144#endif 144#endif
145 145
146int 146int
147archive_read_disk_entry_from_file(struct archive *_a, 147archive_read_disk_entry_from_file(struct archive *_a,
148 struct archive_entry *entry, 148 struct archive_entry *entry,
149 int fd, 149 int fd,
150 const struct stat *st) 150 const struct stat *st)
151{ 151{
152 struct archive_read_disk *a = (struct archive_read_disk *)_a; 152 struct archive_read_disk *a = (struct archive_read_disk *)_a;
153 const char *path, *name; 153 const char *path, *name;
154 struct stat s; 154 struct stat s;
155 int initial_fd = fd; 155 int initial_fd = fd;
156 int r, r1; 156 int r, r1;
157 157
158 archive_clear_error(_a); 158 archive_clear_error(_a);
159 path = archive_entry_sourcepath(entry); 159 path = archive_entry_sourcepath(entry);
160 if (path == NULL) 160 if (path == NULL)
161 path = archive_entry_pathname(entry); 161 path = archive_entry_pathname(entry);
162 162
163 if (a->tree == NULL) { 163 if (a->tree == NULL) {
164 if (st == NULL) { 164 if (st == NULL) {
165#if HAVE_FSTAT 165#if HAVE_FSTAT
166 if (fd >= 0) { 166 if (fd >= 0) {
167 if (fstat(fd, &s) != 0) { 167 if (fstat(fd, &s) != 0) {
168 archive_set_error(&a->archive, errno, 168 archive_set_error(&a->archive, errno,
169 "Can't fstat"); 169 "Can't fstat");
170 return (ARCHIVE_FAILED); 170 return (ARCHIVE_FAILED);
171 } 171 }
172 } else 172 } else
173#endif 173#endif
174#if HAVE_LSTAT 174#if HAVE_LSTAT
175 if (!a->follow_symlinks) { 175 if (!a->follow_symlinks) {
176 if (lstat(path, &s) != 0) { 176 if (lstat(path, &s) != 0) {
177 archive_set_error(&a->archive, errno, 177 archive_set_error(&a->archive, errno,
178 "Can't lstat %s", path); 178 "Can't lstat %s", path);
179 return (ARCHIVE_FAILED); 179 return (ARCHIVE_FAILED);
180 } 180 }
181 } else 181 } else
182#endif 182#endif
183 if (stat(path, &s) != 0) { 183 if (stat(path, &s) != 0) {
184 archive_set_error(&a->archive, errno, 184 archive_set_error(&a->archive, errno,
185 "Can't stat %s", path); 185 "Can't stat %s", path);
186 return (ARCHIVE_FAILED); 186 return (ARCHIVE_FAILED);
187 } 187 }
188 st = &s; 188 st = &s;
189 } 189 }
190 archive_entry_copy_stat(entry, st); 190 archive_entry_copy_stat(entry, st);
191 } 191 }
192 192
193 /* Lookup uname/gname */ 193 /* Lookup uname/gname */
194 name = archive_read_disk_uname(_a, archive_entry_uid(entry)); 194 name = archive_read_disk_uname(_a, archive_entry_uid(entry));
195 if (name != NULL) 195 if (name != NULL)
196 archive_entry_copy_uname(entry, name); 196 archive_entry_copy_uname(entry, name);
197 name = archive_read_disk_gname(_a, archive_entry_gid(entry)); 197 name = archive_read_disk_gname(_a, archive_entry_gid(entry));
198 if (name != NULL) 198 if (name != NULL)
199 archive_entry_copy_gname(entry, name); 199 archive_entry_copy_gname(entry, name);
200 200
201#ifdef HAVE_STRUCT_STAT_ST_FLAGS 201#ifdef HAVE_STRUCT_STAT_ST_FLAGS
202 /* On FreeBSD, we get flags for free with the stat. */ 202 /* On FreeBSD, we get flags for free with the stat. */
203 /* TODO: Does this belong in copy_stat()? */ 203 /* TODO: Does this belong in copy_stat()? */
204 if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0) 204 if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
205 archive_entry_set_fflags(entry, st->st_flags, 0); 205 archive_entry_set_fflags(entry, st->st_flags, 0);
206#endif 206#endif
207 207
208#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \ 208#if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
209 (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)) 209 (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
210 /* Linux requires an extra ioctl to pull the flags. Although 210 /* Linux requires an extra ioctl to pull the flags. Although
211 * this is an extra step, it has a nice side-effect: We get an 211 * this is an extra step, it has a nice side-effect: We get an
212 * open file descriptor which we can use in the subsequent lookups. */ 212 * open file descriptor which we can use in the subsequent lookups. */
213 if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && 213 if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
214 (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) { 214 (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
215 if (fd < 0) { 215 if (fd < 0) {
216 if (a->tree != NULL) 216 if (a->tree != NULL)
217 fd = a->open_on_current_dir(a->tree, path, 217 fd = a->open_on_current_dir(a->tree, path,
218 O_RDONLY | O_NONBLOCK | O_CLOEXEC); 218 O_RDONLY | O_NONBLOCK | O_CLOEXEC);
219 else 219 else
220 fd = open(path, O_RDONLY | O_NONBLOCK | 220 fd = open(path, O_RDONLY | O_NONBLOCK |
221 O_CLOEXEC); 221 O_CLOEXEC);
222 __archive_ensure_cloexec_flag(fd); 222 __archive_ensure_cloexec_flag(fd);
223 } 223 }
224 if (fd >= 0) { 224 if (fd >= 0) {
225 int stflags; 225 int stflags;
226 r = ioctl(fd, 226 r = ioctl(fd,
227#if defined(FS_IOC_GETFLAGS) 227#if defined(FS_IOC_GETFLAGS)
228 FS_IOC_GETFLAGS, 228 FS_IOC_GETFLAGS,
229#else 229#else
230 EXT2_IOC_GETFLAGS, 230 EXT2_IOC_GETFLAGS,
231#endif 231#endif
232 &stflags); 232 &stflags);
233 if (r == 0 && stflags != 0) 233 if (r == 0 && stflags != 0)
234 archive_entry_set_fflags(entry, stflags, 0); 234 archive_entry_set_fflags(entry, stflags, 0);
235 } 235 }
236 } 236 }
237#endif 237#endif
238 238
239#if defined(HAVE_READLINK) || defined(HAVE_READLINKAT) 239#if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
240 if (S_ISLNK(st->st_mode)) { 240 if (S_ISLNK(st->st_mode)) {
241 size_t linkbuffer_len = st->st_size + 1; 241 size_t linkbuffer_len = st->st_size + 1;
242 char *linkbuffer; 242 char *linkbuffer;
243 int lnklen; 243 int lnklen;
244 244
245 linkbuffer = malloc(linkbuffer_len); 245 linkbuffer = malloc(linkbuffer_len);
246 if (linkbuffer == NULL) { 246 if (linkbuffer == NULL) {
247 archive_set_error(&a->archive, ENOMEM, 247 archive_set_error(&a->archive, ENOMEM,
248 "Couldn't read link data"); 248 "Couldn't read link data");
249 return (ARCHIVE_FAILED); 249 return (ARCHIVE_FAILED);
250 } 250 }
251 if (a->tree != NULL) { 251 if (a->tree != NULL) {
252#ifdef HAVE_READLINKAT 252#ifdef HAVE_READLINKAT
253 lnklen = readlinkat(a->tree_current_dir_fd(a->tree), 253 lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
254 path, linkbuffer, linkbuffer_len); 254 path, linkbuffer, linkbuffer_len);
255#else 255#else
256 if (a->tree_enter_working_dir(a->tree) != 0) { 256 if (a->tree_enter_working_dir(a->tree) != 0) {
257 archive_set_error(&a->archive, errno, 257 archive_set_error(&a->archive, errno,
258 "Couldn't read link data"); 258 "Couldn't read link data");
259 free(linkbuffer); 259 free(linkbuffer);
260 return (ARCHIVE_FAILED); 260 return (ARCHIVE_FAILED);
261 } 261 }
262 lnklen = readlink(path, linkbuffer, linkbuffer_len); 262 lnklen = readlink(path, linkbuffer, linkbuffer_len);
263#endif /* HAVE_READLINKAT */ 263#endif /* HAVE_READLINKAT */
264 } else 264 } else
265 lnklen = readlink(path, linkbuffer, linkbuffer_len); 265 lnklen = readlink(path, linkbuffer, linkbuffer_len);
266 if (lnklen < 0) { 266 if (lnklen < 0) {
267 archive_set_error(&a->archive, errno, 267 archive_set_error(&a->archive, errno,
268 "Couldn't read link data"); 268 "Couldn't read link data");
269 free(linkbuffer); 269 free(linkbuffer);
270 return (ARCHIVE_FAILED); 270 return (ARCHIVE_FAILED);
271 } 271 }
272 linkbuffer[lnklen] = 0; 272 linkbuffer[lnklen] = 0;
273 archive_entry_set_symlink(entry, linkbuffer); 273 archive_entry_set_symlink(entry, linkbuffer);
274 free(linkbuffer); 274 free(linkbuffer);
275 } 275 }
276#endif /* HAVE_READLINK || HAVE_READLINKAT */ 276#endif /* HAVE_READLINK || HAVE_READLINKAT */
277 277
278 r = 0; 278 r = 0;
279 if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0) 279 if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
280 r = setup_acls(a, entry, &fd); 280 r = setup_acls(a, entry, &fd);
281 if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) { 281 if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
282 r1 = setup_xattrs(a, entry, &fd); 282 r1 = setup_xattrs(a, entry, &fd);
283 if (r1 < r) 283 if (r1 < r)
284 r = r1; 284 r = r1;
285 } 285 }
286 if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) { 286 if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
287 r1 = setup_mac_metadata(a, entry, &fd); 287 r1 = setup_mac_metadata(a, entry, &fd);
288 if (r1 < r) 288 if (r1 < r)
289 r = r1; 289 r = r1;
290 } 290 }
291 r1 = setup_sparse(a, entry, &fd); 291 r1 = setup_sparse(a, entry, &fd);
292 if (r1 < r) 292 if (r1 < r)
293 r = r1; 293 r = r1;
294 294
295 /* If we opened the file earlier in this function, close it. */ 295 /* If we opened the file earlier in this function, close it. */
296 if (initial_fd != fd) 296 if (initial_fd != fd)
297 close(fd); 297 close(fd);
298 return (r); 298 return (r);
299} 299}
300 300
301#if defined(__APPLE__) && defined(HAVE_COPYFILE_H) 301#if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
302/* 302/*
303 * The Mac OS "copyfile()" API copies the extended metadata for a 303 * The Mac OS "copyfile()" API copies the extended metadata for a
304 * file into a separate file in AppleDouble format (see RFC 1740). 304 * file into a separate file in AppleDouble format (see RFC 1740).
305 * 305 *
306 * Mac OS tar and cpio implementations store this extended 306 * Mac OS tar and cpio implementations store this extended
307 * metadata as a separate entry just before the regular entry 307 * metadata as a separate entry just before the regular entry
308 * with a "._" prefix added to the filename. 308 * with a "._" prefix added to the filename.
309 * 309 *
310 * Note that this is currently done unconditionally; the tar program has 310 * Note that this is currently done unconditionally; the tar program has
311 * an option to discard this information before the archive is written. 311 * an option to discard this information before the archive is written.
312 * 312 *
313 * TODO: If there's a failure, report it and return ARCHIVE_WARN. 313 * TODO: If there's a failure, report it and return ARCHIVE_WARN.
314 */ 314 */
315static int 315static int
316setup_mac_metadata(struct archive_read_disk *a, 316setup_mac_metadata(struct archive_read_disk *a,
317 struct archive_entry *entry, int *fd) 317 struct archive_entry *entry, int *fd)
318{ 318{
319 int tempfd = -1; 319 int tempfd = -1;
320 int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR; 320 int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
321 struct stat copyfile_stat; 321 struct stat copyfile_stat;
322 int ret = ARCHIVE_OK; 322 int ret = ARCHIVE_OK;
323 void *buff = NULL; 323 void *buff = NULL;
324 int have_attrs; 324 int have_attrs;
325 const char *name, *tempdir; 325 const char *name, *tempdir;
326 struct archive_string tempfile; 326 struct archive_string tempfile;
327 327
328 (void)fd; /* UNUSED */ 328 (void)fd; /* UNUSED */
329 name = archive_entry_sourcepath(entry); 329 name = archive_entry_sourcepath(entry);
330 if (name == NULL) 330 if (name == NULL)
331 name = archive_entry_pathname(entry); 331 name = archive_entry_pathname(entry);
332 else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) { 332 else if (a->tree != NULL && a->tree_enter_working_dir(a->tree) != 0) {
333 archive_set_error(&a->archive, errno, 333 archive_set_error(&a->archive, errno,
334 "Can't change dir to read extended attributes"); 334 "Can't change dir to read extended attributes");
335 return (ARCHIVE_FAILED); 335 return (ARCHIVE_FAILED);
336 } 336 }
337 if (name == NULL) { 337 if (name == NULL) {
338 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 338 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
339 "Can't open file to read extended attributes: No name"); 339 "Can't open file to read extended attributes: No name");
340 return (ARCHIVE_WARN); 340 return (ARCHIVE_WARN);
341 } 341 }
342 342
343 /* Short-circuit if there's nothing to do. */ 343 /* Short-circuit if there's nothing to do. */
344 have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK); 344 have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
345 if (have_attrs == -1) { 345 if (have_attrs == -1) {
346 archive_set_error(&a->archive, errno, 346 archive_set_error(&a->archive, errno,
347 "Could not check extended attributes"); 347 "Could not check extended attributes");
348 return (ARCHIVE_WARN); 348 return (ARCHIVE_WARN);
349 } 349 }
350 if (have_attrs == 0) 350 if (have_attrs == 0)
351 return (ARCHIVE_OK); 351 return (ARCHIVE_OK);
352 352
353 tempdir = NULL; 353 tempdir = NULL;
354 if (issetugid() == 0) 354 if (issetugid() == 0)
355 tempdir = getenv("TMPDIR"); 355 tempdir = getenv("TMPDIR");
356 if (tempdir == NULL) 356 if (tempdir == NULL)
357 tempdir = _PATH_TMP; 357 tempdir = _PATH_TMP;
358 archive_string_init(&tempfile); 358 archive_string_init(&tempfile);
359 archive_strcpy(&tempfile, tempdir); 359 archive_strcpy(&tempfile, tempdir);
360 archive_strcat(&tempfile, "tar.md.XXXXXX"); 360 archive_strcat(&tempfile, "tar.md.XXXXXX");
361 tempfd = mkstemp(tempfile.s); 361 tempfd = mkstemp(tempfile.s);
362 if (tempfd < 0) { 362 if (tempfd < 0) {
363 archive_set_error(&a->archive, errno, 363 archive_set_error(&a->archive, errno,
364 "Could not open extended attribute file"); 364 "Could not open extended attribute file");
365 ret = ARCHIVE_WARN; 365 ret = ARCHIVE_WARN;
366 goto cleanup; 366 goto cleanup;
367 } 367 }
368 __archive_ensure_cloexec_flag(tempfd); 368 __archive_ensure_cloexec_flag(tempfd);
369 369
370 /* XXX I wish copyfile() could pack directly to a memory 370 /* XXX I wish copyfile() could pack directly to a memory
371 * buffer; that would avoid the temp file here. For that 371 * buffer; that would avoid the temp file here. For that
372 * matter, it would be nice if fcopyfile() actually worked, 372 * matter, it would be nice if fcopyfile() actually worked,
373 * that would reduce the many open/close races here. */ 373 * that would reduce the many open/close races here. */
374 if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) { 374 if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
375 archive_set_error(&a->archive, errno, 375 archive_set_error(&a->archive, errno,
376 "Could not pack extended attributes"); 376 "Could not pack extended attributes");
377 ret = ARCHIVE_WARN; 377 ret = ARCHIVE_WARN;
378 goto cleanup; 378 goto cleanup;
379 } 379 }
380 if (fstat(tempfd, &copyfile_stat)) { 380 if (fstat(tempfd, &copyfile_stat)) {
381 archive_set_error(&a->archive, errno, 381 archive_set_error(&a->archive, errno,
382 "Could not check size of extended attributes"); 382 "Could not check size of extended attributes");
383 ret = ARCHIVE_WARN; 383 ret = ARCHIVE_WARN;
384 goto cleanup; 384 goto cleanup;
385 } 385 }
386 buff = malloc(copyfile_stat.st_size); 386 buff = malloc(copyfile_stat.st_size);
387 if (buff == NULL) { 387 if (buff == NULL) {
388 archive_set_error(&a->archive, errno, 388 archive_set_error(&a->archive, errno,
389 "Could not allocate memory for extended attributes"); 389 "Could not allocate memory for extended attributes");
390 ret = ARCHIVE_WARN; 390 ret = ARCHIVE_WARN;
391 goto cleanup; 391 goto cleanup;
392 } 392 }
393 if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) { 393 if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
394 archive_set_error(&a->archive, errno, 394 archive_set_error(&a->archive, errno,
395 "Could not read extended attributes into memory"); 395 "Could not read extended attributes into memory");
396 ret = ARCHIVE_WARN; 396 ret = ARCHIVE_WARN;
397 goto cleanup; 397 goto cleanup;
398 } 398 }
399 archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size); 399 archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
400 400
401cleanup: 401cleanup:
402 if (tempfd >= 0) { 402 if (tempfd >= 0) {
403 close(tempfd); 403 close(tempfd);
404 unlink(tempfile.s); 404 unlink(tempfile.s);
405 } 405 }
406 archive_string_free(&tempfile); 406 archive_string_free(&tempfile);
407 free(buff); 407 free(buff);
408 return (ret); 408 return (ret);
409} 409}
410 410
411#else 411#else
412 412
413/* 413/*
414 * Stub implementation for non-Mac systems. 414 * Stub implementation for non-Mac systems.
415 */ 415 */
416static int 416static int
417setup_mac_metadata(struct archive_read_disk *a, 417setup_mac_metadata(struct archive_read_disk *a,
418 struct archive_entry *entry, int *fd) 418 struct archive_entry *entry, int *fd)
419{ 419{
420 (void)a; /* UNUSED */ 420 (void)a; /* UNUSED */
421 (void)entry; /* UNUSED */ 421 (void)entry; /* UNUSED */
422 (void)fd; /* UNUSED */ 422 (void)fd; /* UNUSED */
423 return (ARCHIVE_OK); 423 return (ARCHIVE_OK);
424} 424}
425#endif 425#endif
426 426
427#if HAVE_DARWIN_ACL 427#if HAVE_DARWIN_ACL
428static int translate_guid(struct archive *, acl_entry_t, 428static int translate_guid(struct archive *, acl_entry_t,
429 int *, int *, const char **); 429 int *, int *, const char **);
430 430
431static void add_trivial_nfs4_acl(struct archive_entry *); 431static void add_trivial_nfs4_acl(struct archive_entry *);
432#endif 432#endif
433 433
434#if HAVE_SUN_ACL 434#if HAVE_SUN_ACL
435static int 435static int
436sun_acl_is_trivial(void *, int, mode_t, int, int, int *); 436sun_acl_is_trivial(void *, int, mode_t, int, int, int *);
437 437
438static void * 438static void *
439sunacl_get(int cmd, int *aclcnt, int fd, const char *path) 439sunacl_get(int cmd, int *aclcnt, int fd, const char *path)
440{ 440{
441 int cnt, cntcmd; 441 int cnt, cntcmd;
442 size_t size; 442 size_t size;
443 void *aclp; 443 void *aclp;
444 444
445 if (cmd == GETACL) { 445 if (cmd == GETACL) {
446 cntcmd = GETACLCNT; 446 cntcmd = GETACLCNT;
447 size = sizeof(aclent_t); 447 size = sizeof(aclent_t);
448 } 448 }
449#if HAVE_SUN_NFS4_ACL 449#if HAVE_SUN_NFS4_ACL
450 else if (cmd == ACE_GETACL) { 450 else if (cmd == ACE_GETACL) {
451 cntcmd = ACE_GETACLCNT; 451 cntcmd = ACE_GETACLCNT;
452 size = sizeof(ace_t); 452 size = sizeof(ace_t);
453 } 453 }
454#endif 454#endif
455 else { 455 else {
456 errno = EINVAL; 456 errno = EINVAL;
457 *aclcnt = -1; 457 *aclcnt = -1;
458 return (NULL); 458 return (NULL);
459 } 459 }
460 460
461 aclp = NULL; 461 aclp = NULL;
462 cnt = -2; 462 cnt = -2;
463 463
464 while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) { 464 while (cnt == -2 || (cnt == -1 && errno == ENOSPC)) {
465 if (path != NULL) 465 if (path != NULL)
466 cnt = acl(path, cntcmd, 0, NULL); 466 cnt = acl(path, cntcmd, 0, NULL);
467 else 467 else
468 cnt = facl(fd, cntcmd, 0, NULL); 468 cnt = facl(fd, cntcmd, 0, NULL);
469 469
470 if (cnt > 0) { 470 if (cnt > 0) {
471 if (aclp == NULL) 471 if (aclp == NULL)
472 aclp = malloc(cnt * size); 472 aclp = malloc(cnt * size);
473 else 473 else
474 aclp = realloc(NULL, cnt * size); 474 aclp = realloc(NULL, cnt * size);
475 if (aclp != NULL) { 475 if (aclp != NULL) {
476 if (path != NULL) 476 if (path != NULL)
477 cnt = acl(path, cmd, cnt, aclp); 477 cnt = acl(path, cmd, cnt, aclp);
478 else 478 else
479 cnt = facl(fd, cmd, cnt, aclp); 479 cnt = facl(fd, cmd, cnt, aclp);
480 } 480 }
481 } else { 481 } else {
482 if (aclp != NULL) { 482 if (aclp != NULL) {
483 free(aclp); 483 free(aclp);
484 aclp = NULL; 484 aclp = NULL;
485 } 485 }
486 break; 486 break;
487 } 487 }
488 } 488 }
489 489
490 *aclcnt = cnt; 490 *aclcnt = cnt;
491 return (aclp); 491 return (aclp);
492} 492}
493#endif /* HAVE_SUN_ACL */ 493#endif /* HAVE_SUN_ACL */
494 494
495#if HAVE_POSIX_ACL || HAVE_NFS4_ACL 495#if HAVE_POSIX_ACL || HAVE_NFS4_ACL
496static int translate_acl(struct archive_read_disk *a, 496static int translate_acl(struct archive_read_disk *a,
497 struct archive_entry *entry, 497 struct archive_entry *entry,
498#if HAVE_SUN_ACL 498#if HAVE_SUN_ACL
499 void *acl, 499 void *aclp,
500 int aclcnt, 500 int aclcnt,
501#else 501#else
502 acl_t acl, 502 acl_t acl,
503#endif 503#endif
504 int archive_entry_acl_type); 504 int archive_entry_acl_type);
505 505
506static int 506static int
507setup_acls(struct archive_read_disk *a, 507setup_acls(struct archive_read_disk *a,
508 struct archive_entry *entry, int *fd) 508 struct archive_entry *entry, int *fd)
509{ 509{
510 const char *accpath; 510 const char *accpath;
511#if HAVE_SUN_ACL 511#if HAVE_SUN_ACL
512 void *acl; 512 void *aclp;
513 int aclcnt; 513 int aclcnt;
514#else 514#else
515 acl_t acl; 515 acl_t acl;
516#endif 516#endif
517 int r; 517 int r;
518 518
519 accpath = NULL; 519 accpath = NULL;
520 520
521#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP 521#if HAVE_SUN_ACL || HAVE_DARWIN_ACL || HAVE_ACL_GET_FD_NP
522 if (*fd < 0) 522 if (*fd < 0)
523#else 523#else
524 /* For default ACLs on Linux we need reachable accpath */ 524 /* For default ACLs on Linux we need reachable accpath */
525 if (*fd < 0 || S_ISDIR(archive_entry_mode(entry))) 525 if (*fd < 0 || S_ISDIR(archive_entry_mode(entry)))
526#endif 526#endif
527 { 527 {
528 accpath = archive_entry_sourcepath(entry); 528 accpath = archive_entry_sourcepath(entry);
529 if (accpath == NULL || (a->tree != NULL && 529 if (accpath == NULL || (a->tree != NULL &&
530 a->tree_enter_working_dir(a->tree) != 0)) 530 a->tree_enter_working_dir(a->tree) != 0))
531 accpath = archive_entry_pathname(entry); 531 accpath = archive_entry_pathname(entry);
532 if (accpath == NULL) { 532 if (accpath == NULL) {
533 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 533 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
534 "Couldn't determine file path to read ACLs"); 534 "Couldn't determine file path to read ACLs");
535 return (ARCHIVE_WARN); 535 return (ARCHIVE_WARN);
536 } 536 }
537 if (a->tree != NULL && 537 if (a->tree != NULL &&
538#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP 538#if !HAVE_SUN_ACL && !HAVE_DARWIN_ACL && !HAVE_ACL_GET_FD_NP
539 *fd < 0 && 539 *fd < 0 &&
540#endif 540#endif
541 (a->follow_symlinks || 541 (a->follow_symlinks ||
542 archive_entry_filetype(entry) != AE_IFLNK)) { 542 archive_entry_filetype(entry) != AE_IFLNK)) {
543 *fd = a->open_on_current_dir(a->tree, 543 *fd = a->open_on_current_dir(a->tree,
544 accpath, O_RDONLY | O_NONBLOCK); 544 accpath, O_RDONLY | O_NONBLOCK);
545 } 545 }
546 } 546 }
547 547
548 archive_entry_acl_clear(entry); 548 archive_entry_acl_clear(entry);
549 549
 550#if HAVE_SUN_ACL
 551 aclp = NULL;
 552#else
550 acl = NULL; 553 acl = NULL;
 554#endif
551 555
552#if HAVE_NFS4_ACL 556#if HAVE_NFS4_ACL
553 /* Try NFSv4 ACL first. */ 557 /* Try NFSv4 ACL first. */
554 if (*fd >= 0) 558 if (*fd >= 0)
555#if HAVE_SUN_ACL 559#if HAVE_SUN_ACL
556 acl = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL); 560 aclp = sunacl_get(ACE_GETACL, &aclcnt, *fd, NULL);
557#elif HAVE_ACL_GET_FD_NP 561#elif HAVE_ACL_GET_FD_NP
558 acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); 562 acl = acl_get_fd_np(*fd, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
559#else 563#else
560 acl = acl_get_fd(*fd); 564 acl = acl_get_fd(*fd);
561#endif 565#endif
562#if HAVE_ACL_GET_LINK_NP 566#if HAVE_ACL_GET_LINK_NP
563 else if (!a->follow_symlinks) 567 else if (!a->follow_symlinks)
564 acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); 568 acl = acl_get_link_np(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
565#else 569#else
566 else if ((!a->follow_symlinks) 570 else if ((!a->follow_symlinks)
567 && (archive_entry_filetype(entry) == AE_IFLNK)) 571 && (archive_entry_filetype(entry) == AE_IFLNK))
568 /* We can't get the ACL of a symlink, so we assume it can't 572 /* We can't get the ACL of a symlink, so we assume it can't
569 have one. */ 573 have one. */
 574#if HAVE_SUN_ACL
 575 aclp = NULL;
 576#else
570 acl = NULL; 577 acl = NULL;
571#endif 578#endif
 579#endif /* !HAVE_ACL_GET_LINK_NP */
572 else 580 else
573#if HAVE_SUN_ACL 581#if HAVE_SUN_ACL
574 /* Solaris reads both POSIX.1e and NFSv4 ACLs here */ 582 /* Solaris reads both POSIX.1e and NFSv4 ACLs here */
575 acl = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath); 583 aclp = sunacl_get(ACE_GETACL, &aclcnt, 0, accpath);
576#else 584#else
577 acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4); 585 acl = acl_get_file(accpath, ARCHIVE_PLATFORM_ACL_TYPE_NFS4);
578#endif 586#endif
579 587
580 588
581#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL 
582 /* Ignore "trivial" ACLs that just mirror the file mode. */ 589 /* Ignore "trivial" ACLs that just mirror the file mode. */
583 if (acl != NULL) { 
584#if HAVE_SUN_ACL 590#if HAVE_SUN_ACL
585 if (sun_acl_is_trivial(acl, aclcnt, archive_entry_mode(entry), 591 if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
586 1, S_ISDIR(archive_entry_mode(entry)), &r) == 0 && r == 1) 592 archive_entry_mode(entry), 1, S_ISDIR(archive_entry_mode(entry)),
 593 &r) == 0 && r == 1) {
 594 free(aclp);
 595 aclp = NULL;
 596 return (ARCHIVE_OK);
 597 }
587#elif HAVE_ACL_IS_TRIVIAL_NP 598#elif HAVE_ACL_IS_TRIVIAL_NP
588 if (acl_is_trivial_np(acl, &r) == 0 && r == 1) 599 if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
 600 acl_free(acl);
 601 acl = NULL;
 602 return (ARCHIVE_OK);
 603 }
589#endif 604#endif
590 { 605
591#if HAVE_SUN_ACL 606#if HAVE_SUN_ACL
592 free(acl); 607 if (aclp != NULL)
593#else 608#else
594 acl_free(acl); 609 if (acl != NULL)
595#endif 610#endif
596 acl = NULL; 611 {
597 /* 612 r = translate_acl(a, entry,
598 * Simultaneous NFSv4 and POSIX.1e ACLs for the same 
599 * entry are not allowed, so we should return here 
600 */ 
601 return (ARCHIVE_OK); 
602 } 
603 } 
604#endif /* HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL */ 
605 if (acl != NULL) { 
606 r = translate_acl(a, entry, acl, 
607#if HAVE_SUN_ACL 613#if HAVE_SUN_ACL
608 aclcnt, 614 aclp, aclcnt,
 615#else
 616 acl,
609#endif 617#endif
610 ARCHIVE_ENTRY_ACL_TYPE_NFS4); 618 ARCHIVE_ENTRY_ACL_TYPE_NFS4);
611#if HAVE_SUN_ACL 619#if HAVE_SUN_ACL
612 free(acl); 620 free(aclp);
 621 aclp = NULL;
613#else 622#else
614 acl_free(acl); 623 acl_free(acl);
 624 acl = NULL;
615#endif 625#endif
 626
616 if (r != ARCHIVE_OK) { 627 if (r != ARCHIVE_OK) {
617 archive_set_error(&a->archive, errno, 628 archive_set_error(&a->archive, errno,
618 "Couldn't translate NFSv4 ACLs"); 629 "Couldn't translate NFSv4 ACLs");
619 } 630 }
620#if HAVE_DARWIN_ACL 631#if HAVE_DARWIN_ACL
621 /* 632 /*
622 * Because Mac OS doesn't support owner@, group@ and everyone@ 633 * Because Mac OS doesn't support owner@, group@ and everyone@
623 * ACLs we need to add NFSv4 ACLs mirroring the file mode to 634 * ACLs we need to add NFSv4 ACLs mirroring the file mode to
624 * the archive entry. Otherwise extraction on non-Mac platforms 635 * the archive entry. Otherwise extraction on non-Mac platforms
625 * would lead to an invalid file mode. 636 * would lead to an invalid file mode.
626 */ 637 */
627 if ((archive_entry_acl_types(entry) & 638 if ((archive_entry_acl_types(entry) &
628 ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0) 639 ARCHIVE_ENTRY_ACL_TYPE_NFS4) != 0)
629 add_trivial_nfs4_acl(entry); 640 add_trivial_nfs4_acl(entry);
630#endif 641#endif
631 return (r); 642 return (r);
632 } 643 }
633#endif /* HAVE_NFS4_ACL */ 644#endif /* HAVE_NFS4_ACL */
634 645
635#if HAVE_POSIX_ACL || HAVE_SUN_ACL 646#if HAVE_POSIX_ACL || HAVE_SUN_ACL
636 /* This code path is skipped on MacOS */ 647 /* This code path is skipped on MacOS */
637 648
638 /* Retrieve access ACL from file. */ 649 /* Retrieve access ACL from file. */
639 if (*fd >= 0) 650 if (*fd >= 0)
640#if HAVE_SUN_ACL 651#if HAVE_SUN_ACL
641 acl = sunacl_get(GETACL, &aclcnt, *fd, NULL); 652 aclp = sunacl_get(GETACL, &aclcnt, *fd, NULL);
642#else 653#else
643 acl = acl_get_fd(*fd); 654 acl = acl_get_fd(*fd);
644#endif 655#endif
645#if HAVE_ACL_GET_LINK_NP 656#if HAVE_ACL_GET_LINK_NP
646 else if (!a->follow_symlinks) 657 else if (!a->follow_symlinks)
647 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS); 658 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
648#else 659#else
649 else if ((!a->follow_symlinks) 660 else if ((!a->follow_symlinks)
650 && (archive_entry_filetype(entry) == AE_IFLNK)) 661 && (archive_entry_filetype(entry) == AE_IFLNK))
651 /* We can't get the ACL of a symlink, so we assume it can't 662 /* We can't get the ACL of a symlink, so we assume it can't
652 have one. */ 663 have one. */
 664#if HAVE_SUN_ACL
 665 aclp = NULL;
 666#else
653 acl = NULL; 667 acl = NULL;
654#endif 668#endif
 669#endif /* !HAVE_ACL_GET_LINK_NP */
655 else 670 else
656#if HAVE_SUN_ACL 671#if HAVE_SUN_ACL
657 acl = sunacl_get(GETACL, &aclcnt, 0, accpath); 672 aclp = sunacl_get(GETACL, &aclcnt, 0, accpath);
658#else 673#else
659 acl = acl_get_file(accpath, ACL_TYPE_ACCESS); 674 acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
660#endif 675#endif
661 676
662 677
663#if HAVE_ACL_IS_TRIVIAL_NP || HAVE_SUN_ACL 
664 /* Ignore "trivial" ACLs that just mirror the file mode. */ 678 /* Ignore "trivial" ACLs that just mirror the file mode. */
665 if (acl != NULL) { 
666#if HAVE_SUN_ACL 679#if HAVE_SUN_ACL
667 if (sun_acl_is_trivial(acl, aclcnt, archive_entry_mode(entry), 680 if (aclp != NULL && sun_acl_is_trivial(aclp, aclcnt,
668 0, S_ISDIR(archive_entry_mode(entry)), &r) == 0 && r == 1) 681 archive_entry_mode(entry), 0, S_ISDIR(archive_entry_mode(entry)),
669#else 682 &r) == 0 && r == 1) {
670 if (acl_is_trivial_np(acl, &r) == 0) 683 free(aclp);
 684 aclp = NULL;
 685 }
 686#elif HAVE_ACL_IS_TRIVIAL_NP
 687 if (acl != NULL && acl_is_trivial_np(acl, &r) == 0 && r == 1) {
 688 acl_free(acl);
 689 acl = NULL;
 690 }
671#endif 691#endif
672 { 692
673 if (r) { 
674#if HAVE_SUN_ACL 693#if HAVE_SUN_ACL
675 free(acl); 694 if (aclp != NULL)
676#else 695#else
677 acl_free(acl); 696 if (acl != NULL)
678#endif 697#endif
679 acl = NULL; 698 {
680 } 699 r = translate_acl(a, entry,
681 } 
682 } 
683#endif 
684 
685 if (acl != NULL) { 
686 r = translate_acl(a, entry, acl, 
687#if HAVE_SUN_ACL 700#if HAVE_SUN_ACL
688 aclcnt, 701 aclp, aclcnt,
 702#else
 703 acl,
689#endif 704#endif
690 ARCHIVE_ENTRY_ACL_TYPE_ACCESS); 705 ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
691#if HAVE_SUN_ACL 706#if HAVE_SUN_ACL
692 free(acl); 707 free(aclp);
 708 aclp = NULL;
693#else 709#else
694 acl_free(acl); 710 acl_free(acl);
695#endif 
696 acl = NULL; 711 acl = NULL;
 712#endif
 713
697 if (r != ARCHIVE_OK) { 714 if (r != ARCHIVE_OK) {
698 archive_set_error(&a->archive, errno, 715 archive_set_error(&a->archive, errno,
699 "Couldn't translate access ACLs"); 716 "Couldn't translate access ACLs");
700 return (r); 717 return (r);
701 } 718 }
702 } 719 }
703 720
704#if !HAVE_SUN_ACL 721#if !HAVE_SUN_ACL
705 /* Only directories can have default ACLs. */ 722 /* Only directories can have default ACLs. */
706 if (S_ISDIR(archive_entry_mode(entry))) { 723 if (S_ISDIR(archive_entry_mode(entry))) {
707#if HAVE_ACL_GET_FD_NP 724#if HAVE_ACL_GET_FD_NP
708 if (*fd >= 0) 725 if (*fd >= 0)
709 acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT); 726 acl = acl_get_fd_np(*fd, ACL_TYPE_DEFAULT);
710 else 727 else
711#endif 728#endif
712 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT); 729 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
713 if (acl != NULL) { 730 if (acl != NULL) {
714 r = translate_acl(a, entry, acl, 731 r = translate_acl(a, entry, acl,
715 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT); 732 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
716 acl_free(acl); 733 acl_free(acl);
717 if (r != ARCHIVE_OK) { 734 if (r != ARCHIVE_OK) {
718 archive_set_error(&a->archive, errno, 735 archive_set_error(&a->archive, errno,
719 "Couldn't translate default ACLs"); 736 "Couldn't translate default ACLs");
720 return (r); 737 return (r);
721 } 738 }
722 } 739 }
723 } 740 }
724#endif /* !HAVE_SUN_ACL */ 741#endif /* !HAVE_SUN_ACL */
725#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */ 742#endif /* HAVE_POSIX_ACL || HAVE_SUN_ACL */
726 return (ARCHIVE_OK); 743 return (ARCHIVE_OK);
727} 744}
728 745
729/* 746/*
730 * Translate system ACL permissions into libarchive internal structure 747 * Translate system ACL permissions into libarchive internal structure
731 */ 748 */
732static const struct { 749static const struct {
733 const int archive_perm; 750 const int archive_perm;
734 const int platform_perm; 751 const int platform_perm;
735} acl_perm_map[] = { 752} acl_perm_map[] = {
736#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */ 753#if HAVE_SUN_ACL /* Solaris NFSv4 ACL permissions */
737 {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE}, 754 {ARCHIVE_ENTRY_ACL_EXECUTE, ACE_EXECUTE},
738 {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA}, 755 {ARCHIVE_ENTRY_ACL_READ_DATA, ACE_READ_DATA},
739 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY}, 756 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACE_LIST_DIRECTORY},
740 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA}, 757 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACE_WRITE_DATA},
741 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE}, 758 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACE_ADD_FILE},
742 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA}, 759 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACE_APPEND_DATA},
743 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY}, 760 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACE_ADD_SUBDIRECTORY},
744 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS}, 761 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACE_READ_NAMED_ATTRS},
745 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS}, 762 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACE_WRITE_NAMED_ATTRS},
746 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD}, 763 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACE_DELETE_CHILD},
747 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES}, 764 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACE_READ_ATTRIBUTES},
748 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES}, 765 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACE_WRITE_ATTRIBUTES},
749 {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE}, 766 {ARCHIVE_ENTRY_ACL_DELETE, ACE_DELETE},
750 {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL}, 767 {ARCHIVE_ENTRY_ACL_READ_ACL, ACE_READ_ACL},
751 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL}, 768 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACE_WRITE_ACL},
752 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER}, 769 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACE_WRITE_OWNER},
753 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE} 770 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACE_SYNCHRONIZE}
754#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */ 771#elif HAVE_DARWIN_ACL /* MacOS ACL permissions */
755 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, 772 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
756 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, 773 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
757 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, 774 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
758 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, 775 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
759 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 776 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
760 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, 777 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
761 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, 778 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
762 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, 779 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
763 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, 780 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
764 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 781 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
765 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 782 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
766 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES}, 783 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_EXTATTRIBUTES},
767 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES}, 784 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_EXTATTRIBUTES},
768 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY}, 785 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_SECURITY},
769 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY}, 786 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_SECURITY},
770 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER}, 787 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_CHANGE_OWNER},
771#if HAVE_DECL_ACL_SYNCHRONIZE 788#if HAVE_DECL_ACL_SYNCHRONIZE
772 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} 789 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
773#endif 790#endif
774#else /* POSIX.1e ACL permissions */ 791#else /* POSIX.1e ACL permissions */
775 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE}, 792 {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
776 {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE}, 793 {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
777 {ARCHIVE_ENTRY_ACL_READ, ACL_READ}, 794 {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
778#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD NFSv4 ACL permissions */ 795#if HAVE_FREEBSD_NFS4_ACL /* FreeBSD NFSv4 ACL permissions */
779 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA}, 796 {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
780 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY}, 797 {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
781 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA}, 798 {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
782 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE}, 799 {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
783 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA}, 800 {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
784 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY}, 801 {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
785 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS}, 802 {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
786 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS}, 803 {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
787 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD}, 804 {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
788 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES}, 805 {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
789 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES}, 806 {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
790 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE}, 807 {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
791 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL}, 808 {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
792 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL}, 809 {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
793 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER}, 810 {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
794 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE} 811 {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
795#endif 812#endif
796#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */ 813#endif /* !HAVE_SUN_ACL && !HAVE_DARWIN_ACL */
797}; 814};
798 815
799#if HAVE_NFS4_ACL 816#if HAVE_NFS4_ACL
800/* 817/*
801 * Translate system NFSv4 inheritance flags into libarchive internal structure 818 * Translate system NFSv4 inheritance flags into libarchive internal structure
802 */ 819 */
803static const struct { 820static const struct {
804 const int archive_inherit; 821 const int archive_inherit;
805 const int platform_inherit; 822 const int platform_inherit;
806} acl_inherit_map[] = { 823} acl_inherit_map[] = {
807#if HAVE_SUN_NFS4_ACL /* Solaris ACL inheritance flags */ 824#if HAVE_SUN_NFS4_ACL /* Solaris ACL inheritance flags */
808 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE}, 825 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACE_FILE_INHERIT_ACE},
809 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE}, 826 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACE_DIRECTORY_INHERIT_ACE},
810 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE}, 827 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACE_NO_PROPAGATE_INHERIT_ACE},
811 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE}, 828 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACE_INHERIT_ONLY_ACE},
812 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG}, 829 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACE_SUCCESSFUL_ACCESS_ACE_FLAG},
813 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG}, 830 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACE_FAILED_ACCESS_ACE_FLAG},
814#ifdef ACE_INHERITED_ACE 831#ifdef ACE_INHERITED_ACE
815 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE} 832 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACE_INHERITED_ACE}
816#endif 833#endif
817#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */ 834#elif HAVE_DARWIN_ACL /* MacOS NFSv4 inheritance flags */
818 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}, 835 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED},
819 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, 836 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
820 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, 837 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
821 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT}, 838 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_LIMIT_INHERIT},
822 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT} 839 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_ONLY_INHERIT}
823#else /* FreeBSD NFSv4 ACL inheritance flags */ 840#else /* FreeBSD NFSv4 ACL inheritance flags */
824 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT}, 841 {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
825 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT}, 842 {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
826 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT}, 843 {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
827 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}, 844 {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY},
828 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS}, 845 {ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS, ACL_ENTRY_SUCCESSFUL_ACCESS},
829 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS}, 846 {ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS, ACL_ENTRY_FAILED_ACCESS},
830 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED} 847 {ARCHIVE_ENTRY_ACL_ENTRY_INHERITED, ACL_ENTRY_INHERITED}
831#endif /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */ 848#endif /* !HAVE_SUN_NFS4_ACL && !HAVE_DARWIN_ACL */
832}; 849};
833#endif /* HAVE_NFS4_ACL */ 850#endif /* HAVE_NFS4_ACL */
834 851
835#if HAVE_DARWIN_ACL 852#if HAVE_DARWIN_ACL
836static int translate_guid(struct archive *a, acl_entry_t acl_entry, 853static int translate_guid(struct archive *a, acl_entry_t acl_entry,
837 int *ae_id, int *ae_tag, const char **ae_name) 854 int *ae_id, int *ae_tag, const char **ae_name)
838{ 855{
839 void *q; 856 void *q;
840 uid_t ugid; 857 uid_t ugid;
841 int r, idtype; 858 int r, idtype;
842 struct passwd *pwd; 859 struct passwd *pwd;
843 struct group *grp; 860 struct group *grp;
844 861
845 q = acl_get_qualifier(acl_entry); 862 q = acl_get_qualifier(acl_entry);
846 if (q == NULL) 863 if (q == NULL)
847 return (1); 864 return (1);
848 r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype); 865 r = mbr_uuid_to_id((const unsigned char *)q, &ugid, &idtype);
849 if (r != 0) { 866 if (r != 0) {
850 acl_free(q); 867 acl_free(q);
851 return (1); 868 return (1);
852 } 869 }
853 if (idtype == ID_TYPE_UID) { 870 if (idtype == ID_TYPE_UID) {
854 *ae_tag = ARCHIVE_ENTRY_ACL_USER; 871 *ae_tag = ARCHIVE_ENTRY_ACL_USER;
855 pwd = getpwuuid(q); 872 pwd = getpwuuid(q);
856 if (pwd == NULL) { 873 if (pwd == NULL) {
857 *ae_id = ugid; 874 *ae_id = ugid;
858 *ae_name = NULL; 875 *ae_name = NULL;
859 } else { 876 } else {
860 *ae_id = pwd->pw_uid; 877 *ae_id = pwd->pw_uid;
861 *ae_name = archive_read_disk_uname(a, *ae_id); 878 *ae_name = archive_read_disk_uname(a, *ae_id);
862 } 879 }
863 } else if (idtype == ID_TYPE_GID) { 880 } else if (idtype == ID_TYPE_GID) {
864 *ae_tag = ARCHIVE_ENTRY_ACL_GROUP; 881 *ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
865 grp = getgruuid(q); 882 grp = getgruuid(q);
866 if (grp == NULL) { 883 if (grp == NULL) {
867 *ae_id = ugid; 884 *ae_id = ugid;
868 *ae_name = NULL; 885 *ae_name = NULL;
869 } else { 886 } else {
870 *ae_id = grp->gr_gid; 887 *ae_id = grp->gr_gid;
871 *ae_name = archive_read_disk_gname(a, *ae_id); 888 *ae_name = archive_read_disk_gname(a, *ae_id);
872 } 889 }
873 } else 890 } else
874 r = 1; 891 r = 1;
875 892
876 acl_free(q); 893 acl_free(q);
877 return (r); 894 return (r);
878} 895}
879 896
880/* 897/*
881 * Add trivial NFSv4 ACL entries from mode 898 * Add trivial NFSv4 ACL entries from mode
882 */ 899 */
883static void 900static void
884add_trivial_nfs4_acl(struct archive_entry *entry) 901add_trivial_nfs4_acl(struct archive_entry *entry)
885{ 902{
886 mode_t mode; 903 mode_t mode;
887 int i; 904 int i;
888 const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA; 905 const int rperm = ARCHIVE_ENTRY_ACL_READ_DATA;
889 const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA | 906 const int wperm = ARCHIVE_ENTRY_ACL_WRITE_DATA |
890 ARCHIVE_ENTRY_ACL_APPEND_DATA; 907 ARCHIVE_ENTRY_ACL_APPEND_DATA;
891 const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE; 908 const int eperm = ARCHIVE_ENTRY_ACL_EXECUTE;
892 const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES | 909 const int pubset = ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES |
893 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS | 910 ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS |
894 ARCHIVE_ENTRY_ACL_READ_ACL | 911 ARCHIVE_ENTRY_ACL_READ_ACL |
895 ARCHIVE_ENTRY_ACL_SYNCHRONIZE; 912 ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
896 const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES | 913 const int ownset = pubset | ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES |
897 ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS | 914 ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS |
898 ARCHIVE_ENTRY_ACL_WRITE_ACL | 915 ARCHIVE_ENTRY_ACL_WRITE_ACL |
899 ARCHIVE_ENTRY_ACL_WRITE_OWNER; 916 ARCHIVE_ENTRY_ACL_WRITE_OWNER;
900 917
901 struct { 918 struct {
902 const int type; 919 const int type;
903 const int tag; 920 const int tag;
904 int permset; 921 int permset;
905 } tacl_entry[] = { 922 } tacl_entry[] = {
906 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, 923 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
907 {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0}, 924 {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_USER_OBJ, 0},
908 {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0}, 925 {ARCHIVE_ENTRY_ACL_TYPE_DENY, ARCHIVE_ENTRY_ACL_GROUP_OBJ, 0},
909 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset}, 926 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_USER_OBJ, ownset},
910 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset}, 927 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_GROUP_OBJ, pubset},
911 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset} 928 {ARCHIVE_ENTRY_ACL_TYPE_ALLOW, ARCHIVE_ENTRY_ACL_EVERYONE, pubset}
912 }; 929 };
913 930
914 mode = archive_entry_mode(entry); 931 mode = archive_entry_mode(entry);
915 932
916 /* Permissions for everyone@ */ 933 /* Permissions for everyone@ */
917 if (mode & 0004) 934 if (mode & 0004)
918 tacl_entry[5].permset |= rperm; 935 tacl_entry[5].permset |= rperm;
919 if (mode & 0002) 936 if (mode & 0002)
920 tacl_entry[5].permset |= wperm; 937 tacl_entry[5].permset |= wperm;
921 if (mode & 0001) 938 if (mode & 0001)
922 tacl_entry[5].permset |= eperm; 939 tacl_entry[5].permset |= eperm;
923 940
924 /* Permissions for group@ */ 941 /* Permissions for group@ */
925 if (mode & 0040) 942 if (mode & 0040)
926 tacl_entry[4].permset |= rperm; 943 tacl_entry[4].permset |= rperm;
927 else if (mode & 0004) 944 else if (mode & 0004)
928 tacl_entry[2].permset |= rperm; 945 tacl_entry[2].permset |= rperm;
929 if (mode & 0020) 946 if (mode & 0020)
930 tacl_entry[4].permset |= wperm; 947 tacl_entry[4].permset |= wperm;
931 else if (mode & 0002) 948 else if (mode & 0002)
932 tacl_entry[2].permset |= wperm; 949 tacl_entry[2].permset |= wperm;
933 if (mode & 0010) 950 if (mode & 0010)
934 tacl_entry[4].permset |= eperm; 951 tacl_entry[4].permset |= eperm;
935 else if (mode & 0001) 952 else if (mode & 0001)
936 tacl_entry[2].permset |= eperm; 953 tacl_entry[2].permset |= eperm;
937 954
938 /* Permissions for owner@ */ 955 /* Permissions for owner@ */
939 if (mode & 0400) { 956 if (mode & 0400) {
940 tacl_entry[3].permset |= rperm; 957 tacl_entry[3].permset |= rperm;
941 if (!(mode & 0040) && (mode & 0004)) 958 if (!(mode & 0040) && (mode & 0004))
942 tacl_entry[0].permset |= rperm; 959 tacl_entry[0].permset |= rperm;
943 } else if ((mode & 0040) || (mode & 0004)) 960 } else if ((mode & 0040) || (mode & 0004))
944 tacl_entry[1].permset |= rperm; 961 tacl_entry[1].permset |= rperm;
945 if (mode & 0200) { 962 if (mode & 0200) {
946 tacl_entry[3].permset |= wperm; 963 tacl_entry[3].permset |= wperm;
947 if (!(mode & 0020) && (mode & 0002)) 964 if (!(mode & 0020) && (mode & 0002))
948 tacl_entry[0].permset |= wperm; 965 tacl_entry[0].permset |= wperm;
949 } else if ((mode & 0020) || (mode & 0002)) 966 } else if ((mode & 0020) || (mode & 0002))
950 tacl_entry[1].permset |= wperm; 967 tacl_entry[1].permset |= wperm;
951 if (mode & 0100) { 968 if (mode & 0100) {
952 tacl_entry[3].permset |= eperm; 969 tacl_entry[3].permset |= eperm;
953 if (!(mode & 0010) && (mode & 0001)) 970 if (!(mode & 0010) && (mode & 0001))
954 tacl_entry[0].permset |= eperm; 971 tacl_entry[0].permset |= eperm;
955 } else if ((mode & 0010) || (mode & 0001)) 972 } else if ((mode & 0010) || (mode & 0001))
956 tacl_entry[1].permset |= eperm; 973 tacl_entry[1].permset |= eperm;
957 974
958 for (i = 0; i < 6; i++) { 975 for (i = 0; i < 6; i++) {
959 if (tacl_entry[i].permset != 0) { 976 if (tacl_entry[i].permset != 0) {
960 archive_entry_acl_add_entry(entry, 977 archive_entry_acl_add_entry(entry,
961 tacl_entry[i].type, tacl_entry[i].permset, 978 tacl_entry[i].type, tacl_entry[i].permset,
962 tacl_entry[i].tag, -1, NULL); 979 tacl_entry[i].tag, -1, NULL);
963 } 980 }
964 } 981 }
965 982
966 return; 983 return;
967} 984}
968#elif HAVE_SUN_ACL 985#elif HAVE_SUN_ACL
969/* 986/*
970 * Check if acl is trivial 987 * Check if acl is trivial
971 * This is a FreeBSD acl_is_trivial_np() implementation for Solaris 988 * This is a FreeBSD acl_is_trivial_np() implementation for Solaris
972 */ 989 */
973static int 990static int
974sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4, 991sun_acl_is_trivial(void *aclp, int aclcnt, mode_t mode, int is_nfs4,
975 int is_dir, int *trivialp) 992 int is_dir, int *trivialp)
976{ 993{
977 int i, p; 994 int i, p;
978#if HAVE_SUN_NFS4_ACL 995#if HAVE_SUN_NFS4_ACL
979 const uint32_t rperm = ACE_READ_DATA; 996 const uint32_t rperm = ACE_READ_DATA;
980 const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA; 997 const uint32_t wperm = ACE_WRITE_DATA | ACE_APPEND_DATA;
981 const uint32_t eperm = ACE_EXECUTE; 998 const uint32_t eperm = ACE_EXECUTE;
982 const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS | 999 const uint32_t pubset = ACE_READ_ATTRIBUTES | ACE_READ_NAMED_ATTRS |
983 ACE_READ_ACL | ACE_SYNCHRONIZE; 1000 ACE_READ_ACL | ACE_SYNCHRONIZE;
984 const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES | 1001 const uint32_t ownset = pubset | ACE_WRITE_ATTRIBUTES |
985 ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER; 1002 ACE_WRITE_NAMED_ATTRS | ACE_WRITE_ACL | ACE_WRITE_OWNER;
986 1003
987 ace_t *ace; 1004 ace_t *ace;
988 ace_t tace[6]; 1005 ace_t tace[6];
989#endif 1006#endif
990 1007
991 if (aclp == NULL || trivialp == NULL) 1008 if (aclp == NULL || trivialp == NULL)
992 return (-1); 1009 return (-1);
993 1010
994 *trivialp = 0; 1011 *trivialp = 0;
995 1012
996 /* 1013 /*
997 * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with 1014 * POSIX.1e ACLs marked with ACL_IS_TRIVIAL are compatible with
998 * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries, 1015 * FreeBSD acl_is_trivial_np(). On Solaris they have 4 entries,
999 * including mask. 1016 * including mask.
1000 */ 1017 */
1001 if (!is_nfs4) { 1018 if (!is_nfs4) {
1002 if (aclcnt == 4) 1019 if (aclcnt == 4)
1003 *trivialp = 1; 1020 *trivialp = 1;
1004 return (0); 1021 return (0);
1005 } 1022 }
1006 1023
1007#if HAVE_SUN_NFS4_ACL 1024#if HAVE_SUN_NFS4_ACL
1008 /* 1025 /*
1009 * Continue with checking NFSv4 ACLs 1026 * Continue with checking NFSv4 ACLs
1010 * 1027 *
1011 * Create list of trivial ace's to be compared 1028 * Create list of trivial ace's to be compared
1012 */ 1029 */
1013 1030
1014 /* owner@ allow pre */ 1031 /* owner@ allow pre */
1015 tace[0].a_flags = ACE_OWNER; 1032 tace[0].a_flags = ACE_OWNER;
1016 tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1033 tace[0].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1017 tace[0].a_access_mask = 0; 1034 tace[0].a_access_mask = 0;
1018 1035
1019 /* owner@ deny */ 1036 /* owner@ deny */
1020 tace[1].a_flags = ACE_OWNER; 1037 tace[1].a_flags = ACE_OWNER;
1021 tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE; 1038 tace[1].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
1022 tace[1].a_access_mask = 0; 1039 tace[1].a_access_mask = 0;
1023 1040
1024 /* group@ deny */ 1041 /* group@ deny */
1025 tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; 1042 tace[2].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
1026 tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE; 1043 tace[2].a_type = ACE_ACCESS_DENIED_ACE_TYPE;
1027 tace[2].a_access_mask = 0; 1044 tace[2].a_access_mask = 0;
1028 1045
1029 /* owner@ allow */ 1046 /* owner@ allow */
1030 tace[3].a_flags = ACE_OWNER; 1047 tace[3].a_flags = ACE_OWNER;
1031 tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1048 tace[3].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1032 tace[3].a_access_mask = ownset; 1049 tace[3].a_access_mask = ownset;
1033 1050
1034 /* group@ allow */ 1051 /* group@ allow */
1035 tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP; 1052 tace[4].a_flags = ACE_GROUP | ACE_IDENTIFIER_GROUP;
1036 tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1053 tace[4].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1037 tace[4].a_access_mask = pubset; 1054 tace[4].a_access_mask = pubset;
1038 1055
1039 /* everyone@ allow */ 1056 /* everyone@ allow */
1040 tace[5].a_flags = ACE_EVERYONE; 1057 tace[5].a_flags = ACE_EVERYONE;
1041 tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE; 1058 tace[5].a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
1042 tace[5].a_access_mask = pubset; 1059 tace[5].a_access_mask = pubset;
1043 1060
1044 /* Permissions for everyone@ */ 1061 /* Permissions for everyone@ */
1045 if (mode & 0004) 1062 if (mode & 0004)
1046 tace[5].a_access_mask |= rperm; 1063 tace[5].a_access_mask |= rperm;
1047 if (mode & 0002) 1064 if (mode & 0002)
1048 tace[5].a_access_mask |= wperm; 1065 tace[5].a_access_mask |= wperm;
1049 if (mode & 0001) 1066 if (mode & 0001)
1050 tace[5].a_access_mask |= eperm; 1067 tace[5].a_access_mask |= eperm;
1051 1068
1052 /* Permissions for group@ */ 1069 /* Permissions for group@ */
1053 if (mode & 0040) 1070 if (mode & 0040)
1054 tace[4].a_access_mask |= rperm; 1071 tace[4].a_access_mask |= rperm;
1055 else if (mode & 0004) 1072 else if (mode & 0004)
1056 tace[2].a_access_mask |= rperm; 1073 tace[2].a_access_mask |= rperm;
1057 if (mode & 0020) 1074 if (mode & 0020)
1058 tace[4].a_access_mask |= wperm; 1075 tace[4].a_access_mask |= wperm;
1059 else if (mode & 0002) 1076 else if (mode & 0002)
1060 tace[2].a_access_mask |= wperm; 1077 tace[2].a_access_mask |= wperm;
1061 if (mode & 0010) 1078 if (mode & 0010)
1062 tace[4].a_access_mask |= eperm; 1079 tace[4].a_access_mask |= eperm;
1063 else if (mode & 0001) 1080 else if (mode & 0001)
1064 tace[2].a_access_mask |= eperm; 1081 tace[2].a_access_mask |= eperm;
1065 1082
1066 /* Permissions for owner@ */ 1083 /* Permissions for owner@ */
1067 if (mode & 0400) { 1084 if (mode & 0400) {
1068 tace[3].a_access_mask |= rperm; 1085 tace[3].a_access_mask |= rperm;
1069 if (!(mode & 0040) && (mode & 0004)) 1086 if (!(mode & 0040) && (mode & 0004))
1070 tace[0].a_access_mask |= rperm; 1087 tace[0].a_access_mask |= rperm;
1071 } else if ((mode & 0040) || (mode & 0004)) 1088 } else if ((mode & 0040) || (mode & 0004))
1072 tace[1].a_access_mask |= rperm; 1089 tace[1].a_access_mask |= rperm;
1073 if (mode & 0200) { 1090 if (mode & 0200) {
1074 tace[3].a_access_mask |= wperm; 1091 tace[3].a_access_mask |= wperm;
1075 if (!(mode & 0020) && (mode & 0002)) 1092 if (!(mode & 0020) && (mode & 0002))
1076 tace[0].a_access_mask |= wperm; 1093 tace[0].a_access_mask |= wperm;
1077 } else if ((mode & 0020) || (mode & 0002)) 1094 } else if ((mode & 0020) || (mode & 0002))
1078 tace[1].a_access_mask |= wperm; 1095 tace[1].a_access_mask |= wperm;
1079 if (mode & 0100) { 1096 if (mode & 0100) {
1080 tace[3].a_access_mask |= eperm; 1097 tace[3].a_access_mask |= eperm;
1081 if (!(mode & 0010) && (mode & 0001)) 1098 if (!(mode & 0010) && (mode & 0001))
1082 tace[0].a_access_mask |= eperm; 1099 tace[0].a_access_mask |= eperm;
1083 } else if ((mode & 0010) || (mode & 0001)) 1100 } else if ((mode & 0010) || (mode & 0001))
1084 tace[1].a_access_mask |= eperm; 1101 tace[1].a_access_mask |= eperm;
1085 1102
1086 /* Check if the acl count matches */ 1103 /* Check if the acl count matches */
1087 p = 3; 1104 p = 3;
1088 for (i = 0; i < 3; i++) { 1105 for (i = 0; i < 3; i++) {
1089 if (tace[i].a_access_mask != 0) 1106 if (tace[i].a_access_mask != 0)
1090 p++; 1107 p++;
1091 } 1108 }
1092 if (aclcnt != p) 1109 if (aclcnt != p)
1093 return (0); 1110 return (0);
1094 1111
1095 p = 0; 1112 p = 0;
1096 for (i = 0; i < 6; i++) { 1113 for (i = 0; i < 6; i++) {
1097 if (tace[i].a_access_mask != 0) { 1114 if (tace[i].a_access_mask != 0) {
1098 ace = &((ace_t *)aclp)[p]; 1115 ace = &((ace_t *)aclp)[p];
1099 /* 1116 /*
1100 * Illumos added ACE_DELETE_CHILD to write perms for 1117 * Illumos added ACE_DELETE_CHILD to write perms for
1101 * directories. We have to check against that, too. 1118 * directories. We have to check against that, too.
1102 */ 1119 */
1103 if (ace->a_flags != tace[i].a_flags || 1120 if (ace->a_flags != tace[i].a_flags ||
1104 ace->a_type != tace[i].a_type || 1121 ace->a_type != tace[i].a_type ||
1105 (ace->a_access_mask != tace[i].a_access_mask && 1122 (ace->a_access_mask != tace[i].a_access_mask &&
1106 (!is_dir || (tace[i].a_access_mask & wperm) == 0 || 1123 (!is_dir || (tace[i].a_access_mask & wperm) == 0 ||
1107 ace->a_access_mask != 1124 ace->a_access_mask !=
1108 (tace[i].a_access_mask | ACE_DELETE_CHILD)))) 1125 (tace[i].a_access_mask | ACE_DELETE_CHILD))))
1109 return (0); 1126 return (0);
1110 p++; 1127 p++;
1111 } 1128 }
1112 } 1129 }
1113 1130
1114 *trivialp = 1; 1131 *trivialp = 1;
1115#else /* !HAVE_SUN_NFS4_ACL */ 1132#else /* !HAVE_SUN_NFS4_ACL */
1116 (void)aclp; /* UNUSED */ 1133 (void)aclp; /* UNUSED */
1117#endif /* !HAVE_SUN_NFS4_ACL */ 1134#endif /* !HAVE_SUN_NFS4_ACL */
1118 return (0); 1135 return (0);
1119} 1136}
1120#endif /* HAVE_SUN_ACL */ 1137#endif /* HAVE_SUN_ACL */
1121 1138
1122#if HAVE_SUN_ACL 1139#if HAVE_SUN_ACL
1123/* 1140/*
1124 * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL 1141 * Translate Solaris POSIX.1e and NFSv4 ACLs into libarchive internal ACL
1125 */ 1142 */
1126static int 1143static int
1127translate_acl(struct archive_read_disk *a, 1144translate_acl(struct archive_read_disk *a,
1128 struct archive_entry *entry, void *aclp, int aclcnt, 1145 struct archive_entry *entry, void *aclp, int aclcnt,
1129 int default_entry_acl_type) 1146 int default_entry_acl_type)
1130{ 1147{
1131 int e, i; 1148 int e, i;
1132 int ae_id, ae_tag, ae_perm; 1149 int ae_id, ae_tag, ae_perm;
1133 int entry_acl_type; 1150 int entry_acl_type;
1134 const char *ae_name; 1151 const char *ae_name;
1135 aclent_t *aclent; 1152 aclent_t *aclent;
1136#if HAVE_SUN_NFS4_ACL 1153#if HAVE_SUN_NFS4_ACL
1137 ace_t *ace; 1154 ace_t *ace;
1138#endif 1155#endif
1139 1156
1140 if (aclcnt <= 0) 1157 if (aclcnt <= 0)
1141 return (ARCHIVE_OK); 1158 return (ARCHIVE_OK);
1142 1159
1143 for (e = 0; e < aclcnt; e++) { 1160 for (e = 0; e < aclcnt; e++) {
1144 ae_name = NULL; 1161 ae_name = NULL;
1145 ae_tag = 0; 1162 ae_tag = 0;
1146 ae_perm = 0; 1163 ae_perm = 0;
1147 1164
1148#if HAVE_SUN_NFS4_ACL 1165#if HAVE_SUN_NFS4_ACL
1149 if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 1166 if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
1150 ace = &((ace_t *)aclp)[e]; 1167 ace = &((ace_t *)aclp)[e];
1151 ae_id = ace->a_who; 1168 ae_id = ace->a_who;
1152 1169
1153 switch(ace->a_type) { 1170 switch(ace->a_type) {
1154 case ACE_ACCESS_ALLOWED_ACE_TYPE: 1171 case ACE_ACCESS_ALLOWED_ACE_TYPE:
1155 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; 1172 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
1156 break; 1173 break;
1157 case ACE_ACCESS_DENIED_ACE_TYPE: 1174 case ACE_ACCESS_DENIED_ACE_TYPE:
1158 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; 1175 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
1159 break; 1176 break;
1160 case ACE_SYSTEM_AUDIT_ACE_TYPE: 1177 case ACE_SYSTEM_AUDIT_ACE_TYPE:
1161 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; 1178 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
1162 break; 1179 break;
1163 case ACE_SYSTEM_ALARM_ACE_TYPE: 1180 case ACE_SYSTEM_ALARM_ACE_TYPE:
1164 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; 1181 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
1165 break; 1182 break;
1166 default: 1183 default:
1167 /* Unknown entry type, skip */ 1184 /* Unknown entry type, skip */
1168 continue; 1185 continue;
1169 } 1186 }
1170 1187
1171 if ((ace->a_flags & ACE_OWNER) != 0) 1188 if ((ace->a_flags & ACE_OWNER) != 0)
1172 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; 1189 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
1173 else if ((ace->a_flags & ACE_GROUP) != 0) 1190 else if ((ace->a_flags & ACE_GROUP) != 0)
1174 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; 1191 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
1175 else if ((ace->a_flags & ACE_EVERYONE) != 0) 1192 else if ((ace->a_flags & ACE_EVERYONE) != 0)
1176 ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; 1193 ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
1177 else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) { 1194 else if ((ace->a_flags & ACE_IDENTIFIER_GROUP) != 0) {
1178 ae_tag = ARCHIVE_ENTRY_ACL_GROUP; 1195 ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
1179 ae_name = archive_read_disk_gname(&a->archive, 1196 ae_name = archive_read_disk_gname(&a->archive,
1180 ae_id); 1197 ae_id);
1181 } else { 1198 } else {
1182 ae_tag = ARCHIVE_ENTRY_ACL_USER; 1199 ae_tag = ARCHIVE_ENTRY_ACL_USER;
1183 ae_name = archive_read_disk_uname(&a->archive, 1200 ae_name = archive_read_disk_uname(&a->archive,
1184 ae_id); 1201 ae_id);
1185 } 1202 }
1186 1203
1187 for (i = 0; i < (int)(sizeof(acl_inherit_map) / 1204 for (i = 0; i < (int)(sizeof(acl_inherit_map) /
1188 sizeof(acl_inherit_map[0])); ++i) { 1205 sizeof(acl_inherit_map[0])); ++i) {
1189 if ((ace->a_flags & 1206 if ((ace->a_flags &
1190 acl_inherit_map[i].platform_inherit) != 0) 1207 acl_inherit_map[i].platform_inherit) != 0)
1191 ae_perm |= 1208 ae_perm |=
1192 acl_inherit_map[i].archive_inherit; 1209 acl_inherit_map[i].archive_inherit;
1193 } 1210 }
1194 1211
1195 for (i = 0; i < (int)(sizeof(acl_perm_map) / 1212 for (i = 0; i < (int)(sizeof(acl_perm_map) /
1196 sizeof(acl_perm_map[0])); ++i) { 1213 sizeof(acl_perm_map[0])); ++i) {
1197 if ((ace->a_access_mask & 1214 if ((ace->a_access_mask &
1198 acl_perm_map[i].platform_perm) != 0) 1215 acl_perm_map[i].platform_perm) != 0)
1199 ae_perm |= 1216 ae_perm |=
1200 acl_perm_map[i].archive_perm; 1217 acl_perm_map[i].archive_perm;
1201 } 1218 }
1202 } else 1219 } else
1203#endif /* HAVE_SUN_NFS4_ACL */ 1220#endif /* HAVE_SUN_NFS4_ACL */
1204 if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) { 1221 if (default_entry_acl_type == ARCHIVE_ENTRY_ACL_TYPE_ACCESS) {
1205 aclent = &((aclent_t *)aclp)[e]; 1222 aclent = &((aclent_t *)aclp)[e];
1206 if ((aclent->a_type & ACL_DEFAULT) != 0) 1223 if ((aclent->a_type & ACL_DEFAULT) != 0)
1207 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT; 1224 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DEFAULT;
1208 else 1225 else
1209 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS; 1226 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ACCESS;
1210 ae_id = aclent->a_id; 1227 ae_id = aclent->a_id;
1211 1228
1212 switch(aclent->a_type) { 1229 switch(aclent->a_type) {
1213 case DEF_USER: 1230 case DEF_USER:
1214 case USER: 1231 case USER:
1215 ae_name = archive_read_disk_uname(&a->archive, 1232 ae_name = archive_read_disk_uname(&a->archive,
1216 ae_id); 1233 ae_id);
1217 ae_tag = ARCHIVE_ENTRY_ACL_USER; 1234 ae_tag = ARCHIVE_ENTRY_ACL_USER;
1218 break; 1235 break;
1219 case DEF_GROUP: 1236 case DEF_GROUP:
1220 case GROUP: 1237 case GROUP:
1221 ae_name = archive_read_disk_gname(&a->archive, 1238 ae_name = archive_read_disk_gname(&a->archive,
1222 ae_id); 1239 ae_id);
1223 ae_tag = ARCHIVE_ENTRY_ACL_GROUP; 1240 ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
1224 break; 1241 break;
1225 case DEF_CLASS_OBJ: 1242 case DEF_CLASS_OBJ:
1226 case CLASS_OBJ: 1243 case CLASS_OBJ:
1227 ae_tag = ARCHIVE_ENTRY_ACL_MASK; 1244 ae_tag = ARCHIVE_ENTRY_ACL_MASK;
1228 break; 1245 break;
1229 case DEF_USER_OBJ: 1246 case DEF_USER_OBJ:
1230 case USER_OBJ: 1247 case USER_OBJ:
1231 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; 1248 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
1232 break; 1249 break;
1233 case DEF_GROUP_OBJ: 1250 case DEF_GROUP_OBJ:
1234 case GROUP_OBJ: 1251 case GROUP_OBJ:
1235 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; 1252 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
1236 break; 1253 break;
1237 case DEF_OTHER_OBJ: 1254 case DEF_OTHER_OBJ:
1238 case OTHER_OBJ: 1255 case OTHER_OBJ:
1239 ae_tag = ARCHIVE_ENTRY_ACL_OTHER; 1256 ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
1240 break; 1257 break;
1241 default: 1258 default:
1242 /* Unknown tag type, skip */ 1259 /* Unknown tag type, skip */
1243 continue; 1260 continue;
1244 } 1261 }
1245 1262
1246 if ((aclent->a_perm & 1) != 0) 1263 if ((aclent->a_perm & 1) != 0)
1247 ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; 1264 ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
1248 if ((aclent->a_perm & 2) != 0) 1265 if ((aclent->a_perm & 2) != 0)
1249 ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; 1266 ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
1250 if ((aclent->a_perm & 4) != 0) 1267 if ((aclent->a_perm & 4) != 0)
1251 ae_perm |= ARCHIVE_ENTRY_ACL_READ; 1268 ae_perm |= ARCHIVE_ENTRY_ACL_READ;
1252 } else 1269 } else
1253 return (ARCHIVE_WARN); 1270 return (ARCHIVE_WARN);
1254 1271
1255 archive_entry_acl_add_entry(entry, entry_acl_type, 1272 archive_entry_acl_add_entry(entry, entry_acl_type,
1256 ae_perm, ae_tag, ae_id, ae_name); 1273 ae_perm, ae_tag, ae_id, ae_name);
1257 } 1274 }
1258 return (ARCHIVE_OK); 1275 return (ARCHIVE_OK);
1259} 1276}
1260#else /* !HAVE_SUN_ACL */ 1277#else /* !HAVE_SUN_ACL */
1261/* 1278/*
1262 * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and 1279 * Translate POSIX.1e (Linux), FreeBSD (both POSIX.1e and NFSv4) and
1263 * MacOS (NFSv4 only) ACLs into libarchive internal structure 1280 * MacOS (NFSv4 only) ACLs into libarchive internal structure
1264 */ 1281 */
1265static int 1282static int
1266translate_acl(struct archive_read_disk *a, 1283translate_acl(struct archive_read_disk *a,
1267 struct archive_entry *entry, acl_t acl, int default_entry_acl_type) 1284 struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
1268{ 1285{
1269 acl_tag_t acl_tag; 1286 acl_tag_t acl_tag;
1270#if HAVE_FREEBSD_NFS4_ACL 1287#if HAVE_FREEBSD_NFS4_ACL
1271 acl_entry_type_t acl_type; 1288 acl_entry_type_t acl_type;
1272 int brand; 1289 int brand;
1273#endif 1290#endif
1274#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL 1291#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
1275 acl_flagset_t acl_flagset; 1292 acl_flagset_t acl_flagset;
1276#endif 1293#endif
1277 acl_entry_t acl_entry; 1294 acl_entry_t acl_entry;
1278 acl_permset_t acl_permset; 1295 acl_permset_t acl_permset;
1279 int i, entry_acl_type; 1296 int i, entry_acl_type;
1280 int r, s, ae_id, ae_tag, ae_perm; 1297 int r, s, ae_id, ae_tag, ae_perm;
1281#if !HAVE_DARWIN_ACL 1298#if !HAVE_DARWIN_ACL
1282 void *q; 1299 void *q;
1283#endif 1300#endif
1284 const char *ae_name; 1301 const char *ae_name;
1285 1302
1286#if HAVE_FREEBSD_NFS4_ACL 1303#if HAVE_FREEBSD_NFS4_ACL
1287 // FreeBSD "brands" ACLs as POSIX.1e or NFSv4 1304 // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
1288 // Make sure the "brand" on this ACL is consistent 1305 // Make sure the "brand" on this ACL is consistent
1289 // with the default_entry_acl_type bits provided. 1306 // with the default_entry_acl_type bits provided.
1290 if (acl_get_brand_np(acl, &brand) != 0) { 1307 if (acl_get_brand_np(acl, &brand) != 0) {
1291 archive_set_error(&a->archive, errno, 1308 archive_set_error(&a->archive, errno,
1292 "Failed to read ACL brand"); 1309 "Failed to read ACL brand");
1293 return (ARCHIVE_WARN); 1310 return (ARCHIVE_WARN);
1294 } 1311 }
1295 switch (brand) { 1312 switch (brand) {
1296 case ACL_BRAND_POSIX: 1313 case ACL_BRAND_POSIX:
1297 switch (default_entry_acl_type) { 1314 switch (default_entry_acl_type) {
1298 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS: 1315 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
1299 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT: 1316 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
1300 break; 1317 break;
1301 default: 1318 default:
1302 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1319 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1303 "Invalid ACL entry type for POSIX.1e ACL"); 1320 "Invalid ACL entry type for POSIX.1e ACL");
1304 return (ARCHIVE_WARN); 1321 return (ARCHIVE_WARN);
1305 } 1322 }
1306 break; 1323 break;
1307 case ACL_BRAND_NFS4: 1324 case ACL_BRAND_NFS4:
1308 if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 1325 if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
1309 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1326 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1310 "Invalid ACL entry type for NFSv4 ACL"); 1327 "Invalid ACL entry type for NFSv4 ACL");
1311 return (ARCHIVE_WARN); 1328 return (ARCHIVE_WARN);
1312 } 1329 }
1313 break; 1330 break;
1314 default: 1331 default:
1315 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1332 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1316 "Unknown ACL brand"); 1333 "Unknown ACL brand");
1317 return (ARCHIVE_WARN); 1334 return (ARCHIVE_WARN);
1318 } 1335 }
1319#endif 1336#endif
1320 1337
1321 s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry); 1338 s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
1322 if (s == -1) { 1339 if (s == -1) {
1323 archive_set_error(&a->archive, errno, 1340 archive_set_error(&a->archive, errno,
1324 "Failed to get first ACL entry"); 1341 "Failed to get first ACL entry");
1325 return (ARCHIVE_WARN); 1342 return (ARCHIVE_WARN);
1326 } 1343 }
1327 1344
1328#if HAVE_DARWIN_ACL 1345#if HAVE_DARWIN_ACL
1329 while (s == 0) 1346 while (s == 0)
1330#else /* FreeBSD, Linux */ 1347#else /* FreeBSD, Linux */
1331 while (s == 1) 1348 while (s == 1)
1332#endif 1349#endif
1333 { 1350 {
1334 ae_id = -1; 1351 ae_id = -1;
1335 ae_name = NULL; 1352 ae_name = NULL;
1336 ae_perm = 0; 1353 ae_perm = 0;
1337 1354
1338 if (acl_get_tag_type(acl_entry, &acl_tag) != 0) { 1355 if (acl_get_tag_type(acl_entry, &acl_tag) != 0) {
1339 archive_set_error(&a->archive, errno, 1356 archive_set_error(&a->archive, errno,
1340 "Failed to get ACL tag type"); 1357 "Failed to get ACL tag type");
1341 return (ARCHIVE_WARN); 1358 return (ARCHIVE_WARN);
1342 } 1359 }
1343 switch (acl_tag) { 1360 switch (acl_tag) {
1344#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */ 1361#if !HAVE_DARWIN_ACL /* FreeBSD, Linux */
1345 case ACL_USER: 1362 case ACL_USER:
1346 q = acl_get_qualifier(acl_entry); 1363 q = acl_get_qualifier(acl_entry);
1347 if (q != NULL) { 1364 if (q != NULL) {
1348 ae_id = (int)*(uid_t *)q; 1365 ae_id = (int)*(uid_t *)q;
1349 acl_free(q); 1366 acl_free(q);
1350 ae_name = archive_read_disk_uname(&a->archive, 1367 ae_name = archive_read_disk_uname(&a->archive,
1351 ae_id); 1368 ae_id);
1352 } 1369 }
1353 ae_tag = ARCHIVE_ENTRY_ACL_USER; 1370 ae_tag = ARCHIVE_ENTRY_ACL_USER;
1354 break; 1371 break;
1355 case ACL_GROUP: 1372 case ACL_GROUP:
1356 q = acl_get_qualifier(acl_entry); 1373 q = acl_get_qualifier(acl_entry);
1357 if (q != NULL) { 1374 if (q != NULL) {
1358 ae_id = (int)*(gid_t *)q; 1375 ae_id = (int)*(gid_t *)q;
1359 acl_free(q); 1376 acl_free(q);
1360 ae_name = archive_read_disk_gname(&a->archive, 1377 ae_name = archive_read_disk_gname(&a->archive,
1361 ae_id); 1378 ae_id);
1362 } 1379 }
1363 ae_tag = ARCHIVE_ENTRY_ACL_GROUP; 1380 ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
1364 break; 1381 break;
1365 case ACL_MASK: 1382 case ACL_MASK:
1366 ae_tag = ARCHIVE_ENTRY_ACL_MASK; 1383 ae_tag = ARCHIVE_ENTRY_ACL_MASK;
1367 break; 1384 break;
1368 case ACL_USER_OBJ: 1385 case ACL_USER_OBJ:
1369 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ; 1386 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
1370 break; 1387 break;
1371 case ACL_GROUP_OBJ: 1388 case ACL_GROUP_OBJ:
1372 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ; 1389 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
1373 break; 1390 break;
1374 case ACL_OTHER: 1391 case ACL_OTHER:
1375 ae_tag = ARCHIVE_ENTRY_ACL_OTHER; 1392 ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
1376 break; 1393 break;
1377#if HAVE_FREEBSD_NFS4_ACL 1394#if HAVE_FREEBSD_NFS4_ACL
1378 case ACL_EVERYONE: 1395 case ACL_EVERYONE:
1379 ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE; 1396 ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
1380 break; 1397 break;
1381#endif 1398#endif
1382#else /* HAVE_DARWIN_ACL */ 1399#else /* HAVE_DARWIN_ACL */
1383 case ACL_EXTENDED_ALLOW: 1400 case ACL_EXTENDED_ALLOW:
1384 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; 1401 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
1385 r = translate_guid(&a->archive, acl_entry, &ae_id, 1402 r = translate_guid(&a->archive, acl_entry, &ae_id,
1386 &ae_tag, &ae_name); 1403 &ae_tag, &ae_name);
1387 break; 1404 break;
1388 case ACL_EXTENDED_DENY: 1405 case ACL_EXTENDED_DENY:
1389 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; 1406 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
1390 r = translate_guid(&a->archive, acl_entry, &ae_id, 1407 r = translate_guid(&a->archive, acl_entry, &ae_id,
1391 &ae_tag, &ae_name); 1408 &ae_tag, &ae_name);
1392 break; 1409 break;
1393#endif /* HAVE_DARWIN_ACL */ 1410#endif /* HAVE_DARWIN_ACL */
1394 default: 1411 default:
1395 /* Skip types that libarchive can't support. */ 1412 /* Skip types that libarchive can't support. */
1396 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 1413 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
1397 continue; 1414 continue;
1398 } 1415 }
1399 1416
1400#if HAVE_DARWIN_ACL 1417#if HAVE_DARWIN_ACL
1401 /* Skip if translate_guid() above failed */ 1418 /* Skip if translate_guid() above failed */
1402 if (r != 0) { 1419 if (r != 0) {
1403 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 1420 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
1404 continue; 1421 continue;
1405 } 1422 }
1406#endif 1423#endif
1407 1424
1408#if !HAVE_DARWIN_ACL 1425#if !HAVE_DARWIN_ACL
1409 // XXX acl_type maps to allow/deny/audit/YYYY bits 1426 // XXX acl_type maps to allow/deny/audit/YYYY bits
1410 entry_acl_type = default_entry_acl_type; 1427 entry_acl_type = default_entry_acl_type;
1411#endif 1428#endif
1412#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL 1429#if HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL
1413 if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) { 1430 if (default_entry_acl_type & ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
1414#if HAVE_FREEBSD_NFS4_ACL 1431#if HAVE_FREEBSD_NFS4_ACL
1415 /* 1432 /*
1416 * acl_get_entry_type_np() fails with non-NFSv4 ACLs 1433 * acl_get_entry_type_np() fails with non-NFSv4 ACLs
1417 */ 1434 */
1418 if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) { 1435 if (acl_get_entry_type_np(acl_entry, &acl_type) != 0) {
1419 archive_set_error(&a->archive, errno, "Failed " 1436 archive_set_error(&a->archive, errno, "Failed "
1420 "to get ACL type from a NFSv4 ACL entry"); 1437 "to get ACL type from a NFSv4 ACL entry");
1421 return (ARCHIVE_WARN); 1438 return (ARCHIVE_WARN);
1422 } 1439 }
1423 switch (acl_type) { 1440 switch (acl_type) {
1424 case ACL_ENTRY_TYPE_ALLOW: 1441 case ACL_ENTRY_TYPE_ALLOW:
1425 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW; 1442 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
1426 break; 1443 break;
1427 case ACL_ENTRY_TYPE_DENY: 1444 case ACL_ENTRY_TYPE_DENY:
1428 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY; 1445 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
1429 break; 1446 break;
1430 case ACL_ENTRY_TYPE_AUDIT: 1447 case ACL_ENTRY_TYPE_AUDIT:
1431 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT; 1448 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
1432 break; 1449 break;
1433 case ACL_ENTRY_TYPE_ALARM: 1450 case ACL_ENTRY_TYPE_ALARM:
1434 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM; 1451 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
1435 break; 1452 break;
1436 default: 1453 default:
1437 archive_set_error(&a->archive, errno, 1454 archive_set_error(&a->archive, errno,
1438 "Invalid NFSv4 ACL entry type"); 1455 "Invalid NFSv4 ACL entry type");
1439 return (ARCHIVE_WARN); 1456 return (ARCHIVE_WARN);
1440 } 1457 }
1441#endif /* HAVE_FREEBSD_NFS4_ACL */ 1458#endif /* HAVE_FREEBSD_NFS4_ACL */
1442 1459
1443 /* 1460 /*
1444 * Libarchive stores "flag" (NFSv4 inheritance bits) 1461 * Libarchive stores "flag" (NFSv4 inheritance bits)
1445 * in the ae_perm bitmap. 1462 * in the ae_perm bitmap.
1446 * 1463 *
1447 * acl_get_flagset_np() fails with non-NFSv4 ACLs 1464 * acl_get_flagset_np() fails with non-NFSv4 ACLs
1448 */ 1465 */
1449 if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) { 1466 if (acl_get_flagset_np(acl_entry, &acl_flagset) != 0) {
1450 archive_set_error(&a->archive, errno, 1467 archive_set_error(&a->archive, errno,
1451 "Failed to get flagset from a NFSv4 ACL entry"); 1468 "Failed to get flagset from a NFSv4 ACL entry");
1452 return (ARCHIVE_WARN); 1469 return (ARCHIVE_WARN);
1453 } 1470 }
1454 for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) { 1471 for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
1455 r = acl_get_flag_np(acl_flagset, 1472 r = acl_get_flag_np(acl_flagset,
1456 acl_inherit_map[i].platform_inherit); 1473 acl_inherit_map[i].platform_inherit);
1457 if (r == -1) { 1474 if (r == -1) {
1458 archive_set_error(&a->archive, errno, 1475 archive_set_error(&a->archive, errno,
1459 "Failed to check flag in a NFSv4 " 1476 "Failed to check flag in a NFSv4 "
1460 "ACL flagset"); 1477 "ACL flagset");
1461 return (ARCHIVE_WARN); 1478 return (ARCHIVE_WARN);
1462 } else if (r) 1479 } else if (r)
1463 ae_perm |= acl_inherit_map[i].archive_inherit; 1480 ae_perm |= acl_inherit_map[i].archive_inherit;
1464 } 1481 }
1465 } 1482 }
1466#endif /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL */ 1483#endif /* HAVE_FREEBSD_NFS4_ACL || HAVE_DARWIN_ACL */
1467 1484
1468 if (acl_get_permset(acl_entry, &acl_permset) != 0) { 1485 if (acl_get_permset(acl_entry, &acl_permset) != 0) {
1469 archive_set_error(&a->archive, errno, 1486 archive_set_error(&a->archive, errno,
1470 "Failed to get ACL permission set"); 1487 "Failed to get ACL permission set");
1471 return (ARCHIVE_WARN); 1488 return (ARCHIVE_WARN);
1472 } 1489 }
1473 for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) { 1490 for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
1474 /* 1491 /*
1475 * acl_get_perm() is spelled differently on different 1492 * acl_get_perm() is spelled differently on different
1476 * platforms; see above. 1493 * platforms; see above.
1477 */ 1494 */
1478 r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm); 1495 r = ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm);
1479 if (r == -1) { 1496 if (r == -1) {
1480 archive_set_error(&a->archive, errno, 1497 archive_set_error(&a->archive, errno,
1481 "Failed to check permission in an ACL permission set"); 1498 "Failed to check permission in an ACL permission set");
1482 return (ARCHIVE_WARN); 1499 return (ARCHIVE_WARN);
1483 } else if (r) 1500 } else if (r)
1484 ae_perm |= acl_perm_map[i].archive_perm; 1501 ae_perm |= acl_perm_map[i].archive_perm;
1485 } 1502 }
1486 1503
1487#if HAVE_DARWIN_ACL && !HAVE_DECL_ACL_SYNCHRONIZE 1504#if HAVE_DARWIN_ACL && !HAVE_DECL_ACL_SYNCHRONIZE
1488 /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */ 1505 /* On Mac OS X without ACL_SYNCHRONIZE assume it is set */
1489 ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE; 1506 ae_perm |= ARCHIVE_ENTRY_ACL_SYNCHRONIZE;
1490#endif 1507#endif
1491 1508
1492 archive_entry_acl_add_entry(entry, entry_acl_type, 1509 archive_entry_acl_add_entry(entry, entry_acl_type,
1493 ae_perm, ae_tag, 1510 ae_perm, ae_tag,
1494 ae_id, ae_name); 1511 ae_id, ae_name);
1495 1512
1496 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 1513 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
1497#if !HAVE_DARWIN_ACL 1514#if !HAVE_DARWIN_ACL
1498 if (s == -1) { 1515 if (s == -1) {
1499 archive_set_error(&a->archive, errno, 1516 archive_set_error(&a->archive, errno,
1500 "Failed to get next ACL entry"); 1517 "Failed to get next ACL entry");
1501 return (ARCHIVE_WARN); 1518 return (ARCHIVE_WARN);
1502 } 1519 }
1503#endif 1520#endif
1504 } 1521 }
1505 return (ARCHIVE_OK); 1522 return (ARCHIVE_OK);
1506} 1523}
1507#endif /* !HAVE_SUN_ACL */ 1524#endif /* !HAVE_SUN_ACL */
1508#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ 1525#else /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
1509static int 1526static int
1510setup_acls(struct archive_read_disk *a, 1527setup_acls(struct archive_read_disk *a,
1511 struct archive_entry *entry, int *fd) 1528 struct archive_entry *entry, int *fd)
1512{ 1529{
1513 (void)a; /* UNUSED */ 1530 (void)a; /* UNUSED */
1514 (void)entry; /* UNUSED */ 1531 (void)entry; /* UNUSED */
1515 (void)fd; /* UNUSED */ 1532 (void)fd; /* UNUSED */
1516 return (ARCHIVE_OK); 1533 return (ARCHIVE_OK);
1517} 1534}
1518#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */ 1535#endif /* !HAVE_POSIX_ACL && !HAVE_NFS4_ACL */
1519 1536
1520#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ 1537#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
1521 HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ 1538 HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
1522 (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA) 1539 (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
1523 1540
1524/* 1541/*
1525 * Linux and AIX extended attribute support. 1542 * Linux and AIX extended attribute support.
1526 * 1543 *
1527 * TODO: By using a stack-allocated buffer for the first 1544 * TODO: By using a stack-allocated buffer for the first
1528 * call to getxattr(), we might be able to avoid the second 1545 * call to getxattr(), we might be able to avoid the second
1529 * call entirely. We only need the second call if the 1546 * call entirely. We only need the second call if the
1530 * stack-allocated buffer is too small. But a modest buffer 1547 * stack-allocated buffer is too small. But a modest buffer
1531 * of 1024 bytes or so will often be big enough. Same applies 1548 * of 1024 bytes or so will often be big enough. Same applies
1532 * to listxattr(). 1549 * to listxattr().
1533 */ 1550 */
1534 1551
1535 1552
1536static int 1553static int
1537setup_xattr(struct archive_read_disk *a, 1554setup_xattr(struct archive_read_disk *a,
1538 struct archive_entry *entry, const char *name, int fd, const char *accpath) 1555 struct archive_entry *entry, const char *name, int fd, const char *accpath)
1539{ 1556{
1540 ssize_t size; 1557 ssize_t size;
1541 void *value = NULL; 1558 void *value = NULL;
1542 1559
1543#if HAVE_FGETXATTR 1560#if HAVE_FGETXATTR
1544 if (fd >= 0) 1561 if (fd >= 0)
1545 size = fgetxattr(fd, name, NULL, 0); 1562 size = fgetxattr(fd, name, NULL, 0);
1546 else if (!a->follow_symlinks) 1563 else if (!a->follow_symlinks)
1547 size = lgetxattr(accpath, name, NULL, 0); 1564 size = lgetxattr(accpath, name, NULL, 0);
1548 else 1565 else
1549 size = getxattr(accpath, name, NULL, 0); 1566 size = getxattr(accpath, name, NULL, 0);
1550#elif HAVE_FGETEA 1567#elif HAVE_FGETEA
1551 if (fd >= 0) 1568 if (fd >= 0)
1552 size = fgetea(fd, name, NULL, 0); 1569 size = fgetea(fd, name, NULL, 0);
1553 else if (!a->follow_symlinks) 1570 else if (!a->follow_symlinks)
1554 size = lgetea(accpath, name, NULL, 0); 1571 size = lgetea(accpath, name, NULL, 0);
1555 else 1572 else
1556 size = getea(accpath, name, NULL, 0); 1573 size = getea(accpath, name, NULL, 0);
1557#endif 1574#endif
1558 1575
1559 if (size == -1) { 1576 if (size == -1) {
1560 archive_set_error(&a->archive, errno, 1577 archive_set_error(&a->archive, errno,
1561 "Couldn't query extended attribute"); 1578 "Couldn't query extended attribute");
1562 return (ARCHIVE_WARN); 1579 return (ARCHIVE_WARN);
1563 } 1580 }
1564 1581
1565 if (size > 0 && (value = malloc(size)) == NULL) { 1582 if (size > 0 && (value = malloc(size)) == NULL) {
1566 archive_set_error(&a->archive, errno, "Out of memory"); 1583 archive_set_error(&a->archive, errno, "Out of memory");
1567 return (ARCHIVE_FATAL); 1584 return (ARCHIVE_FATAL);
1568 } 1585 }
1569 1586
1570#if HAVE_FGETXATTR 1587#if HAVE_FGETXATTR
1571 if (fd >= 0) 1588 if (fd >= 0)
1572 size = fgetxattr(fd, name, value, size); 1589 size = fgetxattr(fd, name, value, size);
1573 else if (!a->follow_symlinks) 1590 else if (!a->follow_symlinks)
1574 size = lgetxattr(accpath, name, value, size); 1591 size = lgetxattr(accpath, name, value, size);
1575 else 1592 else
1576 size = getxattr(accpath, name, value, size); 1593 size = getxattr(accpath, name, value, size);
1577#elif HAVE_FGETEA 1594#elif HAVE_FGETEA
1578 if (fd >= 0) 1595 if (fd >= 0)
1579 size = fgetea(fd, name, value, size); 1596 size = fgetea(fd, name, value, size);
1580 else if (!a->follow_symlinks) 1597 else if (!a->follow_symlinks)
1581 size = lgetea(accpath, name, value, size); 1598 size = lgetea(accpath, name, value, size);
1582 else 1599 else
1583 size = getea(accpath, name, value, size); 1600 size = getea(accpath, name, value, size);
1584#endif 1601#endif
1585 1602
1586 if (size == -1) { 1603 if (size == -1) {
1587 archive_set_error(&a->archive, errno, 1604 archive_set_error(&a->archive, errno,
1588 "Couldn't read extended attribute"); 1605 "Couldn't read extended attribute");
1589 return (ARCHIVE_WARN); 1606 return (ARCHIVE_WARN);
1590 } 1607 }
1591 1608
1592 archive_entry_xattr_add_entry(entry, name, value, size); 1609 archive_entry_xattr_add_entry(entry, name, value, size);
1593 1610
1594 free(value); 1611 free(value);
1595 return (ARCHIVE_OK); 1612 return (ARCHIVE_OK);
1596} 1613}
1597 1614
1598static int 1615static int
1599setup_xattrs(struct archive_read_disk *a, 1616setup_xattrs(struct archive_read_disk *a,
1600 struct archive_entry *entry, int *fd) 1617 struct archive_entry *entry, int *fd)
1601{ 1618{
1602 char *list, *p; 1619 char *list, *p;
1603 const char *path; 1620 const char *path;
1604 ssize_t list_size; 1621 ssize_t list_size;
1605 1622
1606 path = NULL; 1623 path = NULL;
1607 1624
1608 if (*fd < 0) { 1625 if (*fd < 0) {
1609 path = archive_entry_sourcepath(entry); 1626 path = archive_entry_sourcepath(entry);
1610 if (path == NULL || (a->tree != NULL && 1627 if (path == NULL || (a->tree != NULL &&
1611 a->tree_enter_working_dir(a->tree) != 0)) 1628 a->tree_enter_working_dir(a->tree) != 0))
1612 path = archive_entry_pathname(entry); 1629 path = archive_entry_pathname(entry);
1613 if (path == NULL) { 1630 if (path == NULL) {
1614 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, 1631 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1615 "Couldn't determine file path to read " 1632 "Couldn't determine file path to read "
1616 "extended attributes"); 1633 "extended attributes");
1617 return (ARCHIVE_WARN); 1634 return (ARCHIVE_WARN);
1618 } 1635 }
1619 if (a->tree != NULL && (a->follow_symlinks || 1636 if (a->tree != NULL && (a->follow_symlinks ||
1620 archive_entry_filetype(entry) != AE_IFLNK)) { 1637 archive_entry_filetype(entry) != AE_IFLNK)) {
1621 *fd = a->open_on_current_dir(a->tree, 1638 *fd = a->open_on_current_dir(a->tree,
1622 path, O_RDONLY | O_NONBLOCK); 1639 path, O_RDONLY | O_NONBLOCK);
1623 } 1640 }
1624 } 1641 }
1625 1642
1626#if HAVE_FLISTXATTR 1643#if HAVE_FLISTXATTR
1627 if (*fd >= 0) 1644 if (*fd >= 0)
1628 list_size = flistxattr(*fd, NULL, 0); 1645 list_size = flistxattr(*fd, NULL, 0);
1629 else if (!a->follow_symlinks) 1646 else if (!a->follow_symlinks)
1630 list_size = llistxattr(path, NULL, 0); 1647 list_size = llistxattr(path, NULL, 0);
1631 else 1648 else
1632 list_size = listxattr(path, NULL, 0); 1649 list_size = listxattr(path, NULL, 0);
1633#elif HAVE_FLISTEA 1650#elif HAVE_FLISTEA
1634 if (*fd >= 0) 1651 if (*fd >= 0)
1635 list_size = flistea(*fd, NULL, 0); 1652 list_size = flistea(*fd, NULL, 0);
1636 else if (!a->follow_symlinks) 1653 else if (!a->follow_symlinks)
1637 list_size = llistea(path, NULL, 0); 1654 list_size = llistea(path, NULL, 0);
1638 else 1655 else
1639 list_size = listea(path, NULL, 0); 1656 list_size = listea(path, NULL, 0);
1640#endif 1657#endif
1641 1658
1642 if (list_size == -1) { 1659 if (list_size == -1) {
1643 if (errno == ENOTSUP || errno == ENOSYS) 1660 if (errno == ENOTSUP || errno == ENOSYS)
1644 return (ARCHIVE_OK); 1661 return (ARCHIVE_OK);
1645 archive_set_error(&a->archive, errno, 1662 archive_set_error(&a->archive, errno,
1646 "Couldn't list extended attributes"); 1663 "Couldn't list extended attributes");
1647 return (ARCHIVE_WARN); 1664 return (ARCHIVE_WARN);
1648 } 1665 }
1649 1666
1650 if (list_size == 0) 1667 if (list_size == 0)
1651 return (ARCHIVE_OK); 1668 return (ARCHIVE_OK);
1652 1669
1653 if ((list = malloc(list_size)) == NULL) { 1670 if ((list = malloc(list_size)) == NULL) {
1654 archive_set_error(&a->archive, errno, "Out of memory"); 1671 archive_set_error(&a->archive, errno, "Out of memory");
1655 return (ARCHIVE_FATAL); 1672 return (ARCHIVE_FATAL);
1656 } 1673 }
1657 1674
1658#if HAVE_FLISTXATTR 1675#if HAVE_FLISTXATTR
1659 if (*fd >= 0) 1676 if (*fd >= 0)
1660 list_size = flistxattr(*fd, list, list_size); 1677 list_size = flistxattr(*fd, list, list_size);
1661 else if (!a->follow_symlinks) 1678 else if (!a->follow_symlinks)
1662 list_size = llistxattr(path, list, list_size); 1679 list_size = llistxattr(path, list, list_size);
1663 else 1680 else
1664 list_size = listxattr(path, list, list_size); 1681 list_size = listxattr(path, list, list_size);
1665#elif HAVE_FLISTEA 1682#elif HAVE_FLISTEA
1666 if (*fd >= 0) 1683 if (*fd >= 0)
1667 list_size = flistea(*fd, list, list_size); 1684 list_size = flistea(*fd, list, list_size);
1668 else if (!a->follow_symlinks) 1685 else if (!a->follow_symlinks)
1669 list_size = llistea(path, list, list_size); 1686 list_size = llistea(path, list, list_size);
1670 else 1687 else
1671 list_size = listea(path, list, list_size); 1688 list_size = listea(path, list, list_size);
1672#endif 1689#endif
1673 1690
1674 if (list_size == -1) { 1691 if (list_size == -1) {
1675 archive_set_error(&a->archive, errno, 1692 archive_set_error(&a->archive, errno,
1676 "Couldn't retrieve extended attributes"); 1693 "Couldn't retrieve extended attributes");
1677 free(list); 1694 free(list);
1678 return (ARCHIVE_WARN); 1695 return (ARCHIVE_WARN);
1679 } 1696 }
1680 1697
1681 for (p = list; (p - list) < list_size; p += strlen(p) + 1) { 1698 for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
1682 if (strncmp(p, "system.", 7) == 0 || 1699 if (strncmp(p, "system.", 7) == 0 ||
1683 strncmp(p, "xfsroot.", 8) == 0) 1700 strncmp(p, "xfsroot.", 8) == 0)
1684 continue; 1701 continue;
1685 setup_xattr(a, entry, p, *fd, path); 1702 setup_xattr(a, entry, p, *fd, path);
1686 } 1703 }
1687 1704
1688 free(list); 1705 free(list);
1689 return (ARCHIVE_OK); 1706 return (ARCHIVE_OK);
1690} 1707}
1691 1708
1692#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \ 1709#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
1693 HAVE_DECL_EXTATTR_NAMESPACE_USER 1710 HAVE_DECL_EXTATTR_NAMESPACE_USER
1694 1711
1695/* 1712/*