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