]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
Replace our (un)vis(1) commands with implementations from NetBSD to
[FreeBSD/FreeBSD.git] / contrib / libarchive / libarchive / archive_read_disk_entry_from_file.c
1 /*-
2  * Copyright (c) 2003-2009 Tim Kientzle
3  * Copyright (c) 2010-2012 Michihiro NAKAJIMA
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD$");
29
30 /* This is the tree-walking code for POSIX systems. */
31 #if !defined(_WIN32) || defined(__CYGWIN__)
32
33 #ifdef HAVE_SYS_TYPES_H
34 /* Mac OSX requires sys/types.h before sys/acl.h. */
35 #include <sys/types.h>
36 #endif
37 #ifdef HAVE_SYS_ACL_H
38 #include <sys/acl.h>
39 #endif
40 #ifdef HAVE_SYS_EXTATTR_H
41 #include <sys/extattr.h>
42 #endif
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
45 #endif
46 #ifdef HAVE_SYS_PARAM_H
47 #include <sys/param.h>
48 #endif
49 #ifdef HAVE_SYS_STAT_H
50 #include <sys/stat.h>
51 #endif
52 #ifdef HAVE_SYS_XATTR_H
53 #include <sys/xattr.h>
54 #endif
55 #ifdef HAVE_SYS_EA_H
56 #include <sys/ea.h>
57 #endif
58 #ifdef HAVE_ACL_LIBACL_H
59 #include <acl/libacl.h>
60 #endif
61 #ifdef HAVE_ATTR_XATTR_H
62 #include <attr/xattr.h>
63 #endif
64 #ifdef HAVE_COPYFILE_H
65 #include <copyfile.h>
66 #endif
67 #ifdef HAVE_ERRNO_H
68 #include <errno.h>
69 #endif
70 #ifdef HAVE_FCNTL_H
71 #include <fcntl.h>
72 #endif
73 #ifdef HAVE_LIMITS_H
74 #include <limits.h>
75 #endif
76 #ifdef HAVE_LINUX_TYPES_H
77 #include <linux/types.h>
78 #endif
79 #ifdef HAVE_LINUX_FIEMAP_H
80 #include <linux/fiemap.h>
81 #endif
82 #ifdef HAVE_LINUX_FS_H
83 #include <linux/fs.h>
84 #endif
85 /*
86  * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
87  * As the include guards don't agree, the order of include is important.
88  */
89 #ifdef HAVE_LINUX_EXT2_FS_H
90 #include <linux/ext2_fs.h>      /* for Linux file flags */
91 #endif
92 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
93 #include <ext2fs/ext2_fs.h>     /* Linux file flags, broken on Cygwin */
94 #endif
95 #ifdef HAVE_PATHS_H
96 #include <paths.h>
97 #endif
98 #ifdef HAVE_UNISTD_H
99 #include <unistd.h>
100 #endif
101
102 #include "archive.h"
103 #include "archive_entry.h"
104 #include "archive_private.h"
105 #include "archive_read_disk_private.h"
106
107 /*
108  * Linux and FreeBSD plug this obvious hole in POSIX.1e in
109  * different ways.
110  */
111 #if HAVE_ACL_GET_PERM
112 #define ACL_GET_PERM acl_get_perm
113 #elif HAVE_ACL_GET_PERM_NP
114 #define ACL_GET_PERM acl_get_perm_np
115 #endif
116
117 static int setup_acls(struct archive_read_disk *,
118     struct archive_entry *, int *fd);
119 static int setup_mac_metadata(struct archive_read_disk *,
120     struct archive_entry *, int *fd);
121 static int setup_xattrs(struct archive_read_disk *,
122     struct archive_entry *, int *fd);
123 static int setup_sparse(struct archive_read_disk *,
124     struct archive_entry *, int *fd);
125
126 int
127 archive_read_disk_entry_from_file(struct archive *_a,
128     struct archive_entry *entry,
129     int fd,
130     const struct stat *st)
131 {
132         struct archive_read_disk *a = (struct archive_read_disk *)_a;
133         const char *path, *name;
134         struct stat s;
135         int initial_fd = fd;
136         int r, r1;
137
138         archive_clear_error(_a);
139         path = archive_entry_sourcepath(entry);
140         if (path == NULL)
141                 path = archive_entry_pathname(entry);
142
143         if (a->tree == NULL) {
144                 if (st == NULL) {
145 #if HAVE_FSTAT
146                         if (fd >= 0) {
147                                 if (fstat(fd, &s) != 0) {
148                                         archive_set_error(&a->archive, errno,
149                                             "Can't fstat");
150                                         return (ARCHIVE_FAILED);
151                                 }
152                         } else
153 #endif
154 #if HAVE_LSTAT
155                         if (!a->follow_symlinks) {
156                                 if (lstat(path, &s) != 0) {
157                                         archive_set_error(&a->archive, errno,
158                                             "Can't lstat %s", path);
159                                         return (ARCHIVE_FAILED);
160                                 }
161                         } else
162 #endif
163                         if (stat(path, &s) != 0) {
164                                 archive_set_error(&a->archive, errno,
165                                     "Can't stat %s", path);
166                                 return (ARCHIVE_FAILED);
167                         }
168                         st = &s;
169                 }
170                 archive_entry_copy_stat(entry, st);
171         }
172
173         /* Lookup uname/gname */
174         name = archive_read_disk_uname(_a, archive_entry_uid(entry));
175         if (name != NULL)
176                 archive_entry_copy_uname(entry, name);
177         name = archive_read_disk_gname(_a, archive_entry_gid(entry));
178         if (name != NULL)
179                 archive_entry_copy_gname(entry, name);
180
181 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
182         /* On FreeBSD, we get flags for free with the stat. */
183         /* TODO: Does this belong in copy_stat()? */
184         if (st->st_flags != 0)
185                 archive_entry_set_fflags(entry, st->st_flags, 0);
186 #endif
187
188 #if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
189         /* Linux requires an extra ioctl to pull the flags.  Although
190          * this is an extra step, it has a nice side-effect: We get an
191          * open file descriptor which we can use in the subsequent lookups. */
192         if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
193                 if (fd < 0) {
194                         if (a->tree != NULL)
195                                 fd = a->open_on_current_dir(a->tree, path,
196                                         O_RDONLY | O_NONBLOCK);
197                         else
198                                 fd = open(path, O_RDONLY | O_NONBLOCK);
199                 }
200                 if (fd >= 0) {
201                         unsigned long stflags;
202                         r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
203                         if (r == 0 && stflags != 0)
204                                 archive_entry_set_fflags(entry, stflags, 0);
205                 }
206         }
207 #endif
208
209 #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
210         if (S_ISLNK(st->st_mode)) {
211                 size_t linkbuffer_len = st->st_size + 1;
212                 char *linkbuffer;
213                 int lnklen;
214
215                 linkbuffer = malloc(linkbuffer_len);
216                 if (linkbuffer == NULL) {
217                         archive_set_error(&a->archive, ENOMEM,
218                             "Couldn't read link data");
219                         return (ARCHIVE_FAILED);
220                 }
221                 if (a->tree != NULL) {
222 #ifdef HAVE_READLINKAT
223                         lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
224                             path, linkbuffer, linkbuffer_len);
225 #else
226                         if (a->tree_enter_working_dir(a->tree) != 0) {
227                                 archive_set_error(&a->archive, errno,
228                                     "Couldn't read link data");
229                                 free(linkbuffer);
230                                 return (ARCHIVE_FAILED);
231                         }
232                         lnklen = readlink(path, linkbuffer, linkbuffer_len);
233 #endif /* HAVE_READLINKAT */
234                 } else
235                         lnklen = readlink(path, linkbuffer, linkbuffer_len);
236                 if (lnklen < 0) {
237                         archive_set_error(&a->archive, errno,
238                             "Couldn't read link data");
239                         free(linkbuffer);
240                         return (ARCHIVE_FAILED);
241                 }
242                 linkbuffer[lnklen] = 0;
243                 archive_entry_set_symlink(entry, linkbuffer);
244                 free(linkbuffer);
245         }
246 #endif /* HAVE_READLINK || HAVE_READLINKAT */
247
248         r = setup_acls(a, entry, &fd);
249         r1 = setup_xattrs(a, entry, &fd);
250         if (r1 < r)
251                 r = r1;
252         if (a->enable_copyfile) {
253                 r1 = setup_mac_metadata(a, entry, &fd);
254                 if (r1 < r)
255                         r = r1;
256         }
257         r1 = setup_sparse(a, entry, &fd);
258         if (r1 < r)
259                 r = r1;
260
261         /* If we opened the file earlier in this function, close it. */
262         if (initial_fd != fd)
263                 close(fd);
264         return (r);
265 }
266
267 #if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
268 /*
269  * The Mac OS "copyfile()" API copies the extended metadata for a
270  * file into a separate file in AppleDouble format (see RFC 1740).
271  *
272  * Mac OS tar and cpio implementations store this extended
273  * metadata as a separate entry just before the regular entry
274  * with a "._" prefix added to the filename.
275  *
276  * Note that this is currently done unconditionally; the tar program has
277  * an option to discard this information before the archive is written.
278  *
279  * TODO: If there's a failure, report it and return ARCHIVE_WARN.
280  */
281 static int
282 setup_mac_metadata(struct archive_read_disk *a,
283     struct archive_entry *entry, int *fd)
284 {
285         int tempfd = -1;
286         int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
287         struct stat copyfile_stat;
288         int ret = ARCHIVE_OK;
289         void *buff;
290         int have_attrs;
291         const char *name, *tempdir, *tempfile = NULL;
292
293         (void)fd; /* UNUSED */
294         name = archive_entry_sourcepath(entry);
295         if (name == NULL)
296                 name = archive_entry_pathname(entry);
297         if (name == NULL) {
298                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
299                     "Can't open file to read extended attributes: No name");
300                 return (ARCHIVE_WARN);
301         }
302
303         if (a->tree != NULL) {
304                 if (a->tree_enter_working_dir(a->tree) != 0) {
305                         archive_set_error(&a->archive, errno,
306                                     "Couldn't change dir");
307                                 return (ARCHIVE_FAILED);
308                 }
309         }
310
311         /* Short-circuit if there's nothing to do. */
312         have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
313         if (have_attrs == -1) {
314                 archive_set_error(&a->archive, errno,
315                         "Could not check extended attributes");
316                 return (ARCHIVE_WARN);
317         }
318         if (have_attrs == 0)
319                 return (ARCHIVE_OK);
320
321         tempdir = NULL;
322         if (issetugid() == 0)
323                 tempdir = getenv("TMPDIR");
324         if (tempdir == NULL)
325                 tempdir = _PATH_TMP;
326         tempfile = tempnam(tempdir, "tar.md.");
327
328         /* XXX I wish copyfile() could pack directly to a memory
329          * buffer; that would avoid the temp file here.  For that
330          * matter, it would be nice if fcopyfile() actually worked,
331          * that would reduce the many open/close races here. */
332         if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
333                 archive_set_error(&a->archive, errno,
334                     "Could not pack extended attributes");
335                 ret = ARCHIVE_WARN;
336                 goto cleanup;
337         }
338         tempfd = open(tempfile, O_RDONLY);
339         if (tempfd < 0) {
340                 archive_set_error(&a->archive, errno,
341                     "Could not open extended attribute file");
342                 ret = ARCHIVE_WARN;
343                 goto cleanup;
344         }
345         if (fstat(tempfd, &copyfile_stat)) {
346                 archive_set_error(&a->archive, errno,
347                     "Could not check size of extended attributes");
348                 ret = ARCHIVE_WARN;
349                 goto cleanup;
350         }
351         buff = malloc(copyfile_stat.st_size);
352         if (buff == NULL) {
353                 archive_set_error(&a->archive, errno,
354                     "Could not allocate memory for extended attributes");
355                 ret = ARCHIVE_WARN;
356                 goto cleanup;
357         }
358         if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
359                 archive_set_error(&a->archive, errno,
360                     "Could not read extended attributes into memory");
361                 ret = ARCHIVE_WARN;
362                 goto cleanup;
363         }
364         archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
365
366 cleanup:
367         if (tempfd >= 0)
368                 close(tempfd);
369         if (tempfile != NULL)
370                 unlink(tempfile);
371         return (ret);
372 }
373
374 #else
375
376 /*
377  * Stub implementation for non-Mac systems.
378  */
379 static int
380 setup_mac_metadata(struct archive_read_disk *a,
381     struct archive_entry *entry, int *fd)
382 {
383         (void)a; /* UNUSED */
384         (void)entry; /* UNUSED */
385         (void)fd; /* UNUSED */
386         return (ARCHIVE_OK);
387 }
388 #endif
389
390
391 #ifdef HAVE_POSIX_ACL
392 static int translate_acl(struct archive_read_disk *a,
393     struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
394
395 static int
396 setup_acls(struct archive_read_disk *a,
397     struct archive_entry *entry, int *fd)
398 {
399         const char      *accpath;
400         acl_t            acl;
401         int             r;
402
403         accpath = archive_entry_sourcepath(entry);
404         if (accpath == NULL)
405                 accpath = archive_entry_pathname(entry);
406
407         archive_entry_acl_clear(entry);
408
409         /* Try NFS4 ACL first. */
410         if (*fd >= 0)
411                 acl = acl_get_fd(*fd);
412 #if HAVE_ACL_GET_LINK_NP
413         else if (!a->follow_symlinks)
414                 acl = acl_get_link_np(accpath, ACL_TYPE_NFS4);
415 #else
416         else if ((!a->follow_symlinks)
417             && (archive_entry_filetype(entry) == AE_IFLNK))
418                 /* We can't get the ACL of a symlink, so we assume it can't
419                    have one. */
420                 acl = NULL;
421 #endif
422         else
423                 acl = acl_get_file(accpath, ACL_TYPE_NFS4);
424 #if HAVE_ACL_IS_TRIVIAL_NP
425         /* Ignore "trivial" ACLs that just mirror the file mode. */
426         acl_is_trivial_np(acl, &r);
427         if (r) {
428                 acl_free(acl);
429                 acl = NULL;
430         }
431 #endif
432         if (acl != NULL) {
433                 translate_acl(a, entry, acl, ARCHIVE_ENTRY_ACL_TYPE_NFS4);
434                 acl_free(acl);
435                 return (ARCHIVE_OK);
436         }
437
438         /* Retrieve access ACL from file. */
439         if (*fd >= 0)
440                 acl = acl_get_fd(*fd);
441 #if HAVE_ACL_GET_LINK_NP
442         else if (!a->follow_symlinks)
443                 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
444 #else
445         else if ((!a->follow_symlinks)
446             && (archive_entry_filetype(entry) == AE_IFLNK))
447                 /* We can't get the ACL of a symlink, so we assume it can't
448                    have one. */
449                 acl = NULL;
450 #endif
451         else
452                 acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
453         if (acl != NULL) {
454                 translate_acl(a, entry, acl,
455                     ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
456                 acl_free(acl);
457         }
458
459         /* Only directories can have default ACLs. */
460         if (S_ISDIR(archive_entry_mode(entry))) {
461                 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
462                 if (acl != NULL) {
463                         translate_acl(a, entry, acl,
464                             ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
465                         acl_free(acl);
466                 }
467         }
468         return (ARCHIVE_OK);
469 }
470
471 /*
472  * Translate system ACL into libarchive internal structure.
473  */
474
475 static struct {
476         int archive_perm;
477         int platform_perm;
478 } acl_perm_map[] = {
479         {ARCHIVE_ENTRY_ACL_EXECUTE, ACL_EXECUTE},
480         {ARCHIVE_ENTRY_ACL_WRITE, ACL_WRITE},
481         {ARCHIVE_ENTRY_ACL_READ, ACL_READ},
482         {ARCHIVE_ENTRY_ACL_READ_DATA, ACL_READ_DATA},
483         {ARCHIVE_ENTRY_ACL_LIST_DIRECTORY, ACL_LIST_DIRECTORY},
484         {ARCHIVE_ENTRY_ACL_WRITE_DATA, ACL_WRITE_DATA},
485         {ARCHIVE_ENTRY_ACL_ADD_FILE, ACL_ADD_FILE},
486         {ARCHIVE_ENTRY_ACL_APPEND_DATA, ACL_APPEND_DATA},
487         {ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY, ACL_ADD_SUBDIRECTORY},
488         {ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS, ACL_READ_NAMED_ATTRS},
489         {ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS, ACL_WRITE_NAMED_ATTRS},
490         {ARCHIVE_ENTRY_ACL_DELETE_CHILD, ACL_DELETE_CHILD},
491         {ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES, ACL_READ_ATTRIBUTES},
492         {ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES, ACL_WRITE_ATTRIBUTES},
493         {ARCHIVE_ENTRY_ACL_DELETE, ACL_DELETE},
494         {ARCHIVE_ENTRY_ACL_READ_ACL, ACL_READ_ACL},
495         {ARCHIVE_ENTRY_ACL_WRITE_ACL, ACL_WRITE_ACL},
496         {ARCHIVE_ENTRY_ACL_WRITE_OWNER, ACL_WRITE_OWNER},
497         {ARCHIVE_ENTRY_ACL_SYNCHRONIZE, ACL_SYNCHRONIZE}
498 };
499
500 static struct {
501         int archive_inherit;
502         int platform_inherit;
503 } acl_inherit_map[] = {
504         {ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT, ACL_ENTRY_FILE_INHERIT},
505         {ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT, ACL_ENTRY_DIRECTORY_INHERIT},
506         {ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT, ACL_ENTRY_NO_PROPAGATE_INHERIT},
507         {ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY, ACL_ENTRY_INHERIT_ONLY}
508 };
509
510 static int
511 translate_acl(struct archive_read_disk *a,
512     struct archive_entry *entry, acl_t acl, int default_entry_acl_type)
513 {
514         acl_tag_t        acl_tag;
515         acl_entry_type_t acl_type;
516         acl_flagset_t    acl_flagset;
517         acl_entry_t      acl_entry;
518         acl_permset_t    acl_permset;
519         int              brand, i, r, entry_acl_type;
520         int              s, ae_id, ae_tag, ae_perm;
521         const char      *ae_name;
522
523
524         // FreeBSD "brands" ACLs as POSIX.1e or NFSv4
525         // Make sure the "brand" on this ACL is consistent
526         // with the default_entry_acl_type bits provided.
527         acl_get_brand_np(acl, &brand);
528         switch (brand) {
529         case ACL_BRAND_POSIX:
530                 switch (default_entry_acl_type) {
531                 case ARCHIVE_ENTRY_ACL_TYPE_ACCESS:
532                 case ARCHIVE_ENTRY_ACL_TYPE_DEFAULT:
533                         entry_acl_type = default_entry_acl_type;
534                         break;
535                 default:
536                         // XXX set warning message?
537                         return ARCHIVE_FAILED;
538                 }
539                 break;
540         case ACL_BRAND_NFS4:
541                 if (default_entry_acl_type & ~ARCHIVE_ENTRY_ACL_TYPE_NFS4) {
542                         // XXX set warning message?
543                         return ARCHIVE_FAILED;
544                 }
545                 break;
546         default:
547                 // XXX set warning message?
548                 return ARCHIVE_FAILED;
549                 break;
550         }
551
552
553         s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
554         while (s == 1) {
555                 ae_id = -1;
556                 ae_name = NULL;
557                 ae_perm = 0;
558
559                 acl_get_tag_type(acl_entry, &acl_tag);
560                 switch (acl_tag) {
561                 case ACL_USER:
562                         ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
563                         ae_name = archive_read_disk_uname(&a->archive, ae_id);
564                         ae_tag = ARCHIVE_ENTRY_ACL_USER;
565                         break;
566                 case ACL_GROUP:
567                         ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
568                         ae_name = archive_read_disk_gname(&a->archive, ae_id);
569                         ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
570                         break;
571                 case ACL_MASK:
572                         ae_tag = ARCHIVE_ENTRY_ACL_MASK;
573                         break;
574                 case ACL_USER_OBJ:
575                         ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
576                         break;
577                 case ACL_GROUP_OBJ:
578                         ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
579                         break;
580                 case ACL_OTHER:
581                         ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
582                         break;
583                 case ACL_EVERYONE:
584                         ae_tag = ARCHIVE_ENTRY_ACL_EVERYONE;
585                         break;
586                 default:
587                         /* Skip types that libarchive can't support. */
588                         s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
589                         continue;
590                 }
591
592                 // XXX acl type maps to allow/deny/audit/YYYY bits
593                 // XXX acl_get_entry_type_np on FreeBSD returns EINVAL for
594                 // non-NFSv4 ACLs
595                 entry_acl_type = default_entry_acl_type;
596                 r = acl_get_entry_type_np(acl_entry, &acl_type);
597                 if (r == 0) {
598                         switch (acl_type) {
599                         case ACL_ENTRY_TYPE_ALLOW:
600                                 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALLOW;
601                                 break;
602                         case ACL_ENTRY_TYPE_DENY:
603                                 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_DENY;
604                                 break;
605                         case ACL_ENTRY_TYPE_AUDIT:
606                                 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_AUDIT;
607                                 break;
608                         case ACL_ENTRY_TYPE_ALARM:
609                                 entry_acl_type = ARCHIVE_ENTRY_ACL_TYPE_ALARM;
610                                 break;
611                         }
612                 }
613
614                 /*
615                  * Libarchive stores "flag" (NFSv4 inheritance bits)
616                  * in the ae_perm bitmap.
617                  */
618                 acl_get_flagset_np(acl_entry, &acl_flagset);
619                 for (i = 0; i < (int)(sizeof(acl_inherit_map) / sizeof(acl_inherit_map[0])); ++i) {
620                         if (acl_get_flag_np(acl_flagset,
621                                             acl_inherit_map[i].platform_inherit))
622                                 ae_perm |= acl_inherit_map[i].archive_inherit;
623
624                 }
625
626                 acl_get_permset(acl_entry, &acl_permset);
627                 for (i = 0; i < (int)(sizeof(acl_perm_map) / sizeof(acl_perm_map[0])); ++i) {
628                         /*
629                          * acl_get_perm() is spelled differently on different
630                          * platforms; see above.
631                          */
632                         if (ACL_GET_PERM(acl_permset, acl_perm_map[i].platform_perm))
633                                 ae_perm |= acl_perm_map[i].archive_perm;
634                 }
635
636                 archive_entry_acl_add_entry(entry, entry_acl_type,
637                                             ae_perm, ae_tag,
638                                             ae_id, ae_name);
639
640                 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
641         }
642         return (ARCHIVE_OK);
643 }
644 #else
645 static int
646 setup_acls(struct archive_read_disk *a,
647     struct archive_entry *entry, int fd)
648 {
649         (void)a;      /* UNUSED */
650         (void)entry;  /* UNUSED */
651         (void)fd;     /* UNUSED */
652         return (ARCHIVE_OK);
653 }
654 #endif
655
656 #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
657     HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
658     (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
659
660 /*
661  * Linux and AIX extended attribute support.
662  *
663  * TODO:  By using a stack-allocated buffer for the first
664  * call to getxattr(), we might be able to avoid the second
665  * call entirely.  We only need the second call if the
666  * stack-allocated buffer is too small.  But a modest buffer
667  * of 1024 bytes or so will often be big enough.  Same applies
668  * to listxattr().
669  */
670
671
672 static int
673 setup_xattr(struct archive_read_disk *a,
674     struct archive_entry *entry, const char *name, int fd)
675 {
676         ssize_t size;
677         void *value = NULL;
678         const char *accpath;
679
680         accpath = archive_entry_sourcepath(entry);
681         if (accpath == NULL)
682                 accpath = archive_entry_pathname(entry);
683
684 #if HAVE_FGETXATTR
685         if (fd >= 0)
686                 size = fgetxattr(fd, name, NULL, 0);
687         else if (!a->follow_symlinks)
688                 size = lgetxattr(accpath, name, NULL, 0);
689         else
690                 size = getxattr(accpath, name, NULL, 0);
691 #elif HAVE_FGETEA
692         if (fd >= 0)
693                 size = fgetea(fd, name, NULL, 0);
694         else if (!a->follow_symlinks)
695                 size = lgetea(accpath, name, NULL, 0);
696         else
697                 size = getea(accpath, name, NULL, 0);
698 #endif
699
700         if (size == -1) {
701                 archive_set_error(&a->archive, errno,
702                     "Couldn't query extended attribute");
703                 return (ARCHIVE_WARN);
704         }
705
706         if (size > 0 && (value = malloc(size)) == NULL) {
707                 archive_set_error(&a->archive, errno, "Out of memory");
708                 return (ARCHIVE_FATAL);
709         }
710
711 #if HAVE_FGETXATTR
712         if (fd >= 0)
713                 size = fgetxattr(fd, name, value, size);
714         else if (!a->follow_symlinks)
715                 size = lgetxattr(accpath, name, value, size);
716         else
717                 size = getxattr(accpath, name, value, size);
718 #elif HAVE_FGETEA
719         if (fd >= 0)
720                 size = fgetea(fd, name, value, size);
721         else if (!a->follow_symlinks)
722                 size = lgetea(accpath, name, value, size);
723         else
724                 size = getea(accpath, name, value, size);
725 #endif
726
727         if (size == -1) {
728                 archive_set_error(&a->archive, errno,
729                     "Couldn't read extended attribute");
730                 return (ARCHIVE_WARN);
731         }
732
733         archive_entry_xattr_add_entry(entry, name, value, size);
734
735         free(value);
736         return (ARCHIVE_OK);
737 }
738
739 static int
740 setup_xattrs(struct archive_read_disk *a,
741     struct archive_entry *entry, int *fd)
742 {
743         char *list, *p;
744         const char *path;
745         ssize_t list_size;
746
747         path = archive_entry_sourcepath(entry);
748         if (path == NULL)
749                 path = archive_entry_pathname(entry);
750
751         if (*fd < 0 && a->tree != NULL) {
752                 if (a->follow_symlinks ||
753                     archive_entry_filetype(entry) != AE_IFLNK)
754                         *fd = a->open_on_current_dir(a->tree, path,
755                                 O_RDONLY | O_NONBLOCK);
756                 if (*fd < 0) {
757                         if (a->tree_enter_working_dir(a->tree) != 0) {
758                                 archive_set_error(&a->archive, errno,
759                                     "Couldn't access %s", path);
760                                 return (ARCHIVE_FAILED);
761                         }
762                 }
763         }
764
765 #if HAVE_FLISTXATTR
766         if (*fd >= 0)
767                 list_size = flistxattr(*fd, NULL, 0);
768         else if (!a->follow_symlinks)
769                 list_size = llistxattr(path, NULL, 0);
770         else
771                 list_size = listxattr(path, NULL, 0);
772 #elif HAVE_FLISTEA
773         if (*fd >= 0)
774                 list_size = flistea(*fd, NULL, 0);
775         else if (!a->follow_symlinks)
776                 list_size = llistea(path, NULL, 0);
777         else
778                 list_size = listea(path, NULL, 0);
779 #endif
780
781         if (list_size == -1) {
782                 if (errno == ENOTSUP || errno == ENOSYS)
783                         return (ARCHIVE_OK);
784                 archive_set_error(&a->archive, errno,
785                         "Couldn't list extended attributes");
786                 return (ARCHIVE_WARN);
787         }
788
789         if (list_size == 0)
790                 return (ARCHIVE_OK);
791
792         if ((list = malloc(list_size)) == NULL) {
793                 archive_set_error(&a->archive, errno, "Out of memory");
794                 return (ARCHIVE_FATAL);
795         }
796
797 #if HAVE_FLISTXATTR
798         if (*fd >= 0)
799                 list_size = flistxattr(*fd, list, list_size);
800         else if (!a->follow_symlinks)
801                 list_size = llistxattr(path, list, list_size);
802         else
803                 list_size = listxattr(path, list, list_size);
804 #elif HAVE_FLISTEA
805         if (*fd >= 0)
806                 list_size = flistea(*fd, list, list_size);
807         else if (!a->follow_symlinks)
808                 list_size = llistea(path, list, list_size);
809         else
810                 list_size = listea(path, list, list_size);
811 #endif
812
813         if (list_size == -1) {
814                 archive_set_error(&a->archive, errno,
815                         "Couldn't retrieve extended attributes");
816                 free(list);
817                 return (ARCHIVE_WARN);
818         }
819
820         for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
821                 if (strncmp(p, "system.", 7) == 0 ||
822                                 strncmp(p, "xfsroot.", 8) == 0)
823                         continue;
824                 setup_xattr(a, entry, p, *fd);
825         }
826
827         free(list);
828         return (ARCHIVE_OK);
829 }
830
831 #elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
832     HAVE_DECL_EXTATTR_NAMESPACE_USER
833
834 /*
835  * FreeBSD extattr interface.
836  */
837
838 /* TODO: Implement this.  Follow the Linux model above, but
839  * with FreeBSD-specific system calls, of course.  Be careful
840  * to not include the system extattrs that hold ACLs; we handle
841  * those separately.
842  */
843 static int
844 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
845     int namespace, const char *name, const char *fullname, int fd);
846
847 static int
848 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
849     int namespace, const char *name, const char *fullname, int fd)
850 {
851         ssize_t size;
852         void *value = NULL;
853         const char *accpath;
854
855         accpath = archive_entry_sourcepath(entry);
856         if (accpath == NULL)
857                 accpath = archive_entry_pathname(entry);
858
859         if (fd >= 0)
860                 size = extattr_get_fd(fd, namespace, name, NULL, 0);
861         else if (!a->follow_symlinks)
862                 size = extattr_get_link(accpath, namespace, name, NULL, 0);
863         else
864                 size = extattr_get_file(accpath, namespace, name, NULL, 0);
865
866         if (size == -1) {
867                 archive_set_error(&a->archive, errno,
868                     "Couldn't query extended attribute");
869                 return (ARCHIVE_WARN);
870         }
871
872         if (size > 0 && (value = malloc(size)) == NULL) {
873                 archive_set_error(&a->archive, errno, "Out of memory");
874                 return (ARCHIVE_FATAL);
875         }
876
877         if (fd >= 0)
878                 size = extattr_get_fd(fd, namespace, name, value, size);
879         else if (!a->follow_symlinks)
880                 size = extattr_get_link(accpath, namespace, name, value, size);
881         else
882                 size = extattr_get_file(accpath, namespace, name, value, size);
883
884         if (size == -1) {
885                 free(value);
886                 archive_set_error(&a->archive, errno,
887                     "Couldn't read extended attribute");
888                 return (ARCHIVE_WARN);
889         }
890
891         archive_entry_xattr_add_entry(entry, fullname, value, size);
892
893         free(value);
894         return (ARCHIVE_OK);
895 }
896
897 static int
898 setup_xattrs(struct archive_read_disk *a,
899     struct archive_entry *entry, int *fd)
900 {
901         char buff[512];
902         char *list, *p;
903         ssize_t list_size;
904         const char *path;
905         int namespace = EXTATTR_NAMESPACE_USER;
906
907         path = archive_entry_sourcepath(entry);
908         if (path == NULL)
909                 path = archive_entry_pathname(entry);
910
911         if (*fd < 0 && a->tree != NULL) {
912                 if (a->follow_symlinks ||
913                     archive_entry_filetype(entry) != AE_IFLNK)
914                         *fd = a->open_on_current_dir(a->tree, path,
915                                 O_RDONLY | O_NONBLOCK);
916                 if (*fd < 0) {
917                         if (a->tree_enter_working_dir(a->tree) != 0) {
918                                 archive_set_error(&a->archive, errno,
919                                     "Couldn't access %s", path);
920                                 return (ARCHIVE_FAILED);
921                         }
922                 }
923         }
924
925         if (*fd >= 0)
926                 list_size = extattr_list_fd(*fd, namespace, NULL, 0);
927         else if (!a->follow_symlinks)
928                 list_size = extattr_list_link(path, namespace, NULL, 0);
929         else
930                 list_size = extattr_list_file(path, namespace, NULL, 0);
931
932         if (list_size == -1 && errno == EOPNOTSUPP)
933                 return (ARCHIVE_OK);
934         if (list_size == -1) {
935                 archive_set_error(&a->archive, errno,
936                         "Couldn't list extended attributes");
937                 return (ARCHIVE_WARN);
938         }
939
940         if (list_size == 0)
941                 return (ARCHIVE_OK);
942
943         if ((list = malloc(list_size)) == NULL) {
944                 archive_set_error(&a->archive, errno, "Out of memory");
945                 return (ARCHIVE_FATAL);
946         }
947
948         if (*fd >= 0)
949                 list_size = extattr_list_fd(*fd, namespace, list, list_size);
950         else if (!a->follow_symlinks)
951                 list_size = extattr_list_link(path, namespace, list, list_size);
952         else
953                 list_size = extattr_list_file(path, namespace, list, list_size);
954
955         if (list_size == -1) {
956                 archive_set_error(&a->archive, errno,
957                         "Couldn't retrieve extended attributes");
958                 free(list);
959                 return (ARCHIVE_WARN);
960         }
961
962         p = list;
963         while ((p - list) < list_size) {
964                 size_t len = 255 & (int)*p;
965                 char *name;
966
967                 strcpy(buff, "user.");
968                 name = buff + strlen(buff);
969                 memcpy(name, p + 1, len);
970                 name[len] = '\0';
971                 setup_xattr(a, entry, namespace, name, buff, *fd);
972                 p += 1 + len;
973         }
974
975         free(list);
976         return (ARCHIVE_OK);
977 }
978
979 #else
980
981 /*
982  * Generic (stub) extended attribute support.
983  */
984 static int
985 setup_xattrs(struct archive_read_disk *a,
986     struct archive_entry *entry, int *fd)
987 {
988         (void)a;     /* UNUSED */
989         (void)entry; /* UNUSED */
990         (void)fd;    /* UNUSED */
991         return (ARCHIVE_OK);
992 }
993
994 #endif
995
996 #if defined(HAVE_LINUX_FIEMAP_H)
997
998 /*
999  * Linux sparse interface.
1000  *
1001  * The FIEMAP ioctl returns an "extent" for each physical allocation
1002  * on disk.  We need to process those to generate a more compact list
1003  * of logical file blocks.  We also need to be very careful to use
1004  * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes
1005  * does not report allocations for newly-written data that hasn't
1006  * been synced to disk.
1007  *
1008  * It's important to return a minimal sparse file list because we want
1009  * to not trigger sparse file extensions if we don't have to, since
1010  * not all readers support them.
1011  */
1012
1013 static int
1014 setup_sparse(struct archive_read_disk *a,
1015     struct archive_entry *entry, int *fd)
1016 {
1017         char buff[4096];
1018         struct fiemap *fm;
1019         struct fiemap_extent *fe;
1020         int64_t size;
1021         int count, do_fiemap;
1022         int exit_sts = ARCHIVE_OK;
1023
1024         if (archive_entry_filetype(entry) != AE_IFREG
1025             || archive_entry_size(entry) <= 0
1026             || archive_entry_hardlink(entry) != NULL)
1027                 return (ARCHIVE_OK);
1028
1029         if (*fd < 0) {
1030                 const char *path;
1031
1032                 path = archive_entry_sourcepath(entry);
1033                 if (path == NULL)
1034                         path = archive_entry_pathname(entry);
1035                 if (a->tree != NULL)
1036                         *fd = a->open_on_current_dir(a->tree, path,
1037                                 O_RDONLY | O_NONBLOCK);
1038                 else
1039                         *fd = open(path, O_RDONLY | O_NONBLOCK);
1040                 if (*fd < 0) {
1041                         archive_set_error(&a->archive, errno,
1042                             "Can't open `%s'", path);
1043                         return (ARCHIVE_FAILED);
1044                 }
1045         }
1046
1047         count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
1048         fm = (struct fiemap *)buff;
1049         fm->fm_start = 0;
1050         fm->fm_length = ~0ULL;;
1051         fm->fm_flags = FIEMAP_FLAG_SYNC;
1052         fm->fm_extent_count = count;
1053         do_fiemap = 1;
1054         size = archive_entry_size(entry);
1055         for (;;) {
1056                 int i, r;
1057
1058                 r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
1059                 if (r < 0) {
1060                         /* When something error happens, it is better we
1061                          * should return ARCHIVE_OK because an earlier
1062                          * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
1063                         goto exit_setup_sparse;
1064                 }
1065                 if (fm->fm_mapped_extents == 0)
1066                         break;
1067                 fe = fm->fm_extents;
1068                 for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
1069                         if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
1070                                 /* The fe_length of the last block does not
1071                                  * adjust itself to its size files. */
1072                                 int64_t length = fe->fe_length;
1073                                 if (fe->fe_logical + length > (uint64_t)size)
1074                                         length -= fe->fe_logical + length - size;
1075                                 if (fe->fe_logical == 0 && length == size) {
1076                                         /* This is not sparse. */
1077                                         do_fiemap = 0;
1078                                         break;
1079                                 }
1080                                 if (length > 0)
1081                                         archive_entry_sparse_add_entry(entry,
1082                                             fe->fe_logical, length);
1083                         }
1084                         if (fe->fe_flags & FIEMAP_EXTENT_LAST)
1085                                 do_fiemap = 0;
1086                 }
1087                 if (do_fiemap) {
1088                         fe = fm->fm_extents + fm->fm_mapped_extents -1;
1089                         fm->fm_start = fe->fe_logical + fe->fe_length;
1090                 } else
1091                         break;
1092         }
1093 exit_setup_sparse:
1094         return (exit_sts);
1095 }
1096
1097 #elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
1098
1099 /*
1100  * FreeBSD and Solaris sparse interface.
1101  */
1102
1103 static int
1104 setup_sparse(struct archive_read_disk *a,
1105     struct archive_entry *entry, int *fd)
1106 {
1107         int64_t size;
1108         off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
1109         off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
1110         int exit_sts = ARCHIVE_OK;
1111
1112         if (archive_entry_filetype(entry) != AE_IFREG
1113             || archive_entry_size(entry) <= 0
1114             || archive_entry_hardlink(entry) != NULL)
1115                 return (ARCHIVE_OK);
1116
1117         /* Does filesystem support the reporting of hole ? */
1118         if (*fd < 0 && a->tree != NULL) {
1119                 const char *path;
1120
1121                 path = archive_entry_sourcepath(entry);
1122                 if (path == NULL)
1123                         path = archive_entry_pathname(entry);
1124                 *fd = a->open_on_current_dir(a->tree, path,
1125                                 O_RDONLY | O_NONBLOCK);
1126                 if (*fd < 0) {
1127                         archive_set_error(&a->archive, errno,
1128                             "Can't open `%s'", path);
1129                         return (ARCHIVE_FAILED);
1130                 }
1131         }
1132
1133         if (*fd >= 0) {
1134                 if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
1135                         return (ARCHIVE_OK);
1136                 initial_off = lseek(*fd, 0, SEEK_CUR);
1137                 if (initial_off != 0)
1138                         lseek(*fd, 0, SEEK_SET);
1139         } else {
1140                 const char *path;
1141
1142                 path = archive_entry_sourcepath(entry);
1143                 if (path == NULL)
1144                         path = archive_entry_pathname(entry);
1145                         
1146                 if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
1147                         return (ARCHIVE_OK);
1148                 *fd = open(path, O_RDONLY | O_NONBLOCK);
1149                 if (*fd < 0) {
1150                         archive_set_error(&a->archive, errno,
1151                             "Can't open `%s'", path);
1152                         return (ARCHIVE_FAILED);
1153                 }
1154                 initial_off = 0;
1155         }
1156
1157         off_s = 0;
1158         size = archive_entry_size(entry);
1159         while (off_s < size) {
1160                 off_s = lseek(*fd, off_s, SEEK_DATA);
1161                 if (off_s == (off_t)-1) {
1162                         if (errno == ENXIO)
1163                                 break;/* no more hole */
1164                         archive_set_error(&a->archive, errno,
1165                             "lseek(SEEK_HOLE) failed");
1166                         exit_sts = ARCHIVE_FAILED;
1167                         goto exit_setup_sparse;
1168                 }
1169                 off_e = lseek(*fd, off_s, SEEK_HOLE);
1170                 if (off_e == (off_t)-1) {
1171                         if (errno == ENXIO) {
1172                                 off_e = lseek(*fd, 0, SEEK_END);
1173                                 if (off_e != (off_t)-1)
1174                                         break;/* no more data */
1175                         }
1176                         archive_set_error(&a->archive, errno,
1177                             "lseek(SEEK_DATA) failed");
1178                         exit_sts = ARCHIVE_FAILED;
1179                         goto exit_setup_sparse;
1180                 }
1181                 if (off_s == 0 && off_e == size)
1182                         break;/* This is not spase. */
1183                 archive_entry_sparse_add_entry(entry, off_s,
1184                         off_e - off_s);
1185                 off_s = off_e;
1186         }
1187 exit_setup_sparse:
1188         lseek(*fd, initial_off, SEEK_SET);
1189         return (exit_sts);
1190 }
1191
1192 #else
1193
1194 /*
1195  * Generic (stub) sparse support.
1196  */
1197 static int
1198 setup_sparse(struct archive_read_disk *a,
1199     struct archive_entry *entry, int *fd)
1200 {
1201         (void)a;     /* UNUSED */
1202         (void)entry; /* UNUSED */
1203         (void)fd;    /* UNUSED */
1204         return (ARCHIVE_OK);
1205 }
1206
1207 #endif
1208
1209 #endif /* !defined(_WIN32) || defined(__CYGWIN__) */
1210