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