archive_read_disk_entry_from_file.c revision 358090
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; 253 char *linkbuffer; 254 int lnklen; 255 256 linkbuffer = malloc(linkbuffer_len + 1); 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 ARCHIVE_XATTR_LINUX 620 /* Linux: skip POSIX.1e ACL extended attributes */ 621 if (strncmp(p, "system.", 7) == 0 && 622 (strcmp(p + 7, "posix_acl_access") == 0 || 623 strcmp(p + 7, "posix_acl_default") == 0)) 624 continue; 625 if (strncmp(p, "trusted.SGI_", 12) == 0 && 626 (strcmp(p + 12, "ACL_DEFAULT") == 0 || 627 strcmp(p + 12, "ACL_FILE") == 0)) 628 continue; 629 630 /* Linux: xfsroot namespace is obsolete and unsupported */ 631 if (strncmp(p, "xfsroot.", 8) == 0) 632 continue; 633#endif 634 setup_xattr(a, entry, p, *fd, path); 635 } 636 637 free(list); 638 return (ARCHIVE_OK); 639} 640 641#elif ARCHIVE_XATTR_FREEBSD 642 643/* 644 * FreeBSD extattr interface. 645 */ 646 647/* TODO: Implement this. Follow the Linux model above, but 648 * with FreeBSD-specific system calls, of course. Be careful 649 * to not include the system extattrs that hold ACLs; we handle 650 * those separately. 651 */ 652static int 653setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, 654 int namespace, const char *name, const char *fullname, int fd, 655 const char *path); 656 657static int 658setup_xattr(struct archive_read_disk *a, struct archive_entry *entry, 659 int namespace, const char *name, const char *fullname, int fd, 660 const char *accpath) 661{ 662 ssize_t size; 663 void *value = NULL; 664 665 if (fd >= 0) 666 size = extattr_get_fd(fd, namespace, name, NULL, 0); 667 else if (!a->follow_symlinks) 668 size = extattr_get_link(accpath, namespace, name, NULL, 0); 669 else 670 size = extattr_get_file(accpath, namespace, name, NULL, 0); 671 672 if (size == -1) { 673 archive_set_error(&a->archive, errno, 674 "Couldn't query extended attribute"); 675 return (ARCHIVE_WARN); 676 } 677 678 if (size > 0 && (value = malloc(size)) == NULL) { 679 archive_set_error(&a->archive, errno, "Out of memory"); 680 return (ARCHIVE_FATAL); 681 } 682 683 if (fd >= 0) 684 size = extattr_get_fd(fd, namespace, name, value, size); 685 else if (!a->follow_symlinks) 686 size = extattr_get_link(accpath, namespace, name, value, size); 687 else 688 size = extattr_get_file(accpath, namespace, name, value, size); 689 690 if (size == -1) { 691 free(value); 692 archive_set_error(&a->archive, errno, 693 "Couldn't read extended attribute"); 694 return (ARCHIVE_WARN); 695 } 696 697 archive_entry_xattr_add_entry(entry, fullname, value, size); 698 699 free(value); 700 return (ARCHIVE_OK); 701} 702 703static int 704setup_xattrs(struct archive_read_disk *a, 705 struct archive_entry *entry, int *fd) 706{ 707 char buff[512]; 708 char *list, *p; 709 ssize_t list_size; 710 const char *path; 711 int namespace = EXTATTR_NAMESPACE_USER; 712 713 path = NULL; 714 715 if (*fd < 0) { 716 path = archive_read_disk_entry_setup_path(a, entry, fd); 717 if (path == NULL) 718 return (ARCHIVE_WARN); 719 } 720 721 if (*fd >= 0) 722 list_size = extattr_list_fd(*fd, namespace, NULL, 0); 723 else if (!a->follow_symlinks) 724 list_size = extattr_list_link(path, namespace, NULL, 0); 725 else 726 list_size = extattr_list_file(path, namespace, NULL, 0); 727 728 if (list_size == -1 && errno == EOPNOTSUPP) 729 return (ARCHIVE_OK); 730 if (list_size == -1) { 731 archive_set_error(&a->archive, errno, 732 "Couldn't list extended attributes"); 733 return (ARCHIVE_WARN); 734 } 735 736 if (list_size == 0) 737 return (ARCHIVE_OK); 738 739 if ((list = malloc(list_size)) == NULL) { 740 archive_set_error(&a->archive, errno, "Out of memory"); 741 return (ARCHIVE_FATAL); 742 } 743 744 if (*fd >= 0) 745 list_size = extattr_list_fd(*fd, namespace, list, list_size); 746 else if (!a->follow_symlinks) 747 list_size = extattr_list_link(path, namespace, list, list_size); 748 else 749 list_size = extattr_list_file(path, namespace, list, list_size); 750 751 if (list_size == -1) { 752 archive_set_error(&a->archive, errno, 753 "Couldn't retrieve extended attributes"); 754 free(list); 755 return (ARCHIVE_WARN); 756 } 757 758 p = list; 759 while ((p - list) < list_size) { 760 size_t len = 255 & (int)*p; 761 char *name; 762 763 strcpy(buff, "user."); 764 name = buff + strlen(buff); 765 memcpy(name, p + 1, len); 766 name[len] = '\0'; 767 setup_xattr(a, entry, namespace, name, buff, *fd, path); 768 p += 1 + len; 769 } 770 771 free(list); 772 return (ARCHIVE_OK); 773} 774 775#else 776 777/* 778 * Generic (stub) extended attribute support. 779 */ 780static int 781setup_xattrs(struct archive_read_disk *a, 782 struct archive_entry *entry, int *fd) 783{ 784 (void)a; /* UNUSED */ 785 (void)entry; /* UNUSED */ 786 (void)fd; /* UNUSED */ 787 return (ARCHIVE_OK); 788} 789 790#endif 791 792#if defined(HAVE_LINUX_FIEMAP_H) 793 794/* 795 * Linux FIEMAP sparse interface. 796 * 797 * The FIEMAP ioctl returns an "extent" for each physical allocation 798 * on disk. We need to process those to generate a more compact list 799 * of logical file blocks. We also need to be very careful to use 800 * FIEMAP_FLAG_SYNC here, since there are reports that Linux sometimes 801 * does not report allocations for newly-written data that hasn't 802 * been synced to disk. 803 * 804 * It's important to return a minimal sparse file list because we want 805 * to not trigger sparse file extensions if we don't have to, since 806 * not all readers support them. 807 */ 808 809static int 810setup_sparse_fiemap(struct archive_read_disk *a, 811 struct archive_entry *entry, int *fd) 812{ 813 char buff[4096]; 814 struct fiemap *fm; 815 struct fiemap_extent *fe; 816 int64_t size; 817 int count, do_fiemap, iters; 818 int exit_sts = ARCHIVE_OK; 819 const char *path; 820 821 if (archive_entry_filetype(entry) != AE_IFREG 822 || archive_entry_size(entry) <= 0 823 || archive_entry_hardlink(entry) != NULL) 824 return (ARCHIVE_OK); 825 826 if (*fd < 0) { 827 path = archive_read_disk_entry_setup_path(a, entry, NULL); 828 if (path == NULL) 829 return (ARCHIVE_FAILED); 830 831 if (a->tree != NULL) 832 *fd = a->open_on_current_dir(a->tree, path, 833 O_RDONLY | O_NONBLOCK | O_CLOEXEC); 834 else 835 *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); 836 if (*fd < 0) { 837 archive_set_error(&a->archive, errno, 838 "Can't open `%s'", path); 839 return (ARCHIVE_FAILED); 840 } 841 __archive_ensure_cloexec_flag(*fd); 842 } 843 844 /* Initialize buffer to avoid the error valgrind complains about. */ 845 memset(buff, 0, sizeof(buff)); 846 count = (sizeof(buff) - sizeof(*fm))/sizeof(*fe); 847 fm = (struct fiemap *)buff; 848 fm->fm_start = 0; 849 fm->fm_length = ~0ULL;; 850 fm->fm_flags = FIEMAP_FLAG_SYNC; 851 fm->fm_extent_count = count; 852 do_fiemap = 1; 853 size = archive_entry_size(entry); 854 for (iters = 0; ; ++iters) { 855 int i, r; 856 857 r = ioctl(*fd, FS_IOC_FIEMAP, fm); 858 if (r < 0) { 859 /* When something error happens, it is better we 860 * should return ARCHIVE_OK because an earlier 861 * version(<2.6.28) cannot perform FS_IOC_FIEMAP. */ 862 goto exit_setup_sparse_fiemap; 863 } 864 if (fm->fm_mapped_extents == 0) { 865 if (iters == 0) { 866 /* Fully sparse file; insert a zero-length "data" entry */ 867 archive_entry_sparse_add_entry(entry, 0, 0); 868 } 869 break; 870 } 871 fe = fm->fm_extents; 872 for (i = 0; i < (int)fm->fm_mapped_extents; i++, fe++) { 873 if (!(fe->fe_flags & FIEMAP_EXTENT_UNWRITTEN)) { 874 /* The fe_length of the last block does not 875 * adjust itself to its size files. */ 876 int64_t length = fe->fe_length; 877 if (fe->fe_logical + length > (uint64_t)size) 878 length -= fe->fe_logical + length - size; 879 if (fe->fe_logical == 0 && length == size) { 880 /* This is not sparse. */ 881 do_fiemap = 0; 882 break; 883 } 884 if (length > 0) 885 archive_entry_sparse_add_entry(entry, 886 fe->fe_logical, length); 887 } 888 if (fe->fe_flags & FIEMAP_EXTENT_LAST) 889 do_fiemap = 0; 890 } 891 if (do_fiemap) { 892 fe = fm->fm_extents + fm->fm_mapped_extents -1; 893 fm->fm_start = fe->fe_logical + fe->fe_length; 894 } else 895 break; 896 } 897exit_setup_sparse_fiemap: 898 return (exit_sts); 899} 900 901#if !defined(SEEK_HOLE) || !defined(SEEK_DATA) 902static int 903setup_sparse(struct archive_read_disk *a, 904 struct archive_entry *entry, int *fd) 905{ 906 return setup_sparse_fiemap(a, entry, fd); 907} 908#endif 909#endif /* defined(HAVE_LINUX_FIEMAP_H) */ 910 911#if defined(SEEK_HOLE) && defined(SEEK_DATA) 912 913/* 914 * SEEK_HOLE sparse interface (FreeBSD, Linux, Solaris) 915 */ 916 917static int 918setup_sparse(struct archive_read_disk *a, 919 struct archive_entry *entry, int *fd) 920{ 921 int64_t size; 922 off_t initial_off; 923 off_t off_s, off_e; 924 int exit_sts = ARCHIVE_OK; 925 int check_fully_sparse = 0; 926 const char *path; 927 928 if (archive_entry_filetype(entry) != AE_IFREG 929 || archive_entry_size(entry) <= 0 930 || archive_entry_hardlink(entry) != NULL) 931 return (ARCHIVE_OK); 932 933 /* Does filesystem support the reporting of hole ? */ 934 if (*fd < 0) 935 path = archive_read_disk_entry_setup_path(a, entry, fd); 936 else 937 path = NULL; 938 939 if (*fd >= 0) { 940#ifdef _PC_MIN_HOLE_SIZE 941 if (fpathconf(*fd, _PC_MIN_HOLE_SIZE) <= 0) 942 return (ARCHIVE_OK); 943#endif 944 initial_off = lseek(*fd, 0, SEEK_CUR); 945 if (initial_off != 0) 946 lseek(*fd, 0, SEEK_SET); 947 } else { 948 if (path == NULL) 949 return (ARCHIVE_FAILED); 950#ifdef _PC_MIN_HOLE_SIZE 951 if (pathconf(path, _PC_MIN_HOLE_SIZE) <= 0) 952 return (ARCHIVE_OK); 953#endif 954 *fd = open(path, O_RDONLY | O_NONBLOCK | O_CLOEXEC); 955 if (*fd < 0) { 956 archive_set_error(&a->archive, errno, 957 "Can't open `%s'", path); 958 return (ARCHIVE_FAILED); 959 } 960 __archive_ensure_cloexec_flag(*fd); 961 initial_off = 0; 962 } 963 964#ifndef _PC_MIN_HOLE_SIZE 965 /* Check if the underlying filesystem supports seek hole */ 966 off_s = lseek(*fd, 0, SEEK_HOLE); 967 if (off_s < 0) 968#if defined(HAVE_LINUX_FIEMAP_H) 969 return setup_sparse_fiemap(a, entry, fd); 970#else 971 goto exit_setup_sparse; 972#endif 973 else if (off_s > 0) 974 lseek(*fd, 0, SEEK_SET); 975#endif 976 977 off_s = 0; 978 size = archive_entry_size(entry); 979 while (off_s < size) { 980 off_s = lseek(*fd, off_s, SEEK_DATA); 981 if (off_s == (off_t)-1) { 982 if (errno == ENXIO) { 983 /* no more hole */ 984 if (archive_entry_sparse_count(entry) == 0) { 985 /* Potentially a fully-sparse file. */ 986 check_fully_sparse = 1; 987 } 988 break; 989 } 990 archive_set_error(&a->archive, errno, 991 "lseek(SEEK_HOLE) failed"); 992 exit_sts = ARCHIVE_FAILED; 993 goto exit_setup_sparse; 994 } 995 off_e = lseek(*fd, off_s, SEEK_HOLE); 996 if (off_e == (off_t)-1) { 997 if (errno == ENXIO) { 998 off_e = lseek(*fd, 0, SEEK_END); 999 if (off_e != (off_t)-1) 1000 break;/* no more data */ 1001 } 1002 archive_set_error(&a->archive, errno, 1003 "lseek(SEEK_DATA) failed"); 1004 exit_sts = ARCHIVE_FAILED; 1005 goto exit_setup_sparse; 1006 } 1007 if (off_s == 0 && off_e == size) 1008 break;/* This is not sparse. */ 1009 archive_entry_sparse_add_entry(entry, off_s, 1010 off_e - off_s); 1011 off_s = off_e; 1012 } 1013 1014 if (check_fully_sparse) { 1015 if (lseek(*fd, 0, SEEK_HOLE) == 0 && 1016 lseek(*fd, 0, SEEK_END) == size) { 1017 /* Fully sparse file; insert a zero-length "data" entry */ 1018 archive_entry_sparse_add_entry(entry, 0, 0); 1019 } 1020 } 1021exit_setup_sparse: 1022 lseek(*fd, initial_off, SEEK_SET); 1023 return (exit_sts); 1024} 1025 1026#elif !defined(HAVE_LINUX_FIEMAP_H) 1027 1028/* 1029 * Generic (stub) sparse support. 1030 */ 1031static int 1032setup_sparse(struct archive_read_disk *a, 1033 struct archive_entry *entry, int *fd) 1034{ 1035 (void)a; /* UNUSED */ 1036 (void)entry; /* UNUSED */ 1037 (void)fd; /* UNUSED */ 1038 return (ARCHIVE_OK); 1039} 1040 1041#endif 1042 1043#endif /* !defined(_WIN32) || defined(__CYGWIN__) */ 1044 1045