2 * Copyright (c) 2003-2009 Tim Kientzle
3 * Copyright (c) 2010 Michihiro NAKAJIMA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
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.
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.
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 $");
30 /* This is the tree-walking code for POSIX systems. */
31 #if !defined(_WIN32) || defined(__CYGWIN__)
33 #ifdef HAVE_SYS_TYPES_H
34 /* Mac OSX requires sys/types.h before sys/acl.h. */
35 #include <sys/types.h>
40 #ifdef HAVE_SYS_EXTATTR_H
41 #include <sys/extattr.h>
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
46 #ifdef HAVE_SYS_PARAM_H
47 #include <sys/param.h>
49 #ifdef HAVE_SYS_STAT_H
52 #ifdef HAVE_SYS_XATTR_H
53 #include <sys/xattr.h>
58 #ifdef HAVE_ACL_LIBACL_H
59 #include <acl/libacl.h>
61 #ifdef HAVE_ATTR_XATTR_H
62 #include <attr/xattr.h>
64 #ifdef HAVE_COPYFILE_H
76 #ifdef HAVE_LINUX_FIEMAP_H
77 #include <linux/fiemap.h>
79 #ifdef HAVE_LINUX_FS_H
83 * Some Linux distributions have both linux/ext2_fs.h and ext2fs/ext2_fs.h.
84 * As the include guards don't agree, the order of include is important.
86 #ifdef HAVE_LINUX_EXT2_FS_H
87 #include <linux/ext2_fs.h> /* for Linux file flags */
89 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
90 #include <ext2fs/ext2_fs.h> /* Linux file flags, broken on Cygwin */
100 #include "archive_entry.h"
101 #include "archive_private.h"
102 #include "archive_read_disk_private.h"
105 * Linux and FreeBSD plug this obvious hole in POSIX.1e in
108 #if HAVE_ACL_GET_PERM
109 #define ACL_GET_PERM acl_get_perm
110 #elif HAVE_ACL_GET_PERM_NP
111 #define ACL_GET_PERM acl_get_perm_np
114 static int setup_acls_posix1e(struct archive_read_disk *,
115 struct archive_entry *, int fd);
116 static int setup_mac_metadata(struct archive_read_disk *,
117 struct archive_entry *, int fd);
118 static int setup_xattrs(struct archive_read_disk *,
119 struct archive_entry *, int fd);
120 static int setup_sparse(struct archive_read_disk *,
121 struct archive_entry *, int fd);
124 archive_read_disk_entry_from_file(struct archive *_a,
125 struct archive_entry *entry,
127 const struct stat *st)
129 struct archive_read_disk *a = (struct archive_read_disk *)_a;
130 const char *path, *name;
135 archive_clear_error(_a);
136 path = archive_entry_sourcepath(entry);
138 path = archive_entry_pathname(entry);
140 if (a->tree == NULL) {
144 if (fstat(fd, &s) != 0) {
145 archive_set_error(&a->archive, errno,
147 return (ARCHIVE_FAILED);
152 if (!a->follow_symlinks) {
153 if (lstat(path, &s) != 0) {
154 archive_set_error(&a->archive, errno,
155 "Can't lstat %s", path);
156 return (ARCHIVE_FAILED);
160 if (stat(path, &s) != 0) {
161 archive_set_error(&a->archive, errno,
162 "Can't stat %s", path);
163 return (ARCHIVE_FAILED);
167 archive_entry_copy_stat(entry, st);
170 /* Lookup uname/gname */
171 name = archive_read_disk_uname(_a, archive_entry_uid(entry));
173 archive_entry_copy_uname(entry, name);
174 name = archive_read_disk_gname(_a, archive_entry_gid(entry));
176 archive_entry_copy_gname(entry, name);
178 #ifdef HAVE_STRUCT_STAT_ST_FLAGS
179 /* On FreeBSD, we get flags for free with the stat. */
180 /* TODO: Does this belong in copy_stat()? */
181 if (st->st_flags != 0)
182 archive_entry_set_fflags(entry, st->st_flags, 0);
185 #if defined(EXT2_IOC_GETFLAGS) && defined(HAVE_WORKING_EXT2_IOC_GETFLAGS)
186 /* Linux requires an extra ioctl to pull the flags. Although
187 * this is an extra step, it has a nice side-effect: We get an
188 * open file descriptor which we can use in the subsequent lookups. */
189 if ((S_ISREG(st->st_mode) || S_ISDIR(st->st_mode))) {
191 fd = open(path, O_RDONLY | O_NONBLOCK);
193 unsigned long stflags;
194 int r = ioctl(fd, EXT2_IOC_GETFLAGS, &stflags);
195 if (r == 0 && stflags != 0)
196 archive_entry_set_fflags(entry, stflags, 0);
201 #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
202 if (S_ISLNK(st->st_mode)) {
203 size_t linkbuffer_len = st->st_size + 1;
207 linkbuffer = malloc(linkbuffer_len);
208 if (linkbuffer == NULL) {
209 archive_set_error(&a->archive, ENOMEM,
210 "Couldn't read link data");
211 return (ARCHIVE_FAILED);
213 #ifdef HAVE_READLINKAT
214 if (a->entry_wd_fd >= 0)
215 lnklen = readlinkat(a->entry_wd_fd, path,
216 linkbuffer, linkbuffer_len);
218 #endif /* HAVE_READLINKAT */
219 lnklen = readlink(path, linkbuffer, linkbuffer_len);
221 archive_set_error(&a->archive, errno,
222 "Couldn't read link data");
224 return (ARCHIVE_FAILED);
226 linkbuffer[lnklen] = 0;
227 archive_entry_set_symlink(entry, linkbuffer);
230 #endif /* HAVE_READLINK || HAVE_READLINKAT */
232 r = setup_acls_posix1e(a, entry, fd);
233 r1 = setup_xattrs(a, entry, fd);
236 r1 = setup_mac_metadata(a, entry, fd);
239 r1 = setup_sparse(a, entry, fd);
243 /* If we opened the file earlier in this function, close it. */
244 if (initial_fd != fd)
249 #if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
251 * The Mac OS "copyfile()" API copies the extended metadata for a
252 * file into a separate file in AppleDouble format (see RFC 1740).
254 * Mac OS tar and cpio implementations store this extended
255 * metadata as a separate entry just before the regular entry
256 * with a "._" prefix added to the filename.
258 * Note that this is currently done unconditionally; the tar program has
259 * an option to discard this information before the archive is written.
261 * TODO: If there's a failure, report it and return ARCHIVE_WARN.
264 setup_mac_metadata(struct archive_read_disk *a,
265 struct archive_entry *entry, int fd)
268 int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
269 struct stat copyfile_stat;
270 int ret = ARCHIVE_OK;
273 const char *name, *tempdir, *tempfile = NULL;
275 name = archive_entry_sourcepath(entry);
277 name = archive_entry_pathname(entry);
279 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
280 "Can't open file to read extended attributes: No name");
281 return (ARCHIVE_WARN);
284 /* Short-circuit if there's nothing to do. */
285 have_attrs = copyfile(name, NULL, 0, copyfile_flags | COPYFILE_CHECK);
286 if (have_attrs == -1) {
287 archive_set_error(&a->archive, errno,
288 "Could not check extended attributes");
289 return (ARCHIVE_WARN);
295 if (issetugid() == 0)
296 tempdir = getenv("TMPDIR");
299 tempfile = tempnam(tempdir, "tar.md.");
301 /* XXX I wish copyfile() could pack directly to a memory
302 * buffer; that would avoid the temp file here. For that
303 * matter, it would be nice if fcopyfile() actually worked,
304 * that would reduce the many open/close races here. */
305 if (copyfile(name, tempfile, 0, copyfile_flags | COPYFILE_PACK)) {
306 archive_set_error(&a->archive, errno,
307 "Could not pack extended attributes");
311 tempfd = open(tempfile, O_RDONLY);
313 archive_set_error(&a->archive, errno,
314 "Could not open extended attribute file");
318 if (fstat(tempfd, ©file_stat)) {
319 archive_set_error(&a->archive, errno,
320 "Could not check size of extended attributes");
324 buff = malloc(copyfile_stat.st_size);
326 archive_set_error(&a->archive, errno,
327 "Could not allocate memory for extended attributes");
331 if (copyfile_stat.st_size != read(tempfd, buff, copyfile_stat.st_size)) {
332 archive_set_error(&a->archive, errno,
333 "Could not read extended attributes into memory");
337 archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
342 if (tempfile != NULL)
350 * Stub implementation for non-Mac systems.
353 setup_mac_metadata(struct archive_read_disk *a,
354 struct archive_entry *entry, int fd)
356 (void)a; /* UNUSED */
357 (void)entry; /* UNUSED */
358 (void)fd; /* UNUSED */
364 #ifdef HAVE_POSIX_ACL
365 static void setup_acl_posix1e(struct archive_read_disk *a,
366 struct archive_entry *entry, acl_t acl, int archive_entry_acl_type);
369 setup_acls_posix1e(struct archive_read_disk *a,
370 struct archive_entry *entry, int fd)
375 accpath = archive_entry_sourcepath(entry);
377 accpath = archive_entry_pathname(entry);
379 archive_entry_acl_clear(entry);
381 /* Retrieve access ACL from file. */
383 acl = acl_get_fd(fd);
384 #if HAVE_ACL_GET_LINK_NP
385 else if (!a->follow_symlinks)
386 acl = acl_get_link_np(accpath, ACL_TYPE_ACCESS);
388 else if ((!a->follow_symlinks)
389 && (archive_entry_filetype(entry) == AE_IFLNK))
390 /* We can't get the ACL of a symlink, so we assume it can't
395 acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
397 setup_acl_posix1e(a, entry, acl,
398 ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
402 /* Only directories can have default ACLs. */
403 if (S_ISDIR(archive_entry_mode(entry))) {
404 acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
406 setup_acl_posix1e(a, entry, acl,
407 ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
415 * Translate POSIX.1e ACL into libarchive internal structure.
418 setup_acl_posix1e(struct archive_read_disk *a,
419 struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
422 acl_entry_t acl_entry;
423 acl_permset_t acl_permset;
424 int s, ae_id, ae_tag, ae_perm;
427 s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
432 acl_get_tag_type(acl_entry, &acl_tag);
433 if (acl_tag == ACL_USER) {
434 ae_id = (int)*(uid_t *)acl_get_qualifier(acl_entry);
435 ae_name = archive_read_disk_uname(&a->archive, ae_id);
436 ae_tag = ARCHIVE_ENTRY_ACL_USER;
437 } else if (acl_tag == ACL_GROUP) {
438 ae_id = (int)*(gid_t *)acl_get_qualifier(acl_entry);
439 ae_name = archive_read_disk_gname(&a->archive, ae_id);
440 ae_tag = ARCHIVE_ENTRY_ACL_GROUP;
441 } else if (acl_tag == ACL_MASK) {
442 ae_tag = ARCHIVE_ENTRY_ACL_MASK;
443 } else if (acl_tag == ACL_USER_OBJ) {
444 ae_tag = ARCHIVE_ENTRY_ACL_USER_OBJ;
445 } else if (acl_tag == ACL_GROUP_OBJ) {
446 ae_tag = ARCHIVE_ENTRY_ACL_GROUP_OBJ;
447 } else if (acl_tag == ACL_OTHER) {
448 ae_tag = ARCHIVE_ENTRY_ACL_OTHER;
450 /* Skip types that libarchive can't support. */
454 acl_get_permset(acl_entry, &acl_permset);
457 * acl_get_perm() is spelled differently on different
458 * platforms; see above.
460 if (ACL_GET_PERM(acl_permset, ACL_EXECUTE))
461 ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE;
462 if (ACL_GET_PERM(acl_permset, ACL_READ))
463 ae_perm |= ARCHIVE_ENTRY_ACL_READ;
464 if (ACL_GET_PERM(acl_permset, ACL_WRITE))
465 ae_perm |= ARCHIVE_ENTRY_ACL_WRITE;
467 archive_entry_acl_add_entry(entry,
468 archive_entry_acl_type, ae_perm, ae_tag,
471 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
476 setup_acls_posix1e(struct archive_read_disk *a,
477 struct archive_entry *entry, int fd)
479 (void)a; /* UNUSED */
480 (void)entry; /* UNUSED */
481 (void)fd; /* UNUSED */
486 #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
487 HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
488 (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
491 * Linux and AIX extended attribute support.
493 * TODO: By using a stack-allocated buffer for the first
494 * call to getxattr(), we might be able to avoid the second
495 * call entirely. We only need the second call if the
496 * stack-allocated buffer is too small. But a modest buffer
497 * of 1024 bytes or so will often be big enough. Same applies
503 setup_xattr(struct archive_read_disk *a,
504 struct archive_entry *entry, const char *name, int fd)
510 accpath = archive_entry_sourcepath(entry);
512 accpath = archive_entry_pathname(entry);
516 size = fgetxattr(fd, name, NULL, 0);
517 else if (!a->follow_symlinks)
518 size = lgetxattr(accpath, name, NULL, 0);
520 size = getxattr(accpath, name, NULL, 0);
523 size = fgetea(fd, name, NULL, 0);
524 else if (!a->follow_symlinks)
525 size = lgetea(accpath, name, NULL, 0);
527 size = getea(accpath, name, NULL, 0);
531 archive_set_error(&a->archive, errno,
532 "Couldn't query extended attribute");
533 return (ARCHIVE_WARN);
536 if (size > 0 && (value = malloc(size)) == NULL) {
537 archive_set_error(&a->archive, errno, "Out of memory");
538 return (ARCHIVE_FATAL);
543 size = fgetxattr(fd, name, value, size);
544 else if (!a->follow_symlinks)
545 size = lgetxattr(accpath, name, value, size);
547 size = getxattr(accpath, name, value, size);
550 size = fgetea(fd, name, value, size);
551 else if (!a->follow_symlinks)
552 size = lgetea(accpath, name, value, size);
554 size = getea(accpath, name, value, size);
558 archive_set_error(&a->archive, errno,
559 "Couldn't read extended attribute");
560 return (ARCHIVE_WARN);
563 archive_entry_xattr_add_entry(entry, name, value, size);
570 setup_xattrs(struct archive_read_disk *a,
571 struct archive_entry *entry, int fd)
577 path = archive_entry_sourcepath(entry);
579 path = archive_entry_pathname(entry);
583 list_size = flistxattr(fd, NULL, 0);
584 else if (!a->follow_symlinks)
585 list_size = llistxattr(path, NULL, 0);
587 list_size = listxattr(path, NULL, 0);
590 list_size = flistea(fd, NULL, 0);
591 else if (!a->follow_symlinks)
592 list_size = llistea(path, NULL, 0);
594 list_size = listea(path, NULL, 0);
597 if (list_size == -1) {
598 if (errno == ENOTSUP || errno == ENOSYS)
600 archive_set_error(&a->archive, errno,
601 "Couldn't list extended attributes");
602 return (ARCHIVE_WARN);
608 if ((list = malloc(list_size)) == NULL) {
609 archive_set_error(&a->archive, errno, "Out of memory");
610 return (ARCHIVE_FATAL);
615 list_size = flistxattr(fd, list, list_size);
616 else if (!a->follow_symlinks)
617 list_size = llistxattr(path, list, list_size);
619 list_size = listxattr(path, list, list_size);
622 list_size = flistea(fd, list, list_size);
623 else if (!a->follow_symlinks)
624 list_size = llistea(path, list, list_size);
626 list_size = listea(path, list, list_size);
629 if (list_size == -1) {
630 archive_set_error(&a->archive, errno,
631 "Couldn't retrieve extended attributes");
633 return (ARCHIVE_WARN);
636 for (p = list; (p - list) < list_size; p += strlen(p) + 1) {
637 if (strncmp(p, "system.", 7) == 0 ||
638 strncmp(p, "xfsroot.", 8) == 0)
640 setup_xattr(a, entry, p, fd);
647 #elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
648 HAVE_DECL_EXTATTR_NAMESPACE_USER
651 * FreeBSD extattr interface.
654 /* TODO: Implement this. Follow the Linux model above, but
655 * with FreeBSD-specific system calls, of course. Be careful
656 * to not include the system extattrs that hold ACLs; we handle
660 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
661 int namespace, const char *name, const char *fullname, int fd);
664 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
665 int namespace, const char *name, const char *fullname, int fd)
671 accpath = archive_entry_sourcepath(entry);
673 accpath = archive_entry_pathname(entry);
676 size = extattr_get_fd(fd, namespace, name, NULL, 0);
677 else if (!a->follow_symlinks)
678 size = extattr_get_link(accpath, namespace, name, NULL, 0);
680 size = extattr_get_file(accpath, namespace, name, NULL, 0);
683 archive_set_error(&a->archive, errno,
684 "Couldn't query extended attribute");
685 return (ARCHIVE_WARN);
688 if (size > 0 && (value = malloc(size)) == NULL) {
689 archive_set_error(&a->archive, errno, "Out of memory");
690 return (ARCHIVE_FATAL);
694 size = extattr_get_fd(fd, namespace, name, value, size);
695 else if (!a->follow_symlinks)
696 size = extattr_get_link(accpath, namespace, name, value, size);
698 size = extattr_get_file(accpath, namespace, name, value, size);
701 archive_set_error(&a->archive, errno,
702 "Couldn't read extended attribute");
703 return (ARCHIVE_WARN);
706 archive_entry_xattr_add_entry(entry, fullname, value, size);
713 setup_xattrs(struct archive_read_disk *a,
714 struct archive_entry *entry, int fd)
720 int namespace = EXTATTR_NAMESPACE_USER;
722 path = archive_entry_sourcepath(entry);
724 path = archive_entry_pathname(entry);
727 list_size = extattr_list_fd(fd, namespace, NULL, 0);
728 else if (!a->follow_symlinks)
729 list_size = extattr_list_link(path, namespace, NULL, 0);
731 list_size = extattr_list_file(path, namespace, NULL, 0);
733 if (list_size == -1 && errno == EOPNOTSUPP)
735 if (list_size == -1) {
736 archive_set_error(&a->archive, errno,
737 "Couldn't list extended attributes");
738 return (ARCHIVE_WARN);
744 if ((list = malloc(list_size)) == NULL) {
745 archive_set_error(&a->archive, errno, "Out of memory");
746 return (ARCHIVE_FATAL);
750 list_size = extattr_list_fd(fd, namespace, list, list_size);
751 else if (!a->follow_symlinks)
752 list_size = extattr_list_link(path, namespace, list, list_size);
754 list_size = extattr_list_file(path, namespace, list, list_size);
756 if (list_size == -1) {
757 archive_set_error(&a->archive, errno,
758 "Couldn't retrieve extended attributes");
760 return (ARCHIVE_WARN);
764 while ((p - list) < list_size) {
765 size_t len = 255 & (int)*p;
768 strcpy(buff, "user.");
769 name = buff + strlen(buff);
770 memcpy(name, p + 1, len);
772 setup_xattr(a, entry, namespace, name, buff, fd);
783 * Generic (stub) extended attribute support.
786 setup_xattrs(struct archive_read_disk *a,
787 struct archive_entry *entry, int fd)
789 (void)a; /* UNUSED */
790 (void)entry; /* UNUSED */
791 (void)fd; /* UNUSED */
797 #if defined(HAVE_LINUX_FIEMAP_H)
800 * Linux sparse interface.
802 * The FIEMAP ioctl returns an "extent" for each physical allocation
803 * on disk. We need to process those to generate a more compact list
804 * of logical file blocks. We also need to be very careful to use
805 * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes
806 * does not report allocations for newly-written data that hasn't
807 * been synced to disk.
809 * It's important to return a minimal sparse file list because we want
810 * to not trigger sparse file extensions if we don't have to, since
811 * not all readers support them.
815 setup_sparse(struct archive_read_disk *a,
816 struct archive_entry *entry, int fd)
820 struct fiemap_extent *fe;
822 int count, do_fiemap;
824 int exit_sts = ARCHIVE_OK;
826 if (archive_entry_filetype(entry) != AE_IFREG
827 || archive_entry_size(entry) <= 0
828 || archive_entry_hardlink(entry) != NULL)
834 path = archive_entry_sourcepath(entry);
836 path = archive_entry_pathname(entry);
837 fd = open(path, O_RDONLY | O_NONBLOCK);
839 archive_set_error(&a->archive, errno,
840 "Can't open `%s'", path);
841 return (ARCHIVE_FAILED);
845 count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
846 fm = (struct fiemap *)buff;
848 fm->fm_length = ~0ULL;;
849 fm->fm_flags = FIEMAP_FLAG_SYNC;
850 fm->fm_extent_count = count;
852 size = archive_entry_size(entry);
856 r = ioctl(fd, FS_IOC_FIEMAP, fm);
858 /* When errno is ENOTTY, it is better we should
859 * return ARCHIVE_OK because an earlier version
860 *(<2.6.28) cannot perfom FS_IOC_FIEMAP.
861 * We should also check if errno is EOPNOTSUPP,
862 * it means "Operation not supported". */
863 if (errno != ENOTTY && errno != EOPNOTSUPP) {
864 archive_set_error(&a->archive, errno,
866 exit_sts = ARCHIVE_FAILED;
868 goto exit_setup_sparse;
870 if (fm->fm_mapped_extents == 0)
873 for (i = 0; i < fm->fm_mapped_extents; i++, fe++) {
874 if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) {
875 /* The fe_length of the last block does not
876 * adjust itself to its size files. */
877 int64_t length = fe->fe_length;
878 if (fe->fe_logical + length > size)
879 length -= fe->fe_logical + length - size;
880 if (fe->fe_logical == 0 && length == size) {
881 /* This is not sparse. */
886 archive_entry_sparse_add_entry(entry,
887 fe->fe_logical, length);
889 if (fe->fe_flags & FIEMAP_EXTENT_LAST)
893 fe = fm->fm_extents + fm->fm_mapped_extents -1;
894 fm->fm_start = fe->fe_logical + fe->fe_length;
899 if (initial_fd != fd)
904 #elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
907 * FreeBSD and Solaris sparse interface.
911 setup_sparse(struct archive_read_disk *a,
912 struct archive_entry *entry, int fd)
916 off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */
917 off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */
918 int exit_sts = ARCHIVE_OK;
920 if (archive_entry_filetype(entry) != AE_IFREG
921 || archive_entry_size(entry) <= 0
922 || archive_entry_hardlink(entry) != NULL)
925 /* Does filesystem support the reporting of hole ? */
927 if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0)
929 initial_off = lseek(fd, 0, SEEK_CUR);
930 if (initial_off != 0)
931 lseek(fd, 0, SEEK_SET);
935 path = archive_entry_sourcepath(entry);
937 path = archive_entry_pathname(entry);
938 if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
940 fd = open(path, O_RDONLY | O_NONBLOCK);
942 archive_set_error(&a->archive, errno,
943 "Can't open `%s'", path);
944 return (ARCHIVE_FAILED);
950 size = archive_entry_size(entry);
951 while (off_s < size) {
952 off_s = lseek(fd, off_s, SEEK_DATA);
953 if (off_s == (off_t)-1) {
955 break;/* no more hole */
956 archive_set_error(&a->archive, errno,
957 "lseek(SEEK_HOLE) failed");
958 exit_sts = ARCHIVE_FAILED;
959 goto exit_setup_sparse;
961 off_e = lseek(fd, off_s, SEEK_HOLE);
962 if (off_s == (off_t)-1) {
963 if (errno == ENXIO) {
964 off_e = lseek(fd, 0, SEEK_END);
965 if (off_e != (off_t)-1)
966 break;/* no more data */
968 archive_set_error(&a->archive, errno,
969 "lseek(SEEK_DATA) failed");
970 exit_sts = ARCHIVE_FAILED;
971 goto exit_setup_sparse;
973 if (off_s == 0 && off_e == size)
974 break;/* This is not spase. */
975 archive_entry_sparse_add_entry(entry, off_s,
980 if (initial_fd != fd)
983 lseek(fd, initial_off, SEEK_SET);
990 * Generic (stub) sparse support.
993 setup_sparse(struct archive_read_disk *a,
994 struct archive_entry *entry, int fd)
996 (void)a; /* UNUSED */
997 (void)entry; /* UNUSED */
998 (void)fd; /* UNUSED */
1004 #endif /* !defined(_WIN32) || defined(__CYGWIN__) */