Merge branch 'vendor/LIBARCHIVE'
[dragonfly.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: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
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_posix1e(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                 /* Lookup uname/gname */
172                 name = archive_read_disk_uname(_a, archive_entry_uid(entry));
173                 if (name != NULL)
174                         archive_entry_copy_uname(entry, name);
175                 name = archive_read_disk_gname(_a, archive_entry_gid(entry));
176                 if (name != NULL)
177                         archive_entry_copy_gname(entry, name);
178         }
179
180 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
181         /* On FreeBSD, we get flags for free with the stat. */
182         /* TODO: Does this belong in copy_stat()? */
183         if (st->st_flags != 0)
184                 archive_entry_set_fflags(entry, st->st_flags, 0);
185 #endif
186
187 #if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
188         /* Linux requires an extra ioctl to pull the flags.  Although
189          * this is an extra step, it has a nice side-effect: We get an
190          * open file descriptor which we can use in the subsequent lookups. */
191         if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
192                 if (fd < 0) {
193                         if (a->tree != NULL)
194                                 fd = a->open_on_current_dir(a->tree, path,
195                                         O_RDONLY | O_NONBLOCK);
196                         else
197                                 fd = open(path, O_RDONLY | O_NONBLOCK);
198                 }
199                 if (fd >= 0) {
200                         unsigned long stflags;
201                         r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
202                         if (r == 0 && stflags != 0)
203                                 archive_entry_set_fflags(entry, stflags, 0);
204                 }
205         }
206 #endif
207
208 #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
209         if (S_ISLNK(st->st_mode)) {
210                 size_t linkbuffer_len = st->st_size + 1;
211                 char *linkbuffer;
212                 int lnklen;
213
214                 linkbuffer = malloc(linkbuffer_len);
215                 if (linkbuffer == NULL) {
216                         archive_set_error(&a->archive, ENOMEM,
217                             "Couldn't read link data");
218                         return (ARCHIVE_FAILED);
219                 }
220                 if (a->tree != NULL) {
221 #ifdef HAVE_READLINKAT
222                         lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
223                             path, linkbuffer, linkbuffer_len);
224 #else
225                         if (a->tree_enter_working_dir(a->tree) != 0) {
226                                 archive_set_error(&a->archive, errno,
227                                     "Couldn't read link data");
228                                 free(linkbuffer);
229                                 return (ARCHIVE_FAILED);
230                         }
231                         lnklen = readlink(path, linkbuffer, linkbuffer_len);
232 #endif /* HAVE_READLINKAT */
233                 } else
234                         lnklen = readlink(path, linkbuffer, linkbuffer_len);
235                 if (lnklen < 0) {
236                         archive_set_error(&a->archive, errno,
237                             "Couldn't read link data");
238                         free(linkbuffer);
239                         return (ARCHIVE_FAILED);
240                 }
241                 linkbuffer[lnklen] = 0;
242                 archive_entry_set_symlink(entry, linkbuffer);
243                 free(linkbuffer);
244         }
245 #endif /* HAVE_READLINK || HAVE_READLINKAT */
246
247         r = setup_acls_posix1e(a, entry, &fd);
248         r1 = setup_xattrs(a, entry, &fd);
249         if (r1 < r)
250                 r = r1;
251         if (a->enable_copyfile) {
252                 r1 = setup_mac_metadata(a, entry, &fd);
253                 if (r1 < r)
254                         r = r1;
255         }
256         r1 = setup_sparse(a, entry, &fd);
257         if (r1 < r)
258                 r = r1;
259
260         /* If we opened the file earlier in this function, close it. */
261         if (initial_fd != fd)
262                 close(fd);
263         return (r);
264 }
265
266 #if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
267 /*
268  * The Mac OS "copyfile()" API copies the extended metadata for a
269  * file into a separate file in AppleDouble format (see RFC 1740).
270  *
271  * Mac OS tar and cpio implementations store this extended
272  * metadata as a separate entry just before the regular entry
273  * with a "._" prefix added to the filename.
274  *
275  * Note that this is currently done unconditionally; the tar program has
276  * an option to discard this information before the archive is written.
277  *
278  * TODO: If there's a failure, report it and return ARCHIVE_WARN.
279  */
280 static int
281 setup_mac_metadata(struct archive_read_disk *a,
282     struct archive_entry *entry, int *fd)
283 {
284         int tempfd = -1;
285         int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
286         struct stat copyfile_stat;
287         int ret = ARCHIVE_OK;
288         void *buff;
289         int have_attrs;
290         const char *name, *tempdir, *tempfile = NULL;
291
292         (void)fd; /* UNUSED */
293         name = archive_entry_sourcepath(entry);
294         if (name == NULL)
295                 name = archive_entry_pathname(entry);
296         if (name == NULL) {
297                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
298                     "Can't open file to read extended attributes: No name");
299                 return (ARCHIVE_WARN);
300         }
301
302         if (a->tree != NULL) {
303                 if (a->tree_enter_working_dir(a->tree) != 0) {
304                         archive_set_error(&a->archive, errno,
305                                     "Couldn't change dir");
306                                 return (ARCHIVE_FAILED);
307                 }
308         }
309
310         /* Short-circuit if there's nothing to do. */
311         have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
312         if (have_attrs == -1) {
313                 archive_set_error(&a->archive, errno,
314                         "Could not check extended attributes");
315                 return (ARCHIVE_WARN);
316         }
317         if (have_attrs == 0)
318                 return (ARCHIVE_OK);
319
320         tempdir = NULL;
321         if (issetugid() == 0)
322                 tempdir = getenv("TMPDIR");
323         if (tempdir == NULL)
324                 tempdir = _PATH_TMP;
325         tempfile = tempnam(tempdir, "tar.md.");
326
327         /* XXX I wish copyfile() could pack directly to a memory
328          * buffer; that would avoid the temp file here.  For that
329          * matter, it would be nice if fcopyfile() actually worked,
330          * that would reduce the many open/close races here. */
331         if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
332                 archive_set_error(&a->archive, errno,
333                     "Could not pack extended attributes");
334                 ret = ARCHIVE_WARN;
335                 goto cleanup;
336         }
337         tempfd = open(tempfile, O_RDONLY);
338         if (tempfd < 0) {
339                 archive_set_error(&a->archive, errno,
340                     "Could not open extended attribute file");
341                 ret = ARCHIVE_WARN;
342                 goto cleanup;
343         }
344         if (fstat(tempfd, &copyfile_stat)) {
345                 archive_set_error(&a->archive, errno,
346                     "Could not check size of extended attributes");
347                 ret = ARCHIVE_WARN;
348                 goto cleanup;
349         }
350         buff = malloc(copyfile_stat.st_size);
351         if (buff == NULL) {
352                 archive_set_error(&a->archive, errno,
353                     "Could not allocate memory for extended attributes");
354                 ret = ARCHIVE_WARN;
355                 goto cleanup;
356         }
357         if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
358                 archive_set_error(&a->archive, errno,
359                     "Could not read extended attributes into memory");
360                 ret = ARCHIVE_WARN;
361                 goto cleanup;
362         }
363         archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
364
365 cleanup:
366         if (tempfd >= 0)
367                 close(tempfd);
368         if (tempfile != NULL)
369                 unlink(tempfile);
370         return (ret);
371 }
372
373 #else
374
375 /*
376  * Stub implementation for non-Mac systems.
377  */
378 static int
379 setup_mac_metadata(struct archive_read_disk *a,
380     struct archive_entry *entry, int *fd)
381 {
382         (void)a; /* UNUSED */
383         (void)entry; /* UNUSED */
384         (void)fd; /* UNUSED */
385         return (ARCHIVE_OK);
386 }
387 #endif
388
389
390 #ifdef HAVE_POSIX_ACL
391 static void setup_acl_posix1e(struct archive_read_disk *a,
392     struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
393
394 static int
395 setup_acls_posix1e(struct archive_read_disk *a,
396     struct archive_entry *entry, int *fd)
397 {
398         const char      *accpath;
399         acl_t            acl;
400
401         accpath = archive_entry_sourcepath(entry);
402         if (accpath == NULL)
403                 accpath = archive_entry_pathname(entry);
404
405         archive_entry_acl_clear(entry);
406
407         if (*fd < 0 && a->tree != NULL &&
408             (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)){
409                 *fd = a->open_on_current_dir(a->tree, accpath,
410                                 O_RDONLY | O_NONBLOCK);
411                 if (*fd < 0) {
412                         archive_set_error(&a->archive, errno,
413                             "Couldn't access %s", accpath);
414                         return (ARCHIVE_FAILED);
415                 }
416         }
417
418         /* Retrieve access ACL from file. */
419         if (*fd >= 0)
420                 acl = acl_get_fd(*fd);
421 #if HAVE_ACL_GET_LINK_NP
422         else if (!a->follow_symlinks)
423                 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
424 #else
425         else if ((!a->follow_symlinks)
426             && (archive_entry_filetype(entry) == AE_IFLNK))
427                 /* We can't get the ACL of a symlink, so we assume it can't
428                    have one. */
429                 acl = NULL;
430 #endif
431         else
432                 acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
433         if (acl != NULL) {
434                 setup_acl_posix1e(a, entry, acl,
435                     ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
436                 acl_free(acl);
437         }
438
439         /* Only directories can have default ACLs. */
440         if (S_ISDIR(archive_entry_mode(entry))) {
441                 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
442                 if (acl != NULL) {
443                         setup_acl_posix1e(a, entry, acl,
444                             ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
445                         acl_free(acl);
446                 }
447         }
448         return (ARCHIVE_OK);
449 }
450
451 /*
452  * Translate POSIX.1e ACL into libarchive internal structure.
453  */
454 static void
455 setup_acl_posix1e(struct archive_read_disk *a,
456     struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
457 {
458         acl_tag_t        acl_tag;
459         acl_entry_t      acl_entry;
460         acl_permset_t    acl_permset;
461         int              s, ae_id, ae_tag, ae_perm;
462         const char      *ae_name;
463
464         s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
465         while (s == 1) {
466                 ae_id = -1;
467                 ae_name = NULL;
468
469                 acl_get_tag_type(acl_entry, &acl_tag);
470                 if (acl_tag == ACL_USER) {
471                         ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
472                         ae_name = archive_read_disk_uname(&a->archive, ae_id);
473                         ae_tag = ARCHIVE_ENTRY_ACL_USER;
474                 } else if (acl_tag == ACL_GROUP) {
475                         ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
476                         ae_name = archive_read_disk_gname(&a->archive, ae_id);
477                         ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
478                 } else if (acl_tag == ACL_MASK) {
479                         ae_tag = ARCHIVE_ENTRY_ACL_MASK;
480                 } else if (acl_tag == ACL_USER_OBJ) {
481                         ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
482                 } else if (acl_tag == ACL_GROUP_OBJ) {
483                         ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
484                 } else if (acl_tag == ACL_OTHER) {
485                         ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
486                 } else {
487                         /* Skip types that libarchive can't support. */
488                         continue;
489                 }
490
491                 acl_get_permset(acl_entry, &acl_permset);
492                 ae_perm = 0;
493                 /*
494                  * acl_get_perm() is spelled differently on different
495                  * platforms; see above.
496                  */
497                 if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
498                         ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
499                 if (ACL_GET_PERM(acl_permset, ACL_READ))
500                         ae_perm |= ARCHIVE_ENTRY_ACL_READ;
501                 if (ACL_GET_PERM(acl_permset, ACL_WRITE))
502                         ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
503
504                 archive_entry_acl_add_entry(entry,
505                     archive_entry_acl_type, ae_perm, ae_tag,
506                     ae_id, ae_name);
507
508                 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
509         }
510 }
511 #else
512 static int
513 setup_acls_posix1e(struct archive_read_disk *a,
514     struct archive_entry *entry, int *fd)
515 {
516         (void)a;      /* UNUSED */
517         (void)entry;  /* UNUSED */
518         (void)fd;     /* UNUSED */
519         return (ARCHIVE_OK);
520 }
521 #endif
522
523 #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
524     HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
525     (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
526
527 /*
528  * Linux and AIX extended attribute support.
529  *
530  * TODO:  By using a stack-allocated buffer for the first
531  * call to getxattr(), we might be able to avoid the second
532  * call entirely.  We only need the second call if the
533  * stack-allocated buffer is too small.  But a modest buffer
534  * of 1024 bytes or so will often be big enough.  Same applies
535  * to listxattr().
536  */
537
538
539 static int
540 setup_xattr(struct archive_read_disk *a,
541     struct archive_entry *entry, const char *name, int fd)
542 {
543         ssize_t size;
544         void *value = NULL;
545         const char *accpath;
546
547         accpath = archive_entry_sourcepath(entry);
548         if (accpath == NULL)
549                 accpath = archive_entry_pathname(entry);
550
551 #if HAVE_FGETXATTR
552         if (fd >= 0)
553                 size = fgetxattr(fd, name, NULL, 0);
554         else if (!a->follow_symlinks)
555                 size = lgetxattr(accpath, name, NULL, 0);
556         else
557                 size = getxattr(accpath, name, NULL, 0);
558 #elif HAVE_FGETEA
559         if (fd >= 0)
560                 size = fgetea(fd, name, NULL, 0);
561         else if (!a->follow_symlinks)
562                 size = lgetea(accpath, name, NULL, 0);
563         else
564                 size = getea(accpath, name, NULL, 0);
565 #endif
566
567         if (size == -1) {
568                 archive_set_error(&a->archive, errno,
569                     "Couldn't query extended attribute");
570                 return (ARCHIVE_WARN);
571         }
572
573         if (size > 0 && (value = malloc(size)) == NULL) {
574                 archive_set_error(&a->archive, errno, "Out of memory");
575                 return (ARCHIVE_FATAL);
576         }
577
578 #if HAVE_FGETXATTR
579         if (fd >= 0)
580                 size = fgetxattr(fd, name, value, size);
581         else if (!a->follow_symlinks)
582                 size = lgetxattr(accpath, name, value, size);
583         else
584                 size = getxattr(accpath, name, value, size);
585 #elif HAVE_FGETEA
586         if (fd >= 0)
587                 size = fgetea(fd, name, value, size);
588         else if (!a->follow_symlinks)
589                 size = lgetea(accpath, name, value, size);
590         else
591                 size = getea(accpath, name, value, size);
592 #endif
593
594         if (size == -1) {
595                 archive_set_error(&a->archive, errno,
596                     "Couldn't read extended attribute");
597                 return (ARCHIVE_WARN);
598         }
599
600         archive_entry_xattr_add_entry(entry, name, value, size);
601
602         free(value);
603         return (ARCHIVE_OK);
604 }
605
606 static int
607 setup_xattrs(struct archive_read_disk *a,
608     struct archive_entry *entry, int *fd)
609 {
610         char *list, *p;
611         const char *path;
612         ssize_t list_size;
613
614         path = archive_entry_sourcepath(entry);
615         if (path == NULL)
616                 path = archive_entry_pathname(entry);
617
618         if (*fd < 0 && a->tree != NULL) {
619                 if (a->follow_symlinks ||
620                     archive_entry_filetype(entry) != AE_IFLNK)
621                         *fd = a->open_on_current_dir(a->tree, path,
622                                 O_RDONLY | O_NONBLOCK);
623                 if (*fd < 0) {
624                         if (a->tree_enter_working_dir(a->tree) != 0) {
625                                 archive_set_error(&a->archive, errno,
626                                     "Couldn't access %s", path);
627                                 return (ARCHIVE_FAILED);
628                         }
629                 }
630         }
631
632 #if HAVE_FLISTXATTR
633         if (*fd >= 0)
634                 list_size = flistxattr(*fd, NULL, 0);
635         else if (!a->follow_symlinks)
636                 list_size = llistxattr(path, NULL, 0);
637         else
638                 list_size = listxattr(path, NULL, 0);
639 #elif HAVE_FLISTEA
640         if (*fd >= 0)
641                 list_size = flistea(*fd, NULL, 0);
642         else if (!a->follow_symlinks)
643                 list_size = llistea(path, NULL, 0);
644         else
645                 list_size = listea(path, NULL, 0);
646 #endif
647
648         if (list_size == -1) {
649                 if (errno == ENOTSUP || errno == ENOSYS)
650                         return (ARCHIVE_OK);
651                 archive_set_error(&a->archive, errno,
652                         "Couldn't list extended attributes");
653                 return (ARCHIVE_WARN);
654         }
655
656         if (list_size == 0)
657                 return (ARCHIVE_OK);
658
659         if ((list = malloc(list_size)) == NULL) {
660                 archive_set_error(&a->archive, errno, "Out of memory");
661                 return (ARCHIVE_FATAL);
662         }
663
664 #if HAVE_FLISTXATTR
665         if (*fd >= 0)
666                 list_size = flistxattr(*fd, list, list_size);
667         else if (!a->follow_symlinks)
668                 list_size = llistxattr(path, list, list_size);
669         else
670                 list_size = listxattr(path, list, list_size);
671 #elif HAVE_FLISTEA
672         if (*fd >= 0)
673                 list_size = flistea(*fd, list, list_size);
674         else if (!a->follow_symlinks)
675                 list_size = llistea(path, list, list_size);
676         else
677                 list_size = listea(path, list, list_size);
678 #endif
679
680         if (list_size == -1) {
681                 archive_set_error(&a->archive, errno,
682                         "Couldn't retrieve extended attributes");
683                 free(list);
684                 return (ARCHIVE_WARN);
685         }
686
687         for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
688                 if (strncmp(p, "system.", 7) == 0 ||
689                                 strncmp(p, "xfsroot.", 8) == 0)
690                         continue;
691                 setup_xattr(a, entry, p, *fd);
692         }
693
694         free(list);
695         return (ARCHIVE_OK);
696 }
697
698 #elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
699     HAVE_DECL_EXTATTR_NAMESPACE_USER
700
701 /*
702  * FreeBSD extattr interface.
703  */
704
705 /* TODO: Implement this.  Follow the Linux model above, but
706  * with FreeBSD-specific system calls, of course.  Be careful
707  * to not include the system extattrs that hold ACLs; we handle
708  * those separately.
709  */
710 static int
711 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
712     int namespace, const char *name, const char *fullname, int fd);
713
714 static int
715 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
716     int namespace, const char *name, const char *fullname, int fd)
717 {
718         ssize_t size;
719         void *value = NULL;
720         const char *accpath;
721
722         accpath = archive_entry_sourcepath(entry);
723         if (accpath == NULL)
724                 accpath = archive_entry_pathname(entry);
725
726         if (fd >= 0)
727                 size = extattr_get_fd(fd, namespace, name, NULL, 0);
728         else if (!a->follow_symlinks)
729                 size = extattr_get_link(accpath, namespace, name, NULL, 0);
730         else
731                 size = extattr_get_file(accpath, namespace, name, NULL, 0);
732
733         if (size == -1) {
734                 archive_set_error(&a->archive, errno,
735                     "Couldn't query extended attribute");
736                 return (ARCHIVE_WARN);
737         }
738
739         if (size > 0 && (value = malloc(size)) == NULL) {
740                 archive_set_error(&a->archive, errno, "Out of memory");
741                 return (ARCHIVE_FATAL);
742         }
743
744         if (fd >= 0)
745                 size = extattr_get_fd(fd, namespace, name, value, size);
746         else if (!a->follow_symlinks)
747                 size = extattr_get_link(accpath, namespace, name, value, size);
748         else
749                 size = extattr_get_file(accpath, namespace, name, value, size);
750
751         if (size == -1) {
752                 free(value);
753                 archive_set_error(&a->archive, errno,
754                     "Couldn't read extended attribute");
755                 return (ARCHIVE_WARN);
756         }
757
758         archive_entry_xattr_add_entry(entry, fullname, value, size);
759
760         free(value);
761         return (ARCHIVE_OK);
762 }
763
764 static int
765 setup_xattrs(struct archive_read_disk *a,
766     struct archive_entry *entry, int *fd)
767 {
768         char buff[512];
769         char *list, *p;
770         ssize_t list_size;
771         const char *path;
772         int namespace = EXTATTR_NAMESPACE_USER;
773
774         path = archive_entry_sourcepath(entry);
775         if (path == NULL)
776                 path = archive_entry_pathname(entry);
777
778         if (*fd < 0 && a->tree != NULL) {
779                 if (a->follow_symlinks ||
780                     archive_entry_filetype(entry) != AE_IFLNK)
781                         *fd = a->open_on_current_dir(a->tree, path,
782                                 O_RDONLY | O_NONBLOCK);
783                 if (*fd < 0) {
784                         if (a->tree_enter_working_dir(a->tree) != 0) {
785                                 archive_set_error(&a->archive, errno,
786                                     "Couldn't access %s", path);
787                                 return (ARCHIVE_FAILED);
788                         }
789                 }
790         }
791
792         if (*fd >= 0)
793                 list_size = extattr_list_fd(*fd, namespace, NULL, 0);
794         else if (!a->follow_symlinks)
795                 list_size = extattr_list_link(path, namespace, NULL, 0);
796         else
797                 list_size = extattr_list_file(path, namespace, NULL, 0);
798
799         if (list_size == -1 && errno == EOPNOTSUPP)
800                 return (ARCHIVE_OK);
801         if (list_size == -1) {
802                 archive_set_error(&a->archive, errno,
803                         "Couldn't list extended attributes");
804                 return (ARCHIVE_WARN);
805         }
806
807         if (list_size == 0)
808                 return (ARCHIVE_OK);
809
810         if ((list = malloc(list_size)) == NULL) {
811                 archive_set_error(&a->archive, errno, "Out of memory");
812                 return (ARCHIVE_FATAL);
813         }
814
815         if (*fd >= 0)
816                 list_size = extattr_list_fd(*fd, namespace, list, list_size);
817         else if (!a->follow_symlinks)
818                 list_size = extattr_list_link(path, namespace, list, list_size);
819         else
820                 list_size = extattr_list_file(path, namespace, list, list_size);
821
822         if (list_size == -1) {
823                 archive_set_error(&a->archive, errno,
824                         "Couldn't retrieve extended attributes");
825                 free(list);
826                 return (ARCHIVE_WARN);
827         }
828
829         p = list;
830         while ((p - list) < list_size) {
831                 size_t len = 255 & (int)*p;
832                 char *name;
833
834                 strcpy(buff, "user.");
835                 name = buff + strlen(buff);
836                 memcpy(name, p + 1, len);
837                 name[len] = '\0';
838                 setup_xattr(a, entry, namespace, name, buff, *fd);
839                 p += 1 + len;
840         }
841
842         free(list);
843         return (ARCHIVE_OK);
844 }
845
846 #else
847
848 /*
849  * Generic (stub) extended attribute support.
850  */
851 static int
852 setup_xattrs(struct archive_read_disk *a,
853     struct archive_entry *entry, int *fd)
854 {
855         (void)a;     /* UNUSED */
856         (void)entry; /* UNUSED */
857         (void)fd;    /* UNUSED */
858         return (ARCHIVE_OK);
859 }
860
861 #endif
862
863 #if defined(HAVE_LINUX_FIEMAP_H)
864
865 /*
866  * Linux sparse interface.
867  *
868  * The FIEMAP ioctl returns an "extent" for each physical allocation
869  * on disk.  We need to process those to generate a more compact list
870  * of logical file blocks.  We also need to be very careful to use
871  * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes
872  * does not report allocations for newly-written data that hasn't
873  * been synced to disk.
874  *
875  * It's important to return a minimal sparse file list because we want
876  * to not trigger sparse file extensions if we don't have to, since
877  * not all readers support them.
878  */
879
880 static int
881 setup_sparse(struct archive_read_disk *a,
882     struct archive_entry *entry, int *fd)
883 {
884         char buff[4096];
885         struct fiemap *fm;
886         struct fiemap_extent *fe;
887         int64_t size;
888         int count, do_fiemap;
889         int exit_sts = ARCHIVE_OK;
890
891         if (archive_entry_filetype(entry) != AE_IFREG
892             || archive_entry_size(entry) <= 0
893             || archive_entry_hardlink(entry) != NULL)
894                 return (ARCHIVE_OK);
895
896         if (*fd < 0) {
897                 const char *path;
898
899                 path = archive_entry_sourcepath(entry);
900                 if (path == NULL)
901                         path = archive_entry_pathname(entry);
902                 if (a->tree != NULL)
903                         *fd = a->open_on_current_dir(a->tree, path,
904                                 O_RDONLY | O_NONBLOCK);
905                 else
906                         *fd = open(path, O_RDONLY | O_NONBLOCK);
907                 if (*fd < 0) {
908                         archive_set_error(&a->archive, errno,
909                             "Can't open `%s'", path);
910                         return (ARCHIVE_FAILED);
911                 }
912         }
913
914         count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
915         fm = (struct fiemap *)buff;
916         fm->fm_start = 0;
917         fm->fm_length = ~0ULL;;
918         fm->fm_flags = FIEMAP_FLAG_SYNC;
919         fm->fm_extent_count = count;
920         do_fiemap = 1;
921         size = archive_entry_size(entry);
922         for (;;) {
923                 int i, r;
924
925                 r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
926                 if (r < 0) {
927                         /* When something error happens, it is better we
928                          * should return ARCHIVE_OK because an earlier
929                          * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */
930                         goto exit_setup_sparse;
931                 }
932                 if (fm->fm_mapped_extents == 0)
933                         break;
934                 fe = fm->fm_extents;
935                 for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
936                         if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
937                                 /* The fe_length of the last block does not
938                                  * adjust itself to its size files. */
939                                 int64_t length = fe->fe_length;
940                                 if (fe->fe_logical + length > (uint64_t)size)
941                                         length -= fe->fe_logical + length - size;
942                                 if (fe->fe_logical == 0 && length == size) {
943                                         /* This is not sparse. */
944                                         do_fiemap = 0;
945                                         break;
946                                 }
947                                 if (length > 0)
948                                         archive_entry_sparse_add_entry(entry,
949                                             fe->fe_logical, length);
950                         }
951                         if (fe->fe_flags & FIEMAP_EXTENT_LAST)
952                                 do_fiemap = 0;
953                 }
954                 if (do_fiemap) {
955                         fe = fm->fm_extents + fm->fm_mapped_extents -1;
956                         fm->fm_start = fe->fe_logical + fe->fe_length;
957                 } else
958                         break;
959         }
960 exit_setup_sparse:
961         return (exit_sts);
962 }
963
964 #elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
965
966 /*
967  * FreeBSD and Solaris sparse interface.
968  */
969
970 static int
971 setup_sparse(struct archive_read_disk *a,
972     struct archive_entry *entry, int *fd)
973 {
974         int64_t size;
975         off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
976         off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
977         int exit_sts = ARCHIVE_OK;
978
979         if (archive_entry_filetype(entry) != AE_IFREG
980             || archive_entry_size(entry) <= 0
981             || archive_entry_hardlink(entry) != NULL)
982                 return (ARCHIVE_OK);
983
984         /* Does filesystem support the reporting of hole ? */
985         if (*fd < 0 && a->tree != NULL) {
986                 const char *path;
987
988                 path = archive_entry_sourcepath(entry);
989                 if (path == NULL)
990                         path = archive_entry_pathname(entry);
991                 *fd = a->open_on_current_dir(a->tree, path,
992                                 O_RDONLY | O_NONBLOCK);
993                 if (*fd < 0) {
994                         archive_set_error(&a->archive, errno,
995                             "Can't open `%s'", path);
996                         return (ARCHIVE_FAILED);
997                 }
998         }
999
1000         if (*fd >= 0) {
1001                 if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
1002                         return (ARCHIVE_OK);
1003                 initial_off = lseek(*fd, 0, SEEK_CUR);
1004                 if (initial_off != 0)
1005                         lseek(*fd, 0, SEEK_SET);
1006         } else {
1007                 const char *path;
1008
1009                 path = archive_entry_sourcepath(entry);
1010                 if (path == NULL)
1011                         path = archive_entry_pathname(entry);
1012                         
1013                 if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
1014                         return (ARCHIVE_OK);
1015                 *fd = open(path, O_RDONLY | O_NONBLOCK);
1016                 if (*fd < 0) {
1017                         archive_set_error(&a->archive, errno,
1018                             "Can't open `%s'", path);
1019                         return (ARCHIVE_FAILED);
1020                 }
1021                 initial_off = 0;
1022         }
1023
1024         off_s = 0;
1025         size = archive_entry_size(entry);
1026         while (off_s < size) {
1027                 off_s = lseek(*fd, off_s, SEEK_DATA);
1028                 if (off_s == (off_t)-1) {
1029                         if (errno == ENXIO)
1030                                 break;/* no more hole */
1031                         archive_set_error(&a->archive, errno,
1032                             "lseek(SEEK_HOLE) failed");
1033                         exit_sts = ARCHIVE_FAILED;
1034                         goto exit_setup_sparse;
1035                 }
1036                 off_e = lseek(*fd, off_s, SEEK_HOLE);
1037                 if (off_e == (off_t)-1) {
1038                         if (errno == ENXIO) {
1039                                 off_e = lseek(*fd, 0, SEEK_END);
1040                                 if (off_e != (off_t)-1)
1041                                         break;/* no more data */
1042                         }
1043                         archive_set_error(&a->archive, errno,
1044                             "lseek(SEEK_DATA) failed");
1045                         exit_sts = ARCHIVE_FAILED;
1046                         goto exit_setup_sparse;
1047                 }
1048                 if (off_s == 0 && off_e == size)
1049                         break;/* This is not spase. */
1050                 archive_entry_sparse_add_entry(entry, off_s,
1051                         off_e - off_s);
1052                 off_s = off_e;
1053         }
1054 exit_setup_sparse:
1055         lseek(*fd, initial_off, SEEK_SET);
1056         return (exit_sts);
1057 }
1058
1059 #else
1060
1061 /*
1062  * Generic (stub) sparse support.
1063  */
1064 static int
1065 setup_sparse(struct archive_read_disk *a,
1066     struct archive_entry *entry, int *fd)
1067 {
1068         (void)a;     /* UNUSED */
1069         (void)entry; /* UNUSED */
1070         (void)fd;    /* UNUSED */
1071         return (ARCHIVE_OK);
1072 }
1073
1074 #endif
1075
1076 #endif /* !defined(_WIN32) || defined(__CYGWIN__) */
1077