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