]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/libarchive/libarchive/archive_read_disk_entry_from_file.c
MFH r324148:
[FreeBSD/stable/10.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  * Copyright (c) 2016 Martin Matuska
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
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
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,
20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
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
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
25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27
28 #include "archive_platform.h"
29 __FBSDID("$FreeBSD");
30
31 /* This is the tree-walking code for POSIX systems. */
32 #if !defined(_WIN32) || defined(__CYGWIN__)
33
34 #ifdef HAVE_SYS_TYPES_H
35 #include <sys/types.h>
36 #endif
37 #ifdef HAVE_SYS_EXTATTR_H
38 #include <sys/extattr.h>
39 #endif
40 #ifdef HAVE_SYS_IOCTL_H
41 #include <sys/ioctl.h>
42 #endif
43 #ifdef HAVE_SYS_PARAM_H
44 #include <sys/param.h>
45 #endif
46 #ifdef HAVE_SYS_STAT_H
47 #include <sys/stat.h>
48 #endif
49 #if defined(HAVE_SYS_XATTR_H)
50 #include <sys/xattr.h>
51 #elif defined(HAVE_ATTR_XATTR_H)
52 #include <attr/xattr.h>
53 #endif
54 #ifdef HAVE_SYS_EA_H
55 #include <sys/ea.h>
56 #endif
57 #ifdef HAVE_COPYFILE_H
58 #include <copyfile.h>
59 #endif
60 #ifdef HAVE_ERRNO_H
61 #include <errno.h>
62 #endif
63 #ifdef HAVE_FCNTL_H
64 #include <fcntl.h>
65 #endif
66 #ifdef HAVE_LIMITS_H
67 #include <limits.h>
68 #endif
69 #ifdef HAVE_LINUX_TYPES_H
70 #include <linux/types.h>
71 #endif
72 #ifdef HAVE_LINUX_FIEMAP_H
73 #include <linux/fiemap.h>
74 #endif
75 #ifdef HAVE_LINUX_FS_H
76 #include <linux/fs.h>
77 #endif
78 /*
79  * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
80  * As the include guards don't agree, the order of include is important.
81  */
82 #ifdef HAVE_LINUX_EXT2_FS_H
83 #include <linux/ext2_fs.h>      /* for Linux file flags */
84 #endif
85 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
86 #include <ext2fs/ext2_fs.h>     /* Linux file flags, broken on Cygwin */
87 #endif
88 #ifdef HAVE_PATHS_H
89 #include <paths.h>
90 #endif
91 #ifdef HAVE_UNISTD_H
92 #include <unistd.h>
93 #endif
94
95 #include "archive.h"
96 #include "archive_entry.h"
97 #include "archive_private.h"
98 #include "archive_read_disk_private.h"
99
100 #ifndef O_CLOEXEC
101 #define O_CLOEXEC       0
102 #endif
103
104 static int setup_mac_metadata(struct archive_read_disk *,
105     struct archive_entry *, int *fd);
106 static int setup_xattrs(struct archive_read_disk *,
107     struct archive_entry *, int *fd);
108 static int setup_sparse(struct archive_read_disk *,
109     struct archive_entry *, int *fd);
110 #if defined(HAVE_LINUX_FIEMAP_H)
111 static int setup_sparse_fiemap(struct archive_read_disk *,
112     struct archive_entry *, int *fd);
113 #endif
114
115 #if !ARCHIVE_ACL_SUPPORT
116 int
117 archive_read_disk_entry_setup_acls(struct archive_read_disk *a,
118     struct archive_entry *entry, int *fd)
119 {
120         (void)a;      /* UNUSED */
121         (void)entry;  /* UNUSED */
122         (void)fd;     /* UNUSED */
123         return (ARCHIVE_OK);
124 }
125 #endif
126
127 /*
128  * Enter working directory and return working pathname of archive_entry.
129  * If a pointer to an integer is provided and its value is below zero
130  * open a file descriptor on this pathname.
131  */
132 const char *
133 archive_read_disk_entry_setup_path(struct archive_read_disk *a,
134     struct archive_entry *entry, int *fd)
135 {
136         const char *path;
137
138         path = archive_entry_sourcepath(entry);
139
140         if (path == NULL || (a->tree != NULL &&
141             a->tree_enter_working_dir(a->tree) != 0))
142                 path = archive_entry_pathname(entry);
143         if (path == NULL) {
144                 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
145                    "Couldn't determine path");
146         } else if (fd != NULL && *fd < 0 && a->tree != NULL &&
147             (a->follow_symlinks || archive_entry_filetype(entry) != AE_IFLNK)) {
148                 *fd = a->open_on_current_dir(a->tree, path,
149                     O_RDONLY | O_NONBLOCK);
150         }
151         return (path);
152 }
153
154 int
155 archive_read_disk_entry_from_file(struct archive *_a,
156     struct archive_entry *entry,
157     int fd,
158     const struct stat *st)
159 {
160         struct archive_read_disk *a = (struct archive_read_disk *)_a;
161         const char *path, *name;
162         struct stat s;
163         int initial_fd = fd;
164         int r, r1;
165
166         archive_clear_error(_a);
167         path = archive_entry_sourcepath(entry);
168         if (path == NULL)
169                 path = archive_entry_pathname(entry);
170
171         if (a->tree == NULL) {
172                 if (st == NULL) {
173 #if HAVE_FSTAT
174                         if (fd >= 0) {
175                                 if (fstat(fd, &s) != 0) {
176                                         archive_set_error(&a->archive, errno,
177                                             "Can't fstat");
178                                         return (ARCHIVE_FAILED);
179                                 }
180                         } else
181 #endif
182 #if HAVE_LSTAT
183                         if (!a->follow_symlinks) {
184                                 if (lstat(path, &s) != 0) {
185                                         archive_set_error(&a->archive, errno,
186                                             "Can't lstat %s", path);
187                                         return (ARCHIVE_FAILED);
188                                 }
189                         } else
190 #endif
191                         if (stat(path, &s) != 0) {
192                                 archive_set_error(&a->archive, errno,
193                                     "Can't stat %s", path);
194                                 return (ARCHIVE_FAILED);
195                         }
196                         st = &s;
197                 }
198                 archive_entry_copy_stat(entry, st);
199         }
200
201         /* Lookup uname/gname */
202         name = archive_read_disk_uname(_a, archive_entry_uid(entry));
203         if (name != NULL)
204                 archive_entry_copy_uname(entry, name);
205         name = archive_read_disk_gname(_a, archive_entry_gid(entry));
206         if (name != NULL)
207                 archive_entry_copy_gname(entry, name);
208
209 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
210         /* On FreeBSD, we get flags for free with the stat. */
211         /* TODO: Does this belong in copy_stat()? */
212         if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 && st->st_flags != 0)
213                 archive_entry_set_fflags(entry, st->st_flags, 0);
214 #endif
215
216 #if (defined(FS_IOC_GETFLAGS) && defined(HAVE_WORKING_FS_IOC_GETFLAGS)) || \
217     (defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS))
218         /* Linux requires an extra ioctl to pull the flags.  Although
219          * this is an extra step, it has a nice side-effect: We get an
220          * open file descriptor which we can use in the subsequent lookups. */
221         if ((a->flags & ARCHIVE_READDISK_NO_FFLAGS) == 0 &&
222             (S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
223                 if (fd < 0) {
224                         if (a->tree != NULL)
225                                 fd = a->open_on_current_dir(a->tree, path,
226                                         O_RDONLY | O_NONBLOCK | O_CLOEXEC);
227                         else
228                                 fd = open(path, O_RDONLY | O_NONBLOCK |
229                                                 O_CLOEXEC);
230                         __archive_ensure_cloexec_flag(fd);
231                 }
232                 if (fd >= 0) {
233                         int stflags;
234                         r = ioctl(fd,
235 #if defined(FS_IOC_GETFLAGS)
236                             FS_IOC_GETFLAGS,
237 #else
238                             EXT2_IOC_GETFLAGS,
239 #endif
240                             &stflags);
241                         if (r == 0 && stflags != 0)
242                                 archive_entry_set_fflags(entry, stflags, 0);
243                 }
244         }
245 #endif
246
247 #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
248         if (S_ISLNK(st->st_mode)) {
249                 size_t linkbuffer_len = st->st_size + 1;
250                 char *linkbuffer;
251                 int lnklen;
252
253                 linkbuffer = malloc(linkbuffer_len);
254                 if (linkbuffer == NULL) {
255                         archive_set_error(&a->archive, ENOMEM,
256                             "Couldn't read link data");
257                         return (ARCHIVE_FAILED);
258                 }
259                 if (a->tree != NULL) {
260 #ifdef HAVE_READLINKAT
261                         lnklen = readlinkat(a->tree_current_dir_fd(a->tree),
262                             path, linkbuffer, linkbuffer_len);
263 #else
264                         if (a->tree_enter_working_dir(a->tree) != 0) {
265                                 archive_set_error(&a->archive, errno,
266                                     "Couldn't read link data");
267                                 free(linkbuffer);
268                                 return (ARCHIVE_FAILED);
269                         }
270                         lnklen = readlink(path, linkbuffer, linkbuffer_len);
271 #endif /* HAVE_READLINKAT */
272                 } else
273                         lnklen = readlink(path, linkbuffer, linkbuffer_len);
274                 if (lnklen < 0) {
275                         archive_set_error(&a->archive, errno,
276                             "Couldn't read link data");
277                         free(linkbuffer);
278                         return (ARCHIVE_FAILED);
279                 }
280                 linkbuffer[lnklen] = 0;
281                 archive_entry_set_symlink(entry, linkbuffer);
282                 free(linkbuffer);
283         }
284 #endif /* HAVE_READLINK || HAVE_READLINKAT */
285
286         r = 0;
287         if ((a->flags & ARCHIVE_READDISK_NO_ACL) == 0)
288                 r = archive_read_disk_entry_setup_acls(a, entry, &fd);
289         if ((a->flags & ARCHIVE_READDISK_NO_XATTR) == 0) {
290                 r1 = setup_xattrs(a, entry, &fd);
291                 if (r1 < r)
292                         r = r1;
293         }
294         if (a->flags & ARCHIVE_READDISK_MAC_COPYFILE) {
295                 r1 = setup_mac_metadata(a, entry, &fd);
296                 if (r1 < r)
297                         r = r1;
298         }
299         r1 = setup_sparse(a, entry, &fd);
300         if (r1 < r)
301                 r = r1;
302
303         /* If we opened the file earlier in this function, close it. */
304         if (initial_fd != fd)
305                 close(fd);
306         return (r);
307 }
308
309 #if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
310 /*
311  * The Mac OS "copyfile()" API copies the extended metadata for a
312  * file into a separate file in AppleDouble format (see RFC 1740).
313  *
314  * Mac OS tar and cpio implementations store this extended
315  * metadata as a separate entry just before the regular entry
316  * with a "._" prefix added to the filename.
317  *
318  * Note that this is currently done unconditionally; the tar program has
319  * an option to discard this information before the archive is written.
320  *
321  * TODO: If there's a failure, report it and return ARCHIVE_WARN.
322  */
323 static int
324 setup_mac_metadata(struct archive_read_disk *a,
325     struct archive_entry *entry, int *fd)
326 {
327         int tempfd = -1;
328         int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
329         struct stat copyfile_stat;
330         int ret = ARCHIVE_OK;
331         void *buff = NULL;
332         int have_attrs;
333         const char *name, *tempdir;
334         struct archive_string tempfile;
335
336         (void)fd; /* UNUSED */
337
338         name = archive_read_disk_entry_setup_path(a, entry, NULL);
339         if (name == NULL)
340                 return (ARCHIVE_WARN);
341
342         /* Short-circuit if there's nothing to do. */
343         have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
344         if (have_attrs == -1) {
345                 archive_set_error(&a->archive, errno,
346                         "Could not check extended attributes");
347                 return (ARCHIVE_WARN);
348         }
349         if (have_attrs == 0)
350                 return (ARCHIVE_OK);
351
352         tempdir = NULL;
353         if (issetugid() == 0)
354                 tempdir = getenv("TMPDIR");
355         if (tempdir == NULL)
356                 tempdir = _PATH_TMP;
357         archive_string_init(&tempfile);
358         archive_strcpy(&tempfile, tempdir);
359         archive_strcat(&tempfile, "tar.md.XXXXXX");
360         tempfd = mkstemp(tempfile.s);
361         if (tempfd < 0) {
362                 archive_set_error(&a->archive, errno,
363                     "Could not open extended attribute file");
364                 ret = ARCHIVE_WARN;
365                 goto cleanup;
366         }
367         __archive_ensure_cloexec_flag(tempfd);
368
369         /* XXX I wish copyfile() could pack directly to a memory
370          * buffer; that would avoid the temp file here.  For that
371          * matter, it would be nice if fcopyfile() actually worked,
372          * that would reduce the many open/close races here. */
373         if (copyfile(name, tempfile.s, 0, copyfile_flags | COPYFILE_PACK)) {
374                 archive_set_error(&a->archive, errno,
375                     "Could not pack extended attributes");
376                 ret = ARCHIVE_WARN;
377                 goto cleanup;
378         }
379         if (fstat(tempfd, &copyfile_stat)) {
380                 archive_set_error(&a->archive, errno,
381                     "Could not check size of extended attributes");
382                 ret = ARCHIVE_WARN;
383                 goto cleanup;
384         }
385         buff = malloc(copyfile_stat.st_size);
386         if (buff == NULL) {
387                 archive_set_error(&a->archive, errno,
388                     "Could not allocate memory for extended attributes");
389                 ret = ARCHIVE_WARN;
390                 goto cleanup;
391         }
392         if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
393                 archive_set_error(&a->archive, errno,
394                     "Could not read extended attributes into memory");
395                 ret = ARCHIVE_WARN;
396                 goto cleanup;
397         }
398         archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
399
400 cleanup:
401         if (tempfd >= 0) {
402                 close(tempfd);
403                 unlink(tempfile.s);
404         }
405         archive_string_free(&tempfile);
406         free(buff);
407         return (ret);
408 }
409
410 #else
411
412 /*
413  * Stub implementation for non-Mac systems.
414  */
415 static int
416 setup_mac_metadata(struct archive_read_disk *a,
417     struct archive_entry *entry, int *fd)
418 {
419         (void)a; /* UNUSED */
420         (void)entry; /* UNUSED */
421         (void)fd; /* UNUSED */
422         return (ARCHIVE_OK);
423 }
424 #endif
425
426 #if ARCHIVE_XATTR_LINUX || ARCHIVE_XATTR_DARWIN || ARCHIVE_XATTR_AIX
427
428 /*
429  * Linux, Darwin and AIX extended attribute support.
430  *
431  * TODO:  By using a stack-allocated buffer for the first
432  * call to getxattr(), we might be able to avoid the second
433  * call entirely.  We only need the second call if the
434  * stack-allocated buffer is too small.  But a modest buffer
435  * of 1024 bytes or so will often be big enough.  Same applies
436  * to listxattr().
437  */
438
439
440 static int
441 setup_xattr(struct archive_read_disk *a,
442     struct archive_entry *entry, const char *name, int fd, const char *accpath)
443 {
444         ssize_t size;
445         void *value = NULL;
446
447
448         if (fd >= 0) {
449 #if ARCHIVE_XATTR_LINUX
450                 size = fgetxattr(fd, name, NULL, 0);
451 #elif ARCHIVE_XATTR_DARWIN
452                 size = fgetxattr(fd, name, NULL, 0, 0, 0);
453 #elif ARCHIVE_XATTR_AIX
454                 size = fgetea(fd, name, NULL, 0);
455 #endif
456         } else if (!a->follow_symlinks) {
457 #if ARCHIVE_XATTR_LINUX
458                 size = lgetxattr(accpath, name, NULL, 0);
459 #elif ARCHIVE_XATTR_DARWIN
460                 size = getxattr(accpath, name, NULL, 0, 0, XATTR_NOFOLLOW);
461 #elif ARCHIVE_XATTR_AIX
462                 size = lgetea(accpath, name, NULL, 0);
463 #endif
464         } else {
465 #if ARCHIVE_XATTR_LINUX
466                 size = getxattr(accpath, name, NULL, 0);
467 #elif ARCHIVE_XATTR_DARWIN
468                 size = getxattr(accpath, name, NULL, 0, 0, 0);
469 #elif ARCHIVE_XATTR_AIX
470                 size = getea(accpath, name, NULL, 0);
471 #endif
472         }
473
474         if (size == -1) {
475                 archive_set_error(&a->archive, errno,
476                     "Couldn't query extended attribute");
477                 return (ARCHIVE_WARN);
478         }
479
480         if (size > 0 && (value = malloc(size)) == NULL) {
481                 archive_set_error(&a->archive, errno, "Out of memory");
482                 return (ARCHIVE_FATAL);
483         }
484
485
486         if (fd >= 0) {
487 #if ARCHIVE_XATTR_LINUX
488                 size = fgetxattr(fd, name, value, size);
489 #elif ARCHIVE_XATTR_DARWIN
490                 size = fgetxattr(fd, name, value, size, 0, 0);
491 #elif ARCHIVE_XATTR_AIX
492                 size = fgetea(fd, name, value, size);
493 #endif
494         } else if (!a->follow_symlinks) {
495 #if ARCHIVE_XATTR_LINUX
496                 size = lgetxattr(accpath, name, value, size);
497 #elif ARCHIVE_XATTR_DARWIN
498                 size = getxattr(accpath, name, value, size, 0, XATTR_NOFOLLOW);
499 #elif ARCHIVE_XATTR_AIX
500                 size = lgetea(accpath, name, value, size);
501 #endif
502         } else {
503 #if ARCHIVE_XATTR_LINUX
504                 size = getxattr(accpath, name, value, size);
505 #elif ARCHIVE_XATTR_DARWIN
506                 size = getxattr(accpath, name, value, size, 0, 0);
507 #elif ARCHIVE_XATTR_AIX
508                 size = getea(accpath, name, value, size);
509 #endif
510         }
511
512         if (size == -1) {
513                 archive_set_error(&a->archive, errno,
514                     "Couldn't read extended attribute");
515                 return (ARCHIVE_WARN);
516         }
517
518         archive_entry_xattr_add_entry(entry, name, value, size);
519
520         free(value);
521         return (ARCHIVE_OK);
522 }
523
524 static int
525 setup_xattrs(struct archive_read_disk *a,
526     struct archive_entry *entry, int *fd)
527 {
528         char *list, *p;
529         const char *path;
530         ssize_t list_size;
531
532         path = NULL;
533
534         if (*fd < 0) {
535                 path = archive_read_disk_entry_setup_path(a, entry, fd);
536                 if (path == NULL)
537                         return (ARCHIVE_WARN);
538         }
539
540         if (*fd >= 0) {
541 #if ARCHIVE_XATTR_LINUX
542                 list_size = flistxattr(*fd, NULL, 0);
543 #elif ARCHIVE_XATTR_DARWIN
544                 list_size = flistxattr(*fd, NULL, 0, 0);
545 #elif ARCHIVE_XATTR_AIX
546                 list_size = flistea(*fd, NULL, 0);
547 #endif
548         } else if (!a->follow_symlinks) {
549 #if ARCHIVE_XATTR_LINUX
550                 list_size = llistxattr(path, NULL, 0);
551 #elif ARCHIVE_XATTR_DARWIN
552                 list_size = listxattr(path, NULL, 0, XATTR_NOFOLLOW);
553 #elif ARCHIVE_XATTR_AIX
554                 list_size = llistea(path, NULL, 0);
555 #endif
556         } else {
557 #if ARCHIVE_XATTR_LINUX
558                 list_size = listxattr(path, NULL, 0);
559 #elif ARCHIVE_XATTR_DARWIN
560                 list_size = listxattr(path, NULL, 0, 0);
561 #elif ARCHIVE_XATTR_AIX
562                 list_size = listea(path, NULL, 0);
563 #endif
564         }
565
566         if (list_size == -1) {
567                 if (errno == ENOTSUP || errno == ENOSYS)
568                         return (ARCHIVE_OK);
569                 archive_set_error(&a->archive, errno,
570                         "Couldn't list extended attributes");
571                 return (ARCHIVE_WARN);
572         }
573
574         if (list_size == 0)
575                 return (ARCHIVE_OK);
576
577         if ((list = malloc(list_size)) == NULL) {
578                 archive_set_error(&a->archive, errno, "Out of memory");
579                 return (ARCHIVE_FATAL);
580         }
581
582         if (*fd >= 0) {
583 #if ARCHIVE_XATTR_LINUX
584                 list_size = flistxattr(*fd, list, list_size);
585 #elif ARCHIVE_XATTR_DARWIN
586                 list_size = flistxattr(*fd, list, list_size, 0);
587 #elif ARCHIVE_XATTR_AIX
588                 list_size = flistea(*fd, list, list_size);
589 #endif
590         } else if (!a->follow_symlinks) {
591 #if ARCHIVE_XATTR_LINUX
592                 list_size = llistxattr(path, list, list_size);
593 #elif ARCHIVE_XATTR_DARWIN
594                 list_size = listxattr(path, list, list_size, XATTR_NOFOLLOW);
595 #elif ARCHIVE_XATTR_AIX
596                 list_size = llistea(path, list, list_size);
597 #endif
598         } else {
599 #if ARCHIVE_XATTR_LINUX
600                 list_size = listxattr(path, list, list_size);
601 #elif ARCHIVE_XATTR_DARWIN
602                 list_size = listxattr(path, list, list_size, 0);
603 #elif ARCHIVE_XATTR_AIX
604                 list_size = listea(path, list, list_size);
605 #endif
606         }
607
608         if (list_size == -1) {
609                 archive_set_error(&a->archive, errno,
610                         "Couldn't retrieve extended attributes");
611                 free(list);
612                 return (ARCHIVE_WARN);
613         }
614
615         for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
616                 if (strncmp(p, "system.", 7) == 0 ||
617                                 strncmp(p, "xfsroot.", 8) == 0)
618                         continue;
619                 setup_xattr(a, entry, p, *fd, path);
620         }
621
622         free(list);
623         return (ARCHIVE_OK);
624 }
625
626 #elif ARCHIVE_XATTR_FREEBSD
627
628 /*
629  * FreeBSD extattr interface.
630  */
631
632 /* TODO: Implement this.  Follow the Linux model above, but
633  * with FreeBSD-specific system calls, of course.  Be careful
634  * to not include the system extattrs that hold ACLs; we handle
635  * those separately.
636  */
637 static int
638 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
639     int namespace, const char *name, const char *fullname, int fd,
640     const char *path);
641
642 static int
643 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
644     int namespace, const char *name, const char *fullname, int fd,
645     const char *accpath)
646 {
647         ssize_t size;
648         void *value = NULL;
649
650         if (fd >= 0)
651                 size = extattr_get_fd(fd, namespace, name, NULL, 0);
652         else if (!a->follow_symlinks)
653                 size = extattr_get_link(accpath, namespace, name, NULL, 0);
654         else
655                 size = extattr_get_file(accpath, namespace, name, NULL, 0);
656
657         if (size == -1) {
658                 archive_set_error(&a->archive, errno,
659                     "Couldn't query extended attribute");
660                 return (ARCHIVE_WARN);
661         }
662
663         if (size > 0 && (value = malloc(size)) == NULL) {
664                 archive_set_error(&a->archive, errno, "Out of memory");
665                 return (ARCHIVE_FATAL);
666         }
667
668         if (fd >= 0)
669                 size = extattr_get_fd(fd, namespace, name, value, size);
670         else if (!a->follow_symlinks)
671                 size = extattr_get_link(accpath, namespace, name, value, size);
672         else
673                 size = extattr_get_file(accpath, namespace, name, value, size);
674
675         if (size == -1) {
676                 free(value);
677                 archive_set_error(&a->archive, errno,
678                     "Couldn't read extended attribute");
679                 return (ARCHIVE_WARN);
680         }
681
682         archive_entry_xattr_add_entry(entry, fullname, value, size);
683
684         free(value);
685         return (ARCHIVE_OK);
686 }
687
688 static int
689 setup_xattrs(struct archive_read_disk *a,
690     struct archive_entry *entry, int *fd)
691 {
692         char buff[512];
693         char *list, *p;
694         ssize_t list_size;
695         const char *path;
696         int namespace = EXTATTR_NAMESPACE_USER;
697
698         path = NULL;
699
700         if (*fd < 0) {
701                 path = archive_read_disk_entry_setup_path(a, entry, fd);
702                 if (path == NULL)
703                         return (ARCHIVE_WARN);
704         }
705
706         if (*fd >= 0)
707                 list_size = extattr_list_fd(*fd, namespace, NULL, 0);
708         else if (!a->follow_symlinks)
709                 list_size = extattr_list_link(path, namespace, NULL, 0);
710         else
711                 list_size = extattr_list_file(path, namespace, NULL, 0);
712
713         if (list_size == -1 && errno == EOPNOTSUPP)
714                 return (ARCHIVE_OK);
715         if (list_size == -1) {
716                 archive_set_error(&a->archive, errno,
717                         "Couldn't list extended attributes");
718                 return (ARCHIVE_WARN);
719         }
720
721         if (list_size == 0)
722                 return (ARCHIVE_OK);
723
724         if ((list = malloc(list_size)) == NULL) {
725                 archive_set_error(&a->archive, errno, "Out of memory");
726                 return (ARCHIVE_FATAL);
727         }
728
729         if (*fd >= 0)
730                 list_size = extattr_list_fd(*fd, namespace, list, list_size);
731         else if (!a->follow_symlinks)
732                 list_size = extattr_list_link(path, namespace, list, list_size);
733         else
734                 list_size = extattr_list_file(path, namespace, list, list_size);
735
736         if (list_size == -1) {
737                 archive_set_error(&a->archive, errno,
738                         "Couldn't retrieve extended attributes");
739                 free(list);
740                 return (ARCHIVE_WARN);
741         }
742
743         p = list;
744         while ((p - list) < list_size) {
745                 size_t len = 255 & (int)*p;
746                 char *name;
747
748                 strcpy(buff, "user.");
749                 name = buff + strlen(buff);
750                 memcpy(name, p + 1, len);
751                 name[len] = '\0';
752                 setup_xattr(a, entry, namespace, name, buff, *fd, path);
753                 p += 1 + len;
754         }
755
756         free(list);
757         return (ARCHIVE_OK);
758 }
759
760 #else
761
762 /*
763  * Generic (stub) extended attribute support.
764  */
765 static int
766 setup_xattrs(struct archive_read_disk *a,
767     struct archive_entry *entry, int *fd)
768 {
769         (void)a;     /* UNUSED */
770         (void)entry; /* UNUSED */
771         (void)fd;    /* UNUSED */
772         return (ARCHIVE_OK);
773 }
774
775 #endif
776
777 #if defined(HAVE_LINUX_FIEMAP_H)
778
779 /*
780  * Linux FIEMAP sparse interface.
781  *
782  * The FIEMAP ioctl returns an "extent" for each physical allocation
783  * on disk.  We need to process those to generate a more compact list
784  * of logical file blocks.  We also need to be very careful to use
785  * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes
786  * does not report allocations for newly-written data that hasn't
787  * been synced to disk.
788  *
789  * It's important to return a minimal sparse file list because we want
790  * to not trigger sparse file extensions if we don't have to, since
791  * not all readers support them.
792  */
793
794 static int
795 setup_sparse_fiemap(struct archive_read_disk *a,
796     struct archive_entry *entry, int *fd)
797 {
798         char buff[4096];
799         struct fiemap *fm;
800         struct fiemap_extent *fe;
801         int64_t size;
802         int count, do_fiemap, iters;
803         int exit_sts = ARCHIVE_OK;
804         const char *path;
805
806         if (archive_entry_filetype(entry) != AE_IFREG
807             || archive_entry_size(entry) <= 0
808             || archive_entry_hardlink(entry) != NULL)
809                 return (ARCHIVE_OK);
810
811         if (*fd < 0) {
812                 path = archive_read_disk_entry_setup_path(a, entry, NULL);
813                 if (path == NULL)
814                         return (ARCHIVE_FAILED);
815
816                 if (a->tree != NULL)
817                         *fd = a->open_on_current_dir(a->tree, path,
818                                 O_RDONLY | O_NONBLOCK | O_CLOEXEC);
819                 else
820                         *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
821                 if (*fd < 0) {
822                         archive_set_error(&a->archive, errno,
823                             "Can't open `%s'", path);
824                         return (ARCHIVE_FAILED);
825                 }
826                 __archive_ensure_cloexec_flag(*fd);
827         }
828
829         /* Initialize buffer to avoid the error valgrind complains about. */
830         memset(buff, 0, sizeof(buff));
831         count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
832         fm = (struct fiemap *)buff;
833         fm->fm_start = 0;
834         fm->fm_length = ~0ULL;;
835         fm->fm_flags = FIEMAP_FLAG_SYNC;
836         fm->fm_extent_count = count;
837         do_fiemap = 1;
838         size = archive_entry_size(entry);
839         for (iters = 0; ; ++iters) {
840                 int i, r;
841
842                 r = ioctl(*fd, FS_IOC_FIEMAP, fm); 
843                 if (r < 0) {
844                         /* When something error happens, it is better we
845                          * should return ARCHIVE_OK because an earlier
846                          * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */
847                         goto exit_setup_sparse_fiemap;
848                 }
849                 if (fm->fm_mapped_extents == 0) {
850                         if (iters == 0) {
851                                 /* Fully sparse file; insert a zero-length "data" entry */
852                                 archive_entry_sparse_add_entry(entry, 0, 0);
853                         }
854                         break;
855                 }
856                 fe = fm->fm_extents;
857                 for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) {
858                         if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
859                                 /* The fe_length of the last block does not
860                                  * adjust itself to its size files. */
861                                 int64_t length = fe->fe_length;
862                                 if (fe->fe_logical + length > (uint64_t)size)
863                                         length -= fe->fe_logical + length - size;
864                                 if (fe->fe_logical == 0 && length == size) {
865                                         /* This is not sparse. */
866                                         do_fiemap = 0;
867                                         break;
868                                 }
869                                 if (length > 0)
870                                         archive_entry_sparse_add_entry(entry,
871                                             fe->fe_logical, length);
872                         }
873                         if (fe->fe_flags & FIEMAP_EXTENT_LAST)
874                                 do_fiemap = 0;
875                 }
876                 if (do_fiemap) {
877                         fe = fm->fm_extents + fm->fm_mapped_extents -1;
878                         fm->fm_start = fe->fe_logical + fe->fe_length;
879                 } else
880                         break;
881         }
882 exit_setup_sparse_fiemap:
883         return (exit_sts);
884 }
885
886 #if !defined(SEEK_HOLE) || !defined(SEEK_DATA)
887 static int
888 setup_sparse(struct archive_read_disk *a,
889     struct archive_entry *entry, int *fd)
890 {
891         return setup_sparse_fiemap(a, entry, fd);
892 }
893 #endif
894 #endif  /* defined(HAVE_LINUX_FIEMAP_H) */
895
896 #if defined(SEEK_HOLE) && defined(SEEK_DATA)
897
898 /*
899  * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris)
900  */
901
902 static int
903 setup_sparse(struct archive_read_disk *a,
904     struct archive_entry *entry, int *fd)
905 {
906         int64_t size;
907         off_t initial_off;
908         off_t off_s, off_e;
909         int exit_sts = ARCHIVE_OK;
910         int check_fully_sparse = 0;
911         const char *path;
912
913         if (archive_entry_filetype(entry) != AE_IFREG
914             || archive_entry_size(entry) <= 0
915             || archive_entry_hardlink(entry) != NULL)
916                 return (ARCHIVE_OK);
917
918         /* Does filesystem support the reporting of hole ? */
919         if (*fd < 0)
920                 path = archive_read_disk_entry_setup_path(a, entry, fd);
921         else
922                 path = NULL;
923
924         if (*fd >= 0) {
925 #ifdef _PC_MIN_HOLE_SIZE
926                 if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0)
927                         return (ARCHIVE_OK);
928 #endif
929                 initial_off = lseek(*fd, 0, SEEK_CUR);
930                 if (initial_off != 0)
931                         lseek(*fd, 0, SEEK_SET);
932         } else {
933                 if (path == NULL)
934                         return (ARCHIVE_FAILED);
935 #ifdef _PC_MIN_HOLE_SIZE
936                 if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
937                         return (ARCHIVE_OK);
938 #endif
939                 *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
940                 if (*fd < 0) {
941                         archive_set_error(&a->archive, errno,
942                             "Can't open `%s'", path);
943                         return (ARCHIVE_FAILED);
944                 }
945                 __archive_ensure_cloexec_flag(*fd);
946                 initial_off = 0;
947         }
948
949 #ifndef _PC_MIN_HOLE_SIZE
950         /* Check if the underlying filesystem supports seek hole */
951         off_s = lseek(*fd, 0, SEEK_HOLE);
952         if (off_s < 0)
953 #if defined(HAVE_LINUX_FIEMAP_H)
954                 return setup_sparse_fiemap(a, entry, fd);
955 #else
956                 goto exit_setup_sparse;
957 #endif
958         else if (off_s > 0)
959                 lseek(*fd, 0, SEEK_SET);
960 #endif
961
962         off_s = 0;
963         size = archive_entry_size(entry);
964         while (off_s < size) {
965                 off_s = lseek(*fd, off_s, SEEK_DATA);
966                 if (off_s == (off_t)-1) {
967                         if (errno == ENXIO) {
968                                 /* no more hole */
969                                 if (archive_entry_sparse_count(entry) == 0) {
970                                         /* Potentially a fully-sparse file. */
971                                         check_fully_sparse = 1;
972                                 }
973                                 break;
974                         }
975                         archive_set_error(&a->archive, errno,
976                             "lseek(SEEK_HOLE) failed");
977                         exit_sts = ARCHIVE_FAILED;
978                         goto exit_setup_sparse;
979                 }
980                 off_e = lseek(*fd, off_s, SEEK_HOLE);
981                 if (off_e == (off_t)-1) {
982                         if (errno == ENXIO) {
983                                 off_e = lseek(*fd, 0, SEEK_END);
984                                 if (off_e != (off_t)-1)
985                                         break;/* no more data */
986                         }
987                         archive_set_error(&a->archive, errno,
988                             "lseek(SEEK_DATA) failed");
989                         exit_sts = ARCHIVE_FAILED;
990                         goto exit_setup_sparse;
991                 }
992                 if (off_s == 0 && off_e == size)
993                         break;/* This is not sparse. */
994                 archive_entry_sparse_add_entry(entry, off_s,
995                         off_e - off_s);
996                 off_s = off_e;
997         }
998
999         if (check_fully_sparse) {
1000                 if (lseek(*fd, 0, SEEK_HOLE) == 0 &&
1001                         lseek(*fd, 0, SEEK_END) == size) {
1002                         /* Fully sparse file; insert a zero-length "data" entry */
1003                         archive_entry_sparse_add_entry(entry, 0, 0);
1004                 }
1005         }
1006 exit_setup_sparse:
1007         lseek(*fd, initial_off, SEEK_SET);
1008         return (exit_sts);
1009 }
1010
1011 #elif !defined(HAVE_LINUX_FIEMAP_H)
1012
1013 /*
1014  * Generic (stub) sparse support.
1015  */
1016 static int
1017 setup_sparse(struct archive_read_disk *a,
1018     struct archive_entry *entry, int *fd)
1019 {
1020         (void)a;     /* UNUSED */
1021         (void)entry; /* UNUSED */
1022         (void)fd;    /* UNUSED */
1023         return (ARCHIVE_OK);
1024 }
1025
1026 #endif
1027
1028 #endif /* !defined(_WIN32) || defined(__CYGWIN__) */
1029