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