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