archive_read_disk_entry_from_file.c revision 238856
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 238856 2012-07-28 06:38:44Z 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 continue; 489 } 490 491 acl_get_permset(acl_entry, &acl_permset); 492 ae_perm = 0; 493 /* 494 * acl_get_perm() is spelled differently on different 495 * platforms; see above. 496 */ 497 if (ACL_GET_PERM(acl_permset, ACL_EXECUTE)) 498 ae_perm |= ARCHIVE_ENTRY_ACL_EXECUTE; 499 if (ACL_GET_PERM(acl_permset, ACL_READ)) 500 ae_perm |= ARCHIVE_ENTRY_ACL_READ; 501 if (ACL_GET_PERM(acl_permset, ACL_WRITE)) 502 ae_perm |= ARCHIVE_ENTRY_ACL_WRITE; 503 504 archive_entry_acl_add_entry(entry, 505 archive_entry_acl_type, ae_perm, ae_tag, 506 ae_id, ae_name); 507 508 s = acl_get_entry(acl, ACL_NEXT_ENTRY, &acl_entry); 509 } 510} 511#else 512static int 513setup_acls_posix1e(struct archive_read_disk *a, 514 struct archive_entry *entry, int *fd) 515{ 516 (void)a; /* UNUSED */ 517 (void)entry; /* UNUSED */ 518 (void)fd; /* UNUSED */ 519 return (ARCHIVE_OK); 520} 521#endif 522 523#if (HAVE_FGETXATTR && HAVE_FLISTXATTR && HAVE_LISTXATTR && \ 524 HAVE_LLISTXATTR && HAVE_GETXATTR && HAVE_LGETXATTR) || \ 525 (HAVE_FGETEA && HAVE_FLISTEA && HAVE_LISTEA) 526 527/* 528 * Linux and AIX extended attribute support. 529 * 530 * TODO: By using a stack-allocated buffer for the first 531 * call to getxattr(), we might be able to avoid the second 532 * call entirely. We only need the second call if the 533 * stack-allocated buffer is too small. But a modest buffer 534 * of 1024 bytes or so will often be big enough. Same applies 535 * to listxattr(). 536 */ 537 538 539static int 540setup_xattr(struct archive_read_disk *a, 541 struct archive_entry *entry, const char *name, int fd) 542{ 543 ssize_t size; 544 void *value = NULL; 545 const char *accpath; 546 547 accpath = archive_entry_sourcepath(entry); 548 if (accpath == NULL) 549 accpath = archive_entry_pathname(entry); 550 551#if HAVE_FGETXATTR 552 if (fd >= 0) 553 size = fgetxattr(fd, name, NULL, 0); 554 else if (!a->follow_symlinks) 555 size = lgetxattr(accpath, name, NULL, 0); 556 else 557 size = getxattr(accpath, name, NULL, 0); 558#elif HAVE_FGETEA 559 if (fd >= 0) 560 size = fgetea(fd, name, NULL, 0); 561 else if (!a->follow_symlinks) 562 size = lgetea(accpath, name, NULL, 0); 563 else 564 size = getea(accpath, name, NULL, 0); 565#endif 566 567 if (size == -1) { 568 archive_set_error(&a->archive, errno, 569 "Couldn't query extended attribute"); 570 return (ARCHIVE_WARN); 571 } 572 573 if (size > 0 && (value = malloc(size)) == NULL) { 574 archive_set_error(&a->archive, errno, "Out of memory"); 575 return (ARCHIVE_FATAL); 576 } 577 578#if HAVE_FGETXATTR 579 if (fd >= 0) 580 size = fgetxattr(fd, name, value, size); 581 else if (!a->follow_symlinks) 582 size = lgetxattr(accpath, name, value, size); 583 else 584 size = getxattr(accpath, name, value, size); 585#elif HAVE_FGETEA 586 if (fd >= 0) 587 size = fgetea(fd, name, value, size); 588 else if (!a->follow_symlinks) 589 size = lgetea(accpath, name, value, size); 590 else 591 size = getea(accpath, name, value, size); 592#endif 593 594 if (size == -1) { 595 archive_set_error(&a->archive, errno, 596 "Couldn't read extended attribute"); 597 return (ARCHIVE_WARN); 598 } 599 600 archive_entry_xattr_add_entry(entry, name, value, size); 601 602 free(value); 603 return (ARCHIVE_OK); 604} 605 606static int 607setup_xattrs(struct archive_read_disk *a, 608 struct archive_entry *entry, int *fd) 609{ 610 char *list, *p; 611 const char *path; 612 ssize_t list_size; 613 614 path = archive_entry_sourcepath(entry); 615 if (path == NULL) 616 path = archive_entry_pathname(entry); 617 618 if (*fd < 0 && a->tree != NULL) { 619 if (a->follow_symlinks || 620 archive_entry_filetype(entry) != AE_IFLNK) 621 *fd = a->open_on_current_dir(a->tree, path, 622 O_RDONLY | O_NONBLOCK); 623 if (*fd < 0) { 624 if (a->tree_enter_working_dir(a->tree) != 0) { 625 archive_set_error(&a->archive, errno, 626 "Couldn't access %s", path); 627 return (ARCHIVE_FAILED); 628 } 629 } 630 } 631 632#if HAVE_FLISTXATTR 633 if (*fd >= 0) 634 list_size = flistxattr(*fd, NULL, 0); 635 else if (!a->follow_symlinks) 636 list_size = llistxattr(path, NULL, 0); 637 else 638 list_size = listxattr(path, NULL, 0); 639#elif HAVE_FLISTEA 640 if (*fd >= 0) 641 list_size = flistea(*fd, NULL, 0); 642 else if (!a->follow_symlinks) 643 list_size = llistea(path, NULL, 0); 644 else 645 list_size = listea(path, NULL, 0); 646#endif 647 648 if (list_size == -1) { 649 if (errno == ENOTSUP || errno == ENOSYS) 650 return (ARCHIVE_OK); 651 archive_set_error(&a->archive, errno, 652 "Couldn't list extended attributes"); 653 return (ARCHIVE_WARN); 654 } 655 656 if (list_size == 0) 657 return (ARCHIVE_OK); 658 659 if ((list = malloc(list_size)) == NULL) { 660 archive_set_error(&a->archive, errno, "Out of memory"); 661 return (ARCHIVE_FATAL); 662 } 663 664#if HAVE_FLISTXATTR 665 if (*fd >= 0) 666 list_size = flistxattr(*fd, list, list_size); 667 else if (!a->follow_symlinks) 668 list_size = llistxattr(path, list, list_size); 669 else 670 list_size = listxattr(path, list, list_size); 671#elif HAVE_FLISTEA 672 if (*fd >= 0) 673 list_size = flistea(*fd, list, list_size); 674 else if (!a->follow_symlinks) 675 list_size = llistea(path, list, list_size); 676 else 677 list_size = listea(path, list, list_size); 678#endif 679 680 if (list_size == -1) { 681 archive_set_error(&a->archive, errno, 682 "Couldn't retrieve extended attributes"); 683 free(list); 684 return (ARCHIVE_WARN); 685 } 686 687 for (p = list; (p - list) < list_size; p += strlen(p) + 1) { 688 if (strncmp(p, "system.", 7) == 0 || 689 strncmp(p, "xfsroot.", 8) == 0) 690 continue; 691 setup_xattr(a, entry, p, *fd); 692 } 693 694 free(list); 695 return (ARCHIVE_OK); 696} 697 698#elif HAVE_EXTATTR_GET_FILE && HAVE_EXTATTR_LIST_FILE && \ 699 HAVE_DECL_EXTATTR_NAMESPACE_USER 700 701/* 702 * FreeBSD extattr interface. 703 */ 704 705/* TODO: Implement this. Follow the Linux model above, but 706 * with FreeBSD-specific system calls, of course. Be careful 707 * to not include the system extattrs that hold ACLs; we handle 708 * those separately. 709 */ 710static int 711setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, 712 int namespace, const char *name, const char *fullname, int fd); 713 714static int 715setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, 716 int namespace, const char *name, const char *fullname, int fd) 717{ 718 ssize_t size; 719 void *value = NULL; 720 const char *accpath; 721 722 accpath = archive_entry_sourcepath(entry); 723 if (accpath == NULL) 724 accpath = archive_entry_pathname(entry); 725 726 if (fd >= 0) 727 size = extattr_get_fd(fd, namespace, name, NULL, 0); 728 else if (!a->follow_symlinks) 729 size = extattr_get_link(accpath, namespace, name, NULL, 0); 730 else 731 size = extattr_get_file(accpath, namespace, name, NULL, 0); 732 733 if (size == -1) { 734 archive_set_error(&a->archive, errno, 735 "Couldn't query extended attribute"); 736 return (ARCHIVE_WARN); 737 } 738 739 if (size > 0 && (value = malloc(size)) == NULL) { 740 archive_set_error(&a->archive, errno, "Out of memory"); 741 return (ARCHIVE_FATAL); 742 } 743 744 if (fd >= 0) 745 size = extattr_get_fd(fd, namespace, name, value, size); 746 else if (!a->follow_symlinks) 747 size = extattr_get_link(accpath, namespace, name, value, size); 748 else 749 size = extattr_get_file(accpath, namespace, name, value, size); 750 751 if (size == -1) { 752 free(value); 753 archive_set_error(&a->archive, errno, 754 "Couldn't read extended attribute"); 755 return (ARCHIVE_WARN); 756 } 757 758 archive_entry_xattr_add_entry(entry, fullname, value, size); 759 760 free(value); 761 return (ARCHIVE_OK); 762} 763 764static int 765setup_xattrs(struct archive_read_disk *a, 766 struct archive_entry *entry, int *fd) 767{ 768 char buff[512]; 769 char *list, *p; 770 ssize_t list_size; 771 const char *path; 772 int namespace = EXTATTR_NAMESPACE_USER; 773 774 path = archive_entry_sourcepath(entry); 775 if (path == NULL) 776 path = archive_entry_pathname(entry); 777 778 if (*fd < 0 && a->tree != NULL) { 779 if (a->follow_symlinks || 780 archive_entry_filetype(entry) != AE_IFLNK) 781 *fd = a->open_on_current_dir(a->tree, path, 782 O_RDONLY | O_NONBLOCK); 783 if (*fd < 0) { 784 if (a->tree_enter_working_dir(a->tree) != 0) { 785 archive_set_error(&a->archive, errno, 786 "Couldn't access %s", path); 787 return (ARCHIVE_FAILED); 788 } 789 } 790 } 791 792 if (*fd >= 0) 793 list_size = extattr_list_fd(*fd, namespace, NULL, 0); 794 else if (!a->follow_symlinks) 795 list_size = extattr_list_link(path, namespace, NULL, 0); 796 else 797 list_size = extattr_list_file(path, namespace, NULL, 0); 798 799 if (list_size == -1 && errno == EOPNOTSUPP) 800 return (ARCHIVE_OK); 801 if (list_size == -1) { 802 archive_set_error(&a->archive, errno, 803 "Couldn't list extended attributes"); 804 return (ARCHIVE_WARN); 805 } 806 807 if (list_size == 0) 808 return (ARCHIVE_OK); 809 810 if ((list = malloc(list_size)) == NULL) { 811 archive_set_error(&a->archive, errno, "Out of memory"); 812 return (ARCHIVE_FATAL); 813 } 814 815 if (*fd >= 0) 816 list_size = extattr_list_fd(*fd, namespace, list, list_size); 817 else if (!a->follow_symlinks) 818 list_size = extattr_list_link(path, namespace, list, list_size); 819 else 820 list_size = extattr_list_file(path, namespace, list, list_size); 821 822 if (list_size == -1) { 823 archive_set_error(&a->archive, errno, 824 "Couldn't retrieve extended attributes"); 825 free(list); 826 return (ARCHIVE_WARN); 827 } 828 829 p = list; 830 while ((p - list) < list_size) { 831 size_t len = 255 & (int)*p; 832 char *name; 833 834 strcpy(buff, "user."); 835 name = buff + strlen(buff); 836 memcpy(name, p + 1, len); 837 name[len] = '\0'; 838 setup_xattr(a, entry, namespace, name, buff, *fd); 839 p += 1 + len; 840 } 841 842 free(list); 843 return (ARCHIVE_OK); 844} 845 846#else 847 848/* 849 * Generic (stub) extended attribute support. 850 */ 851static int 852setup_xattrs(struct archive_read_disk *a, 853 struct archive_entry *entry, int *fd) 854{ 855 (void)a; /* UNUSED */ 856 (void)entry; /* UNUSED */ 857 (void)fd; /* UNUSED */ 858 return (ARCHIVE_OK); 859} 860 861#endif 862 863#if defined(HAVE_LINUX_FIEMAP_H) 864 865/* 866 * Linux sparse interface. 867 * 868 * The FIEMAP ioctl returns an "extent" for each physical allocation 869 * on disk. We need to process those to generate a more compact list 870 * of logical file blocks. We also need to be very careful to use 871 * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes 872 * does not report allocations for newly-written data that hasn't 873 * been synced to disk. 874 * 875 * It's important to return a minimal sparse file list because we want 876 * to not trigger sparse file extensions if we don't have to, since 877 * not all readers support them. 878 */ 879 880static int 881setup_sparse(struct archive_read_disk *a, 882 struct archive_entry *entry, int *fd) 883{ 884 char buff[4096]; 885 struct fiemap *fm; 886 struct fiemap_extent *fe; 887 int64_t size; 888 int count, do_fiemap; 889 int exit_sts = ARCHIVE_OK; 890 891 if (archive_entry_filetype(entry) != AE_IFREG 892 || archive_entry_size(entry) <= 0 893 || archive_entry_hardlink(entry) != NULL) 894 return (ARCHIVE_OK); 895 896 if (*fd < 0) { 897 const char *path; 898 899 path = archive_entry_sourcepath(entry); 900 if (path == NULL) 901 path = archive_entry_pathname(entry); 902 if (a->tree != NULL) 903 *fd = a->open_on_current_dir(a->tree, path, 904 O_RDONLY | O_NONBLOCK); 905 else 906 *fd = open(path, O_RDONLY | O_NONBLOCK); 907 if (*fd < 0) { 908 archive_set_error(&a->archive, errno, 909 "Can't open `%s'", path); 910 return (ARCHIVE_FAILED); 911 } 912 } 913 914 count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe); 915 fm = (struct fiemap *)buff; 916 fm->fm_start = 0; 917 fm->fm_length = ~0ULL;; 918 fm->fm_flags = FIEMAP_FLAG_SYNC; 919 fm->fm_extent_count = count; 920 do_fiemap = 1; 921 size = archive_entry_size(entry); 922 for (;;) { 923 int i, r; 924 925 r = ioctl(*fd, FS_IOC_FIEMAP, fm); 926 if (r < 0) { 927 /* When something error happens, it is better we 928 * should return ARCHIVE_OK because an earlier 929 * version(<2.6.28) cannot perfom FS_IOC_FIEMAP. */ 930 goto exit_setup_sparse; 931 } 932 if (fm->fm_mapped_extents == 0) 933 break; 934 fe = fm->fm_extents; 935 for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) { 936 if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { 937 /* The fe_length of the last block does not 938 * adjust itself to its size files. */ 939 int64_t length = fe->fe_length; 940 if (fe->fe_logical + length > (uint64_t)size) 941 length -= fe->fe_logical + length - size; 942 if (fe->fe_logical == 0 && length == size) { 943 /* This is not sparse. */ 944 do_fiemap = 0; 945 break; 946 } 947 if (length > 0) 948 archive_entry_sparse_add_entry(entry, 949 fe->fe_logical, length); 950 } 951 if (fe->fe_flags & FIEMAP_EXTENT_LAST) 952 do_fiemap = 0; 953 } 954 if (do_fiemap) { 955 fe = fm->fm_extents + fm->fm_mapped_extents -1; 956 fm->fm_start = fe->fe_logical + fe->fe_length; 957 } else 958 break; 959 } 960exit_setup_sparse: 961 return (exit_sts); 962} 963 964#elif defined(SEEK_HOLE) && defined(SEEK_DATA) && defined(_PC_MIN_HOLE_SIZE) 965 966/* 967 * FreeBSD and Solaris sparse interface. 968 */ 969 970static int 971setup_sparse(struct archive_read_disk *a, 972 struct archive_entry *entry, int *fd) 973{ 974 int64_t size; 975 off_t initial_off; /* FreeBSD/Solaris only, so off_t okay here */ 976 off_t off_s, off_e; /* FreeBSD/Solaris only, so off_t okay here */ 977 int exit_sts = ARCHIVE_OK; 978 979 if (archive_entry_filetype(entry) != AE_IFREG 980 || archive_entry_size(entry) <= 0 981 || archive_entry_hardlink(entry) != NULL) 982 return (ARCHIVE_OK); 983 984 /* Does filesystem support the reporting of hole ? */ 985 if (*fd < 0 && a->tree != NULL) { 986 const char *path; 987 988 path = archive_entry_sourcepath(entry); 989 if (path == NULL) 990 path = archive_entry_pathname(entry); 991 *fd = a->open_on_current_dir(a->tree, path, 992 O_RDONLY | O_NONBLOCK); 993 if (*fd < 0) { 994 archive_set_error(&a->archive, errno, 995 "Can't open `%s'", path); 996 return (ARCHIVE_FAILED); 997 } 998 } 999 1000 if (*fd >= 0) { 1001 if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) 1002 return (ARCHIVE_OK); 1003 initial_off = lseek(*fd, 0, SEEK_CUR); 1004 if (initial_off != 0) 1005 lseek(*fd, 0, SEEK_SET); 1006 } else { 1007 const char *path; 1008 1009 path = archive_entry_sourcepath(entry); 1010 if (path == NULL) 1011 path = archive_entry_pathname(entry); 1012 1013 if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) 1014 return (ARCHIVE_OK); 1015 *fd = open(path, O_RDONLY | O_NONBLOCK); 1016 if (*fd < 0) { 1017 archive_set_error(&a->archive, errno, 1018 "Can't open `%s'", path); 1019 return (ARCHIVE_FAILED); 1020 } 1021 initial_off = 0; 1022 } 1023 1024 off_s = 0; 1025 size = archive_entry_size(entry); 1026 while (off_s < size) { 1027 off_s = lseek(*fd, off_s, SEEK_DATA); 1028 if (off_s == (off_t)-1) { 1029 if (errno == ENXIO) 1030 break;/* no more hole */ 1031 archive_set_error(&a->archive, errno, 1032 "lseek(SEEK_HOLE) failed"); 1033 exit_sts = ARCHIVE_FAILED; 1034 goto exit_setup_sparse; 1035 } 1036 off_e = lseek(*fd, off_s, SEEK_HOLE); 1037 if (off_e == (off_t)-1) { 1038 if (errno == ENXIO) { 1039 off_e = lseek(*fd, 0, SEEK_END); 1040 if (off_e != (off_t)-1) 1041 break;/* no more data */ 1042 } 1043 archive_set_error(&a->archive, errno, 1044 "lseek(SEEK_DATA) failed"); 1045 exit_sts = ARCHIVE_FAILED; 1046 goto exit_setup_sparse; 1047 } 1048 if (off_s == 0 && off_e == size) 1049 break;/* This is not spase. */ 1050 archive_entry_sparse_add_entry(entry, off_s, 1051 off_e - off_s); 1052 off_s = off_e; 1053 } 1054exit_setup_sparse: 1055 lseek(*fd, initial_off, SEEK_SET); 1056 return (exit_sts); 1057} 1058 1059#else 1060 1061/* 1062 * Generic (stub) sparse support. 1063 */ 1064static int 1065setup_sparse(struct archive_read_disk *a, 1066 struct archive_entry *entry, int *fd) 1067{ 1068 (void)a; /* UNUSED */ 1069 (void)entry; /* UNUSED */ 1070 (void)fd; /* UNUSED */ 1071 return (ARCHIVE_OK); 1072} 1073 1074#endif 1075 1076#endif /* !defined(_WIN32) || defined(__CYGWIN__) */ 1077 1078