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