1 /*-
2  * Copyright (c) 2003-2009 Tim Kientzle
3  * Copyright (c) 2010 Michihiro NAKAJIMA
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26 
27 #include "archive_platform.h"
28 __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_disk_entry_from_file.c 201084 2009-12-28 02:14:09Z kientzle $");
29 
30 /* This is the tree-walking code for POSIX systems. */
31 #if !defined(_WIN32) || defined(__CYGWIN__)
32 
33 #ifdef HAVE_SYS_TYPES_H
34 /* Mac OSX requires sys/types.h before sys/acl.h. */
35 #include <sys/types.h>
36 #endif
37 #ifdef HAVE_SYS_ACL_H
38 #include <sys/acl.h>
39 #endif
40 #ifdef HAVE_SYS_EXTATTR_H
41 #include <sys/extattr.h>
42 #endif
43 #ifdef HAVE_SYS_IOCTL_H
44 #include <sys/ioctl.h>
45 #endif
46 #ifdef HAVE_SYS_PARAM_H
47 #include <sys/param.h>
48 #endif
49 #ifdef HAVE_SYS_STAT_H
50 #include <sys/stat.h>
51 #endif
52 #ifdef HAVE_SYS_XATTR_H
53 #include <sys/xattr.h>
54 #endif
55 #ifdef HAVE_SYS_EA_H
56 #include <sys/ea.h>
57 #endif
58 #ifdef HAVE_ACL_LIBACL_H
59 #include <acl/libacl.h>
60 #endif
61 #ifdef HAVE_ATTR_XATTR_H
62 #include <attr/xattr.h>
63 #endif
64 #ifdef HAVE_COPYFILE_H
65 #include <copyfile.h>
66 #endif
67 #ifdef HAVE_ERRNO_H
68 #include <errno.h>
69 #endif
70 #ifdef HAVE_FCNTL_H
71 #include <fcntl.h>
72 #endif
73 #ifdef HAVE_LIMITS_H
74 #include <limits.h>
75 #endif
76 #ifdef HAVE_LINUX_FIEMAP_H
77 #include <linux/fiemap.h>
78 #endif
79 #ifdef HAVE_LINUX_FS_H
80 #include <linux/fs.h>
81 #endif
82 /*
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.
85  */
86 #ifdef HAVE_LINUX_EXT2_FS_H
87 #include <linux/ext2_fs.h>      /* for Linux file flags */
88 #endif
89 #if defined(HAVE_EXT2FS_EXT2_FS_H) && !defined(__CYGWIN__)
90 #include <ext2fs/ext2_fs.h>     /* Linux file flags, broken on Cygwin */
91 #endif
92 #ifdef HAVE_PATHS_H
93 #include <paths.h>
94 #endif
95 #ifdef HAVE_UNISTD_H
96 #include <unistd.h>
97 #endif
98 
99 #include "archive.h"
100 #include "archive_entry.h"
101 #include "archive_private.h"
102 #include "archive_read_disk_private.h"
103 
104 /*
105  * Linux and FreeBSD plug this obvious hole in POSIX.1e in
106  * different ways.
107  */
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
112 #endif
113 
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);
122 
123 int
124 archive_read_disk_entry_from_file(struct archive *_a,
125     struct archive_entry *entry,
126     int fd,
127     const struct stat *st)
128 {
129 	struct archive_read_disk *a = (struct archive_read_disk *)_a;
130 	const char *path, *name;
131 	struct stat s;
132 	int initial_fd = fd;
133 	int r, r1;
134 
135 	archive_clear_error(_a);
136 	path = archive_entry_sourcepath(entry);
137 	if (path == NULL)
138 		path = archive_entry_pathname(entry);
139 
140 	if (a->tree == NULL) {
141 		if (st == NULL) {
142 #if HAVE_FSTAT
143 			if (fd >= 0) {
144 				if (fstat(fd, &s) != 0) {
145 					archive_set_error(&a->archive, errno,
146 					    "Can't fstat");
147 					return (ARCHIVE_FAILED);
148 				}
149 			} else
150 #endif
151 #if HAVE_LSTAT
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);
157 				}
158 			} else
159 #endif
160 			if (stat(path, &s) != 0) {
161 				archive_set_error(&a->archive, errno,
162 				    "Can't stat %s", path);
163 				return (ARCHIVE_FAILED);
164 			}
165 			st = &s;
166 		}
167 		archive_entry_copy_stat(entry, st);
168 	}
169 
170 	/* Lookup uname/gname */
171 	name = archive_read_disk_uname(_a, archive_entry_uid(entry));
172 	if (name != NULL)
173 		archive_entry_copy_uname(entry, name);
174 	name = archive_read_disk_gname(_a, archive_entry_gid(entry));
175 	if (name != NULL)
176 		archive_entry_copy_gname(entry, name);
177 
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);
183 #endif
184 
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))) {
190 		if (fd < 0)
191 			fd = open(path, O_RDONLY | O_NONBLOCK);
192 		if (fd >= 0) {
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);
197 		}
198 	}
199 #endif
200 
201 #if defined(HAVE_READLINK) || defined(HAVE_READLINKAT)
202 	if (S_ISLNK(st->st_mode)) {
203 		size_t linkbuffer_len = st->st_size + 1;
204 		char *linkbuffer;
205 		int lnklen;
206 
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);
212 		}
213 #ifdef HAVE_READLINKAT
214 		if (a->entry_wd_fd >= 0)
215 			lnklen = readlinkat(a->entry_wd_fd, path,
216 			    linkbuffer, linkbuffer_len);
217 		else
218 #endif /* HAVE_READLINKAT */
219 		lnklen = readlink(path, linkbuffer, linkbuffer_len);
220 		if (lnklen < 0) {
221 			archive_set_error(&a->archive, errno,
222 			    "Couldn't read link data");
223 			free(linkbuffer);
224 			return (ARCHIVE_FAILED);
225 		}
226 		linkbuffer[lnklen] = 0;
227 		archive_entry_set_symlink(entry, linkbuffer);
228 		free(linkbuffer);
229 	}
230 #endif /* HAVE_READLINK || HAVE_READLINKAT */
231 
232 	r = setup_acls_posix1e(a, entry, fd);
233 	r1 = setup_xattrs(a, entry, fd);
234 	if (r1 < r)
235 		r = r1;
236 	r1 = setup_mac_metadata(a, entry, fd);
237 	if (r1 < r)
238 		r = r1;
239 	r1 = setup_sparse(a, entry, fd);
240 	if (r1 < r)
241 		r = r1;
242 
243 	/* If we opened the file earlier in this function, close it. */
244 	if (initial_fd != fd)
245 		close(fd);
246 	return (r);
247 }
248 
249 #if defined(__APPLE__) && defined(HAVE_COPYFILE_H)
250 /*
251  * The Mac OS "copyfile()" API copies the extended metadata for a
252  * file into a separate file in AppleDouble format (see RFC 1740).
253  *
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.
257  *
258  * Note that this is currently done unconditionally; the tar program has
259  * an option to discard this information before the archive is written.
260  *
261  * TODO: If there's a failure, report it and return ARCHIVE_WARN.
262  */
263 static int
264 setup_mac_metadata(struct archive_read_disk *a,
265     struct archive_entry *entry, int fd)
266 {
267 	int tempfd = -1;
268 	int copyfile_flags = COPYFILE_NOFOLLOW | COPYFILE_ACL | COPYFILE_XATTR;
269 	struct stat copyfile_stat;
270 	int ret = ARCHIVE_OK;
271 	void *buff;
272 	int have_attrs;
273 	const char *name, *tempdir, *tempfile = NULL;
274 
275 	name = archive_entry_sourcepath(entry);
276 	if (name == NULL)
277 		name = archive_entry_pathname(entry);
278 	if (name == NULL) {
279 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
280 		    "Can't open file to read extended attributes: No name");
281 		return (ARCHIVE_WARN);
282 	}
283 
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);
290 	}
291 	if (have_attrs == 0)
292 		return (ARCHIVE_OK);
293 
294 	tempdir = NULL;
295 	if (issetugid() == 0)
296 		tempdir = getenv("TMPDIR");
297 	if (tempdir == NULL)
298 		tempdir = _PATH_TMP;
299 	tempfile = tempnam(tempdir, "tar.md.");
300 
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");
308 		ret = ARCHIVE_WARN;
309 		goto cleanup;
310 	}
311 	tempfd = open(tempfile, O_RDONLY);
312 	if (tempfd < 0) {
313 		archive_set_error(&a->archive, errno,
314 		    "Could not open extended attribute file");
315 		ret = ARCHIVE_WARN;
316 		goto cleanup;
317 	}
318 	if (fstat(tempfd, &copyfile_stat)) {
319 		archive_set_error(&a->archive, errno,
320 		    "Could not check size of extended attributes");
321 		ret = ARCHIVE_WARN;
322 		goto cleanup;
323 	}
324 	buff = malloc(copyfile_stat.st_size);
325 	if (buff == NULL) {
326 		archive_set_error(&a->archive, errno,
327 		    "Could not allocate memory for extended attributes");
328 		ret = ARCHIVE_WARN;
329 		goto cleanup;
330 	}
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");
334 		ret = ARCHIVE_WARN;
335 		goto cleanup;
336 	}
337 	archive_entry_copy_mac_metadata(entry, buff, copyfile_stat.st_size);
338 
339 cleanup:
340 	if (tempfd >= 0)
341 		close(tempfd);
342 	if (tempfile != NULL)
343 		unlink(tempfile);
344 	return (ret);
345 }
346 
347 #else
348 
349 /*
350  * Stub implementation for non-Mac systems.
351  */
352 static int
353 setup_mac_metadata(struct archive_read_disk *a,
354     struct archive_entry *entry, int fd)
355 {
356 	(void)a; /* UNUSED */
357 	(void)entry; /* UNUSED */
358 	(void)fd; /* UNUSED */
359 	return (ARCHIVE_OK);
360 }
361 #endif
362 
363 
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);
367 
368 static int
369 setup_acls_posix1e(struct archive_read_disk *a,
370     struct archive_entry *entry, int fd)
371 {
372 	const char	*accpath;
373 	acl_t		 acl;
374 
375 	accpath = archive_entry_sourcepath(entry);
376 	if (accpath == NULL)
377 		accpath = archive_entry_pathname(entry);
378 
379 	archive_entry_acl_clear(entry);
380 
381 	/* Retrieve access ACL from file. */
382 	if (fd >= 0)
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);
387 #else
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
391 		   have one. */
392 		acl = NULL;
393 #endif
394 	else
395 		acl = acl_get_file(accpath, ACL_TYPE_ACCESS);
396 	if (acl != NULL) {
397 		setup_acl_posix1e(a, entry, acl,
398 		    ARCHIVE_ENTRY_ACL_TYPE_ACCESS);
399 		acl_free(acl);
400 	}
401 
402 	/* Only directories can have default ACLs. */
403 	if (S_ISDIR(archive_entry_mode(entry))) {
404 		acl = acl_get_file(accpath, ACL_TYPE_DEFAULT);
405 		if (acl != NULL) {
406 			setup_acl_posix1e(a, entry, acl,
407 			    ARCHIVE_ENTRY_ACL_TYPE_DEFAULT);
408 			acl_free(acl);
409 		}
410 	}
411 	return (ARCHIVE_OK);
412 }
413 
414 /*
415  * Translate POSIX.1e ACL into libarchive internal structure.
416  */
417 static void
418 setup_acl_posix1e(struct archive_read_disk *a,
419     struct archive_entry *entry, acl_t acl, int archive_entry_acl_type)
420 {
421 	acl_tag_t	 acl_tag;
422 	acl_entry_t	 acl_entry;
423 	acl_permset_t	 acl_permset;
424 	int		 s, ae_id, ae_tag, ae_perm;
425 	const char	*ae_name;
426 
427 	s = acl_get_entry(acl, ACL_FIRST_ENTRY, &acl_entry);
428 	while (s == 1) {
429 		ae_id = -1;
430 		ae_name = NULL;
431 
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;
449 		} else {
450 			/* Skip types that libarchive can't support. */
451 			continue;
452 		}
453 
454 		acl_get_permset(acl_entry, &acl_permset);
455 		ae_perm = 0;
456 		/*
457 		 * acl_get_perm() is spelled differently on different
458 		 * platforms; see above.
459 		 */
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;
466 
467 		archive_entry_acl_add_entry(entry,
468 		    archive_entry_acl_type, ae_perm, ae_tag,
469 		    ae_id, ae_name);
470 
471 		s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry);
472 	}
473 }
474 #else
475 static int
476 setup_acls_posix1e(struct archive_read_disk *a,
477     struct archive_entry *entry, int fd)
478 {
479 	(void)a;      /* UNUSED */
480 	(void)entry;  /* UNUSED */
481 	(void)fd;     /* UNUSED */
482 	return (ARCHIVE_OK);
483 }
484 #endif
485 
486 #if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \
487     HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \
488     (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA)
489 
490 /*
491  * Linux and AIX extended attribute support.
492  *
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
498  * to listxattr().
499  */
500 
501 
502 static int
503 setup_xattr(struct archive_read_disk *a,
504     struct archive_entry *entry, const char *name, int fd)
505 {
506 	ssize_t size;
507 	void *value = NULL;
508 	const char *accpath;
509 
510 	accpath = archive_entry_sourcepath(entry);
511 	if (accpath == NULL)
512 		accpath = archive_entry_pathname(entry);
513 
514 #if HAVE_FGETXATTR
515 	if (fd >= 0)
516 		size = fgetxattr(fd, name, NULL, 0);
517 	else if (!a->follow_symlinks)
518 		size = lgetxattr(accpath, name, NULL, 0);
519 	else
520 		size = getxattr(accpath, name, NULL, 0);
521 #elif HAVE_FGETEA
522 	if (fd >= 0)
523 		size = fgetea(fd, name, NULL, 0);
524 	else if (!a->follow_symlinks)
525 		size = lgetea(accpath, name, NULL, 0);
526 	else
527 		size = getea(accpath, name, NULL, 0);
528 #endif
529 
530 	if (size == -1) {
531 		archive_set_error(&a->archive, errno,
532 		    "Couldn't query extended attribute");
533 		return (ARCHIVE_WARN);
534 	}
535 
536 	if (size > 0 && (value = malloc(size)) == NULL) {
537 		archive_set_error(&a->archive, errno, "Out of memory");
538 		return (ARCHIVE_FATAL);
539 	}
540 
541 #if HAVE_FGETXATTR
542 	if (fd >= 0)
543 		size = fgetxattr(fd, name, value, size);
544 	else if (!a->follow_symlinks)
545 		size = lgetxattr(accpath, name, value, size);
546 	else
547 		size = getxattr(accpath, name, value, size);
548 #elif HAVE_FGETEA
549 	if (fd >= 0)
550 		size = fgetea(fd, name, value, size);
551 	else if (!a->follow_symlinks)
552 		size = lgetea(accpath, name, value, size);
553 	else
554 		size = getea(accpath, name, value, size);
555 #endif
556 
557 	if (size == -1) {
558 		archive_set_error(&a->archive, errno,
559 		    "Couldn't read extended attribute");
560 		return (ARCHIVE_WARN);
561 	}
562 
563 	archive_entry_xattr_add_entry(entry, name, value, size);
564 
565 	free(value);
566 	return (ARCHIVE_OK);
567 }
568 
569 static int
570 setup_xattrs(struct archive_read_disk *a,
571     struct archive_entry *entry, int fd)
572 {
573 	char *list, *p;
574 	const char *path;
575 	ssize_t list_size;
576 
577 	path = archive_entry_sourcepath(entry);
578 	if (path == NULL)
579 		path = archive_entry_pathname(entry);
580 
581 #if HAVE_FLISTXATTR
582 	if (fd >= 0)
583 		list_size = flistxattr(fd, NULL, 0);
584 	else if (!a->follow_symlinks)
585 		list_size = llistxattr(path, NULL, 0);
586 	else
587 		list_size = listxattr(path, NULL, 0);
588 #elif HAVE_FLISTEA
589 	if (fd >= 0)
590 		list_size = flistea(fd, NULL, 0);
591 	else if (!a->follow_symlinks)
592 		list_size = llistea(path, NULL, 0);
593 	else
594 		list_size = listea(path, NULL, 0);
595 #endif
596 
597 	if (list_size == -1) {
598 		if (errno == ENOTSUP || errno == ENOSYS)
599 			return (ARCHIVE_OK);
600 		archive_set_error(&a->archive, errno,
601 			"Couldn't list extended attributes");
602 		return (ARCHIVE_WARN);
603 	}
604 
605 	if (list_size == 0)
606 		return (ARCHIVE_OK);
607 
608 	if ((list = malloc(list_size)) == NULL) {
609 		archive_set_error(&a->archive, errno, "Out of memory");
610 		return (ARCHIVE_FATAL);
611 	}
612 
613 #if HAVE_FLISTXATTR
614 	if (fd >= 0)
615 		list_size = flistxattr(fd, list, list_size);
616 	else if (!a->follow_symlinks)
617 		list_size = llistxattr(path, list, list_size);
618 	else
619 		list_size = listxattr(path, list, list_size);
620 #elif HAVE_FLISTEA
621 	if (fd >= 0)
622 		list_size = flistea(fd, list, list_size);
623 	else if (!a->follow_symlinks)
624 		list_size = llistea(path, list, list_size);
625 	else
626 		list_size = listea(path, list, list_size);
627 #endif
628 
629 	if (list_size == -1) {
630 		archive_set_error(&a->archive, errno,
631 			"Couldn't retrieve extended attributes");
632 		free(list);
633 		return (ARCHIVE_WARN);
634 	}
635 
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)
639 			continue;
640 		setup_xattr(a, entry, p, fd);
641 	}
642 
643 	free(list);
644 	return (ARCHIVE_OK);
645 }
646 
647 #elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \
648     HAVE_DECL_EXTATTR_NAMESPACE_USER
649 
650 /*
651  * FreeBSD extattr interface.
652  */
653 
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
657  * those separately.
658  */
659 static int
660 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
661     int namespace, const char *name, const char *fullname, int fd);
662 
663 static int
664 setup_xattr(struct archive_read_disk *a, struct archive_entry *entry,
665     int namespace, const char *name, const char *fullname, int fd)
666 {
667 	ssize_t size;
668 	void *value = NULL;
669 	const char *accpath;
670 
671 	accpath = archive_entry_sourcepath(entry);
672 	if (accpath == NULL)
673 		accpath = archive_entry_pathname(entry);
674 
675 	if (fd >= 0)
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);
679 	else
680 		size = extattr_get_file(accpath, namespace, name, NULL, 0);
681 
682 	if (size == -1) {
683 		archive_set_error(&a->archive, errno,
684 		    "Couldn't query extended attribute");
685 		return (ARCHIVE_WARN);
686 	}
687 
688 	if (size > 0 && (value = malloc(size)) == NULL) {
689 		archive_set_error(&a->archive, errno, "Out of memory");
690 		return (ARCHIVE_FATAL);
691 	}
692 
693 	if (fd >= 0)
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);
697 	else
698 		size = extattr_get_file(accpath, namespace, name, value, size);
699 
700 	if (size == -1) {
701 		archive_set_error(&a->archive, errno,
702 		    "Couldn't read extended attribute");
703 		return (ARCHIVE_WARN);
704 	}
705 
706 	archive_entry_xattr_add_entry(entry, fullname, value, size);
707 
708 	free(value);
709 	return (ARCHIVE_OK);
710 }
711 
712 static int
713 setup_xattrs(struct archive_read_disk *a,
714     struct archive_entry *entry, int fd)
715 {
716 	char buff[512];
717 	char *list, *p;
718 	ssize_t list_size;
719 	const char *path;
720 	int namespace = EXTATTR_NAMESPACE_USER;
721 
722 	path = archive_entry_sourcepath(entry);
723 	if (path == NULL)
724 		path = archive_entry_pathname(entry);
725 
726 	if (fd >= 0)
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);
730 	else
731 		list_size = extattr_list_file(path, namespace, NULL, 0);
732 
733 	if (list_size == -1 && errno == EOPNOTSUPP)
734 		return (ARCHIVE_OK);
735 	if (list_size == -1) {
736 		archive_set_error(&a->archive, errno,
737 			"Couldn't list extended attributes");
738 		return (ARCHIVE_WARN);
739 	}
740 
741 	if (list_size == 0)
742 		return (ARCHIVE_OK);
743 
744 	if ((list = malloc(list_size)) == NULL) {
745 		archive_set_error(&a->archive, errno, "Out of memory");
746 		return (ARCHIVE_FATAL);
747 	}
748 
749 	if (fd >= 0)
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);
753 	else
754 		list_size = extattr_list_file(path, namespace, list, list_size);
755 
756 	if (list_size == -1) {
757 		archive_set_error(&a->archive, errno,
758 			"Couldn't retrieve extended attributes");
759 		free(list);
760 		return (ARCHIVE_WARN);
761 	}
762 
763 	p = list;
764 	while ((p - list) < list_size) {
765 		size_t len = 255 & (int)*p;
766 		char *name;
767 
768 		strcpy(buff, "user.");
769 		name = buff + strlen(buff);
770 		memcpy(name, p + 1, len);
771 		name[len] = '\0';
772 		setup_xattr(a, entry, namespace, name, buff, fd);
773 		p += 1 + len;
774 	}
775 
776 	free(list);
777 	return (ARCHIVE_OK);
778 }
779 
780 #else
781 
782 /*
783  * Generic (stub) extended attribute support.
784  */
785 static int
786 setup_xattrs(struct archive_read_disk *a,
787     struct archive_entry *entry, int fd)
788 {
789 	(void)a;     /* UNUSED */
790 	(void)entry; /* UNUSED */
791 	(void)fd;    /* UNUSED */
792 	return (ARCHIVE_OK);
793 }
794 
795 #endif
796 
797 #if defined(HAVE_LINUX_FIEMAP_H)
798 
799 /*
800  * Linux sparse interface.
801  *
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.
808  *
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.
812  */
813 
814 static int
815 setup_sparse(struct archive_read_disk *a,
816     struct archive_entry *entry, int fd)
817 {
818 	char buff[4096];
819 	struct fiemap *fm;
820 	struct fiemap_extent *fe;
821 	int64_t size;
822 	int count, do_fiemap;
823 	int initial_fd = fd;
824 	int exit_sts = ARCHIVE_OK;
825 
826 	if (archive_entry_filetype(entry) != AE_IFREG
827 	    || archive_entry_size(entry) <= 0
828 	    || archive_entry_hardlink(entry) != NULL)
829 		return (ARCHIVE_OK);
830 
831 	if (fd < 0) {
832 		const char *path;
833 
834 		path = archive_entry_sourcepath(entry);
835 		if (path == NULL)
836 			path = archive_entry_pathname(entry);
837 		fd = open(path, O_RDONLY | O_NONBLOCK);
838 		if (fd < 0) {
839 			archive_set_error(&a->archive, errno,
840 			    "Can't open `%s'", path);
841 			return (ARCHIVE_FAILED);
842 		}
843 	}
844 
845 	count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe);
846 	fm = (struct fiemap *)buff;
847 	fm->fm_start = 0;
848 	fm->fm_length = ~0ULL;;
849 	fm->fm_flags = FIEMAP_FLAG_SYNC;
850 	fm->fm_extent_count = count;
851 	do_fiemap = 1;
852 	size = archive_entry_size(entry);
853 	for (;;) {
854 		int i, r;
855 
856 		r = ioctl(fd, FS_IOC_FIEMAP, fm);
857 		if (r < 0) {
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,
865 				    "FIEMAP failed");
866 				exit_sts = ARCHIVE_FAILED;
867 			}
868 			goto exit_setup_sparse;
869 		}
870 		if (fm->fm_mapped_extents == 0)
871 			break;
872 		fe = fm->fm_extents;
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. */
882 					do_fiemap = 0;
883 					break;
884 				}
885 				if (length > 0)
886 					archive_entry_sparse_add_entry(entry,
887 					    fe->fe_logical, length);
888 			}
889 			if (fe->fe_flags & FIEMAP_EXTENT_LAST)
890 				do_fiemap = 0;
891 		}
892 		if (do_fiemap) {
893 			fe = fm->fm_extents + fm->fm_mapped_extents -1;
894 			fm->fm_start = fe->fe_logical + fe->fe_length;
895 		} else
896 			break;
897 	}
898 exit_setup_sparse:
899 	if (initial_fd != fd)
900 		close(fd);
901 	return (exit_sts);
902 }
903 
904 #elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE)
905 
906 /*
907  * FreeBSD and Solaris sparse interface.
908  */
909 
910 static int
911 setup_sparse(struct archive_read_disk *a,
912     struct archive_entry *entry, int fd)
913 {
914 	int64_t size;
915 	int initial_fd = 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;
919 
920 	if (archive_entry_filetype(entry) != AE_IFREG
921 	    || archive_entry_size(entry) <= 0
922 	    || archive_entry_hardlink(entry) != NULL)
923 		return (ARCHIVE_OK);
924 
925 	/* Does filesystem support the reporting of hole ? */
926 	if (fd >= 0) {
927 		if (fpathconf(fd, _PC_MIN_HOLE_SIZE) <= 0)
928 			return (ARCHIVE_OK);
929 		initial_off = lseek(fd, 0, SEEK_CUR);
930 		if (initial_off != 0)
931 			lseek(fd, 0, SEEK_SET);
932 	} else {
933 		const char *path;
934 
935 		path = archive_entry_sourcepath(entry);
936 		if (path == NULL)
937 			path = archive_entry_pathname(entry);
938 		if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0)
939 			return (ARCHIVE_OK);
940 		fd = open(path, O_RDONLY | O_NONBLOCK);
941 		if (fd < 0) {
942 			archive_set_error(&a->archive, errno,
943 			    "Can't open `%s'", path);
944 			return (ARCHIVE_FAILED);
945 		}
946 		initial_off = 0;
947 	}
948 
949 	off_s = 0;
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) {
954 			if (errno == ENXIO)
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;
960 		}
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 */
967 			}
968 			archive_set_error(&a->archive, errno,
969 			    "lseek(SEEK_DATA) failed");
970 			exit_sts = ARCHIVE_FAILED;
971 			goto exit_setup_sparse;
972 		}
973 		if (off_s == 0 && off_e == size)
974 			break;/* This is not spase. */
975 		archive_entry_sparse_add_entry(entry, off_s,
976 			off_e - off_s);
977 		off_s = off_e;
978 	}
979 exit_setup_sparse:
980 	if (initial_fd != fd)
981 		close(fd);
982 	else
983 		lseek(fd, initial_off, SEEK_SET);
984 	return (exit_sts);
985 }
986 
987 #else
988 
989 /*
990  * Generic (stub) sparse support.
991  */
992 static int
993 setup_sparse(struct archive_read_disk *a,
994     struct archive_entry *entry, int fd)
995 {
996 	(void)a;     /* UNUSED */
997 	(void)entry; /* UNUSED */
998 	(void)fd;    /* UNUSED */
999 	return (ARCHIVE_OK);
1000 }
1001 
1002 #endif
1003 
1004 #endif /* !defined(_WIN32) || defined(__CYGWIN__) */
1005 
1006