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