1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2003-2007 Tim Kientzle 5 * All rights reserved. 6 */ 7 8 9 #include "cpio_platform.h" 10 11 #include <sys/types.h> 12 #include <archive.h> 13 #include <archive_entry.h> 14 15 #ifdef HAVE_SYS_MKDEV_H 16 #include <sys/mkdev.h> 17 #endif 18 #ifdef HAVE_SYS_STAT_H 19 #include <sys/stat.h> 20 #endif 21 #ifdef HAVE_SYS_TIME_H 22 #include <sys/time.h> 23 #endif 24 #ifdef HAVE_ERRNO_H 25 #include <errno.h> 26 #endif 27 #ifdef HAVE_FCNTL_H 28 #include <fcntl.h> 29 #endif 30 #ifdef HAVE_GRP_H 31 #include <grp.h> 32 #endif 33 #ifdef HAVE_LOCALE_H 34 #include <locale.h> 35 #endif 36 #ifdef HAVE_PWD_H 37 #include <pwd.h> 38 #endif 39 #ifdef HAVE_SIGNAL_H 40 #include <signal.h> 41 #endif 42 #ifdef HAVE_STDARG_H 43 #include <stdarg.h> 44 #endif 45 #ifdef HAVE_STDINT_H 46 #include <stdint.h> 47 #endif 48 #include <stdio.h> 49 #ifdef HAVE_STDLIB_H 50 #include <stdlib.h> 51 #endif 52 #ifdef HAVE_STRING_H 53 #include <string.h> 54 #endif 55 #ifdef HAVE_UNISTD_H 56 #include <unistd.h> 57 #endif 58 #ifdef HAVE_TIME_H 59 #include <time.h> 60 #endif 61 62 #include "cpio.h" 63 #include "err.h" 64 #include "line_reader.h" 65 #include "passphrase.h" 66 67 /* Fixed size of uname/gname caches. */ 68 #define name_cache_size 101 69 70 #ifndef O_BINARY 71 #define O_BINARY 0 72 #endif 73 74 struct name_cache { 75 int probes; 76 int hits; 77 size_t size; 78 struct { 79 id_t id; 80 char *name; 81 } cache[name_cache_size]; 82 }; 83 84 static int extract_data(struct archive *, struct archive *); 85 const char * cpio_i64toa(int64_t); 86 static const char *cpio_rename(const char *name); 87 static int entry_to_archive(struct cpio *, struct archive_entry *); 88 static int file_to_archive(struct cpio *, const char *); 89 static void free_cache(struct name_cache *cache); 90 static void list_item_verbose(struct cpio *, struct archive_entry *); 91 static __LA_NORETURN void long_help(void); 92 static const char *lookup_gname(struct cpio *, gid_t gid); 93 static int lookup_gname_helper(struct cpio *, 94 const char **name, id_t gid); 95 static const char *lookup_uname(struct cpio *, uid_t uid); 96 static int lookup_uname_helper(struct cpio *, 97 const char **name, id_t uid); 98 static __LA_NORETURN void mode_in(struct cpio *); 99 static __LA_NORETURN void mode_list(struct cpio *); 100 static void mode_out(struct cpio *); 101 static void mode_pass(struct cpio *, const char *); 102 static const char *remove_leading_slash(const char *); 103 static int restore_time(struct cpio *, struct archive_entry *, 104 const char *, int fd); 105 static __LA_NORETURN void usage(void); 106 static __LA_NORETURN void version(void); 107 static const char * passphrase_callback(struct archive *, void *); 108 static void passphrase_free(char *); 109 110 int 111 main(int argc, char *argv[]) 112 { 113 static char buff[16384]; 114 struct cpio _cpio; /* Allocated on stack. */ 115 struct cpio *cpio; 116 struct cpio_owner owner; 117 const char *errmsg; 118 char *tptr; 119 int opt, t; 120 121 cpio = &_cpio; 122 memset(cpio, 0, sizeof(*cpio)); 123 cpio->buff = buff; 124 cpio->buff_size = sizeof(buff); 125 126 127 #if defined(HAVE_SIGACTION) && defined(SIGPIPE) 128 { /* Ignore SIGPIPE signals. */ 129 struct sigaction sa; 130 sigemptyset(&sa.sa_mask); 131 sa.sa_flags = 0; 132 sa.sa_handler = SIG_IGN; 133 sigaction(SIGPIPE, &sa, NULL); 134 } 135 #endif 136 137 /* Set lafe_progname before calling lafe_warnc. */ 138 lafe_setprogname(*argv, "bsdcpio"); 139 140 #if HAVE_SETLOCALE 141 if (setlocale(LC_ALL, "") == NULL) 142 lafe_warnc(0, "Failed to set default locale"); 143 #endif 144 145 cpio->uid_override = -1; 146 cpio->uname_override = NULL; 147 cpio->gid_override = -1; 148 cpio->gname_override = NULL; 149 cpio->argv = argv; 150 cpio->argc = argc; 151 cpio->mode = '\0'; 152 cpio->verbose = 0; 153 cpio->compress = '\0'; 154 cpio->extract_flags = ARCHIVE_EXTRACT_NO_AUTODIR; 155 cpio->extract_flags |= ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; 156 cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_SYMLINKS; 157 cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NODOTDOT; 158 cpio->extract_flags |= ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; 159 cpio->extract_flags |= ARCHIVE_EXTRACT_PERM; 160 cpio->extract_flags |= ARCHIVE_EXTRACT_FFLAGS; 161 cpio->extract_flags |= ARCHIVE_EXTRACT_ACL; 162 #if !defined(_WIN32) && !defined(__CYGWIN__) 163 if (geteuid() == 0) 164 cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER; 165 #endif 166 cpio->bytes_per_block = 512; 167 cpio->filename = NULL; 168 169 cpio->matching = archive_match_new(); 170 if (cpio->matching == NULL) 171 lafe_errc(1, 0, "Out of memory"); 172 173 while ((opt = cpio_getopt(cpio)) != -1) { 174 switch (opt) { 175 case '0': /* GNU convention: --null, -0 */ 176 cpio->option_null = 1; 177 break; 178 case '6': /* in/out: assume/create 6th edition (PWB) format */ 179 cpio->option_pwb = 1; 180 break; 181 case '7': /* out: create archive using 7th Edition binary format */ 182 cpio->format = "bin"; 183 break; 184 case 'A': /* NetBSD/OpenBSD */ 185 cpio->option_append = 1; 186 break; 187 case 'a': /* POSIX 1997 */ 188 cpio->option_atime_restore = 1; 189 break; 190 case 'B': /* POSIX 1997 */ 191 cpio->bytes_per_block = 5120; 192 break; 193 case OPTION_B64ENCODE: 194 cpio->add_filter = opt; 195 break; 196 case 'C': /* NetBSD/OpenBSD */ 197 errno = 0; 198 tptr = NULL; 199 t = (int)strtol(cpio->argument, &tptr, 10); 200 if (errno || t <= 0 || *(cpio->argument) == '\0' || 201 tptr == NULL || *tptr != '\0') { 202 lafe_errc(1, 0, "Invalid blocksize: %s", 203 cpio->argument); 204 } 205 cpio->bytes_per_block = t; 206 break; 207 case 'c': /* POSIX 1997 */ 208 cpio->format = "odc"; 209 break; 210 case 'd': /* POSIX 1997 */ 211 cpio->extract_flags &= ~ARCHIVE_EXTRACT_NO_AUTODIR; 212 break; 213 case 'E': /* NetBSD/OpenBSD */ 214 if (archive_match_include_pattern_from_file( 215 cpio->matching, cpio->argument, 216 cpio->option_null) != ARCHIVE_OK) 217 lafe_errc(1, 0, "Error : %s", 218 archive_error_string(cpio->matching)); 219 break; 220 case 'F': /* NetBSD/OpenBSD/GNU cpio */ 221 cpio->filename = cpio->argument; 222 break; 223 case 'f': /* POSIX 1997 */ 224 if (archive_match_exclude_pattern(cpio->matching, 225 cpio->argument) != ARCHIVE_OK) 226 lafe_errc(1, 0, "Error : %s", 227 archive_error_string(cpio->matching)); 228 break; 229 case OPTION_GRZIP: 230 cpio->compress = opt; 231 break; 232 case 'H': /* GNU cpio (also --format) */ 233 cpio->format = cpio->argument; 234 break; 235 case 'h': 236 long_help(); 237 /* NOTREACHED */ 238 case 'I': /* NetBSD/OpenBSD */ 239 cpio->filename = cpio->argument; 240 break; 241 case 'i': /* POSIX 1997 */ 242 if (cpio->mode != '\0') 243 lafe_errc(1, 0, 244 "Cannot use both -i and -%c", cpio->mode); 245 cpio->mode = opt; 246 break; 247 case 'J': /* GNU tar, others */ 248 cpio->compress = opt; 249 break; 250 case 'j': /* GNU tar, others */ 251 cpio->compress = opt; 252 break; 253 case OPTION_INSECURE: 254 cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_SYMLINKS; 255 cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; 256 cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; 257 break; 258 case 'L': /* GNU cpio */ 259 cpio->option_follow_links = 1; 260 break; 261 case 'l': /* POSIX 1997 */ 262 cpio->option_link = 1; 263 break; 264 case OPTION_LRZIP: 265 case OPTION_LZ4: 266 case OPTION_LZMA: /* GNU tar, others */ 267 case OPTION_LZOP: /* GNU tar, others */ 268 case OPTION_ZSTD: 269 cpio->compress = opt; 270 break; 271 case 'm': /* POSIX 1997 */ 272 cpio->extract_flags |= ARCHIVE_EXTRACT_TIME; 273 break; 274 case 'n': /* GNU cpio */ 275 cpio->option_numeric_uid_gid = 1; 276 break; 277 case OPTION_NO_PRESERVE_OWNER: /* GNU cpio */ 278 cpio->extract_flags &= ~ARCHIVE_EXTRACT_OWNER; 279 break; 280 case 'O': /* GNU cpio */ 281 cpio->filename = cpio->argument; 282 break; 283 case 'o': /* POSIX 1997 */ 284 if (cpio->mode != '\0') 285 lafe_errc(1, 0, 286 "Cannot use both -o and -%c", cpio->mode); 287 cpio->mode = opt; 288 break; 289 case 'p': /* POSIX 1997 */ 290 if (cpio->mode != '\0') 291 lafe_errc(1, 0, 292 "Cannot use both -p and -%c", cpio->mode); 293 cpio->mode = opt; 294 cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NODOTDOT; 295 cpio->extract_flags &= ~ARCHIVE_EXTRACT_SECURE_NOABSOLUTEPATHS; 296 break; 297 case OPTION_PASSPHRASE: 298 cpio->passphrase = cpio->argument; 299 break; 300 case OPTION_PRESERVE_OWNER: 301 cpio->extract_flags |= ARCHIVE_EXTRACT_OWNER; 302 break; 303 case OPTION_QUIET: /* GNU cpio */ 304 cpio->quiet = 1; 305 break; 306 case 'R': /* GNU cpio, also --owner */ 307 errmsg = NULL; 308 if (owner_parse(cpio->argument, &owner, &errmsg) != 0) { 309 if (!errmsg) 310 errmsg = "Error parsing owner"; 311 lafe_warnc(-1, "%s", errmsg); 312 usage(); 313 } 314 if (owner.uid != -1) 315 cpio->uid_override = owner.uid; 316 if (owner.uname != NULL) 317 cpio->uname_override = owner.uname; 318 if (owner.gid != -1) 319 cpio->gid_override = owner.gid; 320 if (owner.gname != NULL) 321 cpio->gname_override = owner.gname; 322 break; 323 case 'r': /* POSIX 1997 */ 324 cpio->option_rename = 1; 325 break; 326 case 't': /* POSIX 1997 */ 327 cpio->option_list = 1; 328 break; 329 case 'u': /* POSIX 1997 */ 330 cpio->extract_flags 331 &= ~ARCHIVE_EXTRACT_NO_OVERWRITE_NEWER; 332 break; 333 case OPTION_UUENCODE: 334 cpio->add_filter = opt; 335 break; 336 case 'v': /* POSIX 1997 */ 337 cpio->verbose++; 338 break; 339 case 'V': /* GNU cpio */ 340 cpio->dot++; 341 break; 342 case OPTION_VERSION: /* GNU convention */ 343 version(); 344 /* NOTREACHED */ 345 #if 0 346 /* 347 * cpio_getopt() handles -W specially, so it's not 348 * available here. 349 */ 350 case 'W': /* Obscure, but useful GNU convention. */ 351 break; 352 #endif 353 case 'y': /* tar convention */ 354 cpio->compress = opt; 355 break; 356 case 'Z': /* tar convention */ 357 cpio->compress = opt; 358 break; 359 case 'z': /* tar convention */ 360 cpio->compress = opt; 361 break; 362 default: 363 usage(); 364 } 365 } 366 367 /* 368 * Sanity-check args, error out on nonsensical combinations. 369 */ 370 /* -t implies -i if no mode was specified. */ 371 if (cpio->option_list && cpio->mode == '\0') 372 cpio->mode = 'i'; 373 /* -t requires -i */ 374 if (cpio->option_list && cpio->mode != 'i') 375 lafe_errc(1, 0, "Option -t requires -i"); 376 /* -n requires -it */ 377 if (cpio->option_numeric_uid_gid && !cpio->option_list) 378 lafe_errc(1, 0, "Option -n requires -it"); 379 /* Can only specify format when writing */ 380 if (cpio->format != NULL && cpio->mode != 'o') 381 lafe_errc(1, 0, "Option --format requires -o"); 382 /* -l requires -p */ 383 if (cpio->option_link && cpio->mode != 'p') 384 lafe_errc(1, 0, "Option -l requires -p"); 385 /* -v overrides -V */ 386 if (cpio->dot && cpio->verbose) 387 cpio->dot = 0; 388 /* TODO: Flag other nonsensical combinations. */ 389 390 switch (cpio->mode) { 391 case 'o': 392 if (cpio->format == NULL) { 393 if (cpio->option_pwb) 394 cpio->format = "pwb"; 395 else 396 cpio->format = "cpio"; 397 } 398 mode_out(cpio); 399 break; 400 case 'i': 401 while (*cpio->argv != NULL) { 402 if (archive_match_include_pattern(cpio->matching, 403 *cpio->argv) != ARCHIVE_OK) 404 lafe_errc(1, 0, "Error : %s", 405 archive_error_string(cpio->matching)); 406 --cpio->argc; 407 ++cpio->argv; 408 } 409 if (cpio->option_list) 410 mode_list(cpio); 411 else 412 mode_in(cpio); 413 /* NOTREACHED */ 414 case 'p': 415 if (*cpio->argv == NULL || **cpio->argv == '\0') 416 lafe_errc(1, 0, 417 "-p mode requires a target directory"); 418 mode_pass(cpio, *cpio->argv); 419 break; 420 default: 421 lafe_errc(1, 0, 422 "Must specify at least one of -i, -o, or -p"); 423 } 424 425 archive_match_free(cpio->matching); 426 free_cache(cpio->uname_cache); 427 free(cpio->uname_override); 428 free_cache(cpio->gname_cache); 429 free(cpio->gname_override); 430 archive_read_close(cpio->archive_read_disk); 431 archive_read_free(cpio->archive_read_disk); 432 free(cpio->destdir); 433 434 passphrase_free(cpio->ppbuff); 435 return (cpio->return_value); 436 } 437 438 static void 439 usage(void) 440 { 441 const char *p; 442 443 p = lafe_getprogname(); 444 445 fprintf(stderr, "Brief Usage:\n"); 446 fprintf(stderr, " List: %s -it < archive\n", p); 447 fprintf(stderr, " Extract: %s -i < archive\n", p); 448 fprintf(stderr, " Create: %s -o < filenames > archive\n", p); 449 fprintf(stderr, " Help: %s --help\n", p); 450 exit(1); 451 } 452 453 static const char *long_help_msg = 454 "First option must be a mode specifier:\n" 455 " -i Input -o Output -p Pass\n" 456 "Common Options:\n" 457 " -v Verbose filenames -V one dot per file\n" 458 "Create: %p -o [options] < [list of files] > [archive]\n" 459 " -J,-y,-z,--lzma Compress archive with xz/bzip2/gzip/lzma\n" 460 " --format {pwb|bin|odc|newc|ustar} Select archive format\n" 461 "List: %p -it < [archive]\n" 462 "Extract: %p -i [options] < [archive]\n"; 463 464 465 /* 466 * Note that the word 'bsdcpio' will always appear in the first line 467 * of output. 468 * 469 * In particular, /bin/sh scripts that need to test for the presence 470 * of bsdcpio can use the following template: 471 * 472 * if (cpio --help 2>&1 | grep bsdcpio >/dev/null 2>&1 ) then \ 473 * echo bsdcpio; else echo not bsdcpio; fi 474 */ 475 static void 476 long_help(void) 477 { 478 const char *prog; 479 const char *p; 480 481 prog = lafe_getprogname(); 482 483 fflush(stderr); 484 485 p = (strcmp(prog,"bsdcpio") != 0) ? "(bsdcpio)" : ""; 486 printf("%s%s: manipulate archive files\n", prog, p); 487 488 for (p = long_help_msg; *p != '\0'; p++) { 489 if (*p == '%') { 490 if (p[1] == 'p') { 491 fputs(prog, stdout); 492 p++; 493 } else 494 putchar('%'); 495 } else 496 putchar(*p); 497 } 498 version(); 499 } 500 501 static void 502 version(void) 503 { 504 fprintf(stdout,"bsdcpio %s - %s \n", 505 BSDCPIO_VERSION_STRING, 506 archive_version_details()); 507 exit(0); 508 } 509 510 static void 511 mode_out(struct cpio *cpio) 512 { 513 struct archive_entry *entry, *spare; 514 struct lafe_line_reader *lr; 515 const char *p; 516 int r; 517 518 if (cpio->option_append) 519 lafe_errc(1, 0, "Append mode not yet supported."); 520 521 cpio->archive_read_disk = archive_read_disk_new(); 522 if (cpio->archive_read_disk == NULL) 523 lafe_errc(1, 0, "Failed to allocate archive object"); 524 if (cpio->option_follow_links) 525 archive_read_disk_set_symlink_logical(cpio->archive_read_disk); 526 else 527 archive_read_disk_set_symlink_physical(cpio->archive_read_disk); 528 archive_read_disk_set_standard_lookup(cpio->archive_read_disk); 529 530 cpio->archive = archive_write_new(); 531 if (cpio->archive == NULL) 532 lafe_errc(1, 0, "Failed to allocate archive object"); 533 switch (cpio->compress) { 534 case OPTION_GRZIP: 535 r = archive_write_add_filter_grzip(cpio->archive); 536 break; 537 case 'J': 538 r = archive_write_add_filter_xz(cpio->archive); 539 break; 540 case OPTION_LRZIP: 541 r = archive_write_add_filter_lrzip(cpio->archive); 542 break; 543 case OPTION_LZ4: 544 r = archive_write_add_filter_lz4(cpio->archive); 545 break; 546 case OPTION_LZMA: 547 r = archive_write_add_filter_lzma(cpio->archive); 548 break; 549 case OPTION_LZOP: 550 r = archive_write_add_filter_lzop(cpio->archive); 551 break; 552 case OPTION_ZSTD: 553 r = archive_write_add_filter_zstd(cpio->archive); 554 break; 555 case 'j': case 'y': 556 r = archive_write_add_filter_bzip2(cpio->archive); 557 break; 558 case 'z': 559 r = archive_write_add_filter_gzip(cpio->archive); 560 break; 561 case 'Z': 562 r = archive_write_add_filter_compress(cpio->archive); 563 break; 564 default: 565 r = archive_write_add_filter_none(cpio->archive); 566 break; 567 } 568 if (r < ARCHIVE_WARN) 569 lafe_errc(1, 0, "Requested compression not available"); 570 switch (cpio->add_filter) { 571 case 0: 572 r = ARCHIVE_OK; 573 break; 574 case OPTION_B64ENCODE: 575 r = archive_write_add_filter_b64encode(cpio->archive); 576 break; 577 case OPTION_UUENCODE: 578 r = archive_write_add_filter_uuencode(cpio->archive); 579 break; 580 } 581 if (r < ARCHIVE_WARN) 582 lafe_errc(1, 0, "Requested filter not available"); 583 r = archive_write_set_format_by_name(cpio->archive, cpio->format); 584 if (r != ARCHIVE_OK) 585 lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); 586 archive_write_set_bytes_per_block(cpio->archive, cpio->bytes_per_block); 587 cpio->linkresolver = archive_entry_linkresolver_new(); 588 archive_entry_linkresolver_set_strategy(cpio->linkresolver, 589 archive_format(cpio->archive)); 590 if (cpio->passphrase != NULL) 591 r = archive_write_set_passphrase(cpio->archive, 592 cpio->passphrase); 593 else 594 r = archive_write_set_passphrase_callback(cpio->archive, cpio, 595 &passphrase_callback); 596 if (r != ARCHIVE_OK) 597 lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); 598 599 /* 600 * The main loop: Copy each file into the output archive. 601 */ 602 r = archive_write_open_filename(cpio->archive, cpio->filename); 603 if (r != ARCHIVE_OK) 604 lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); 605 lr = lafe_line_reader("-", cpio->option_null); 606 while ((p = lafe_line_reader_next(lr)) != NULL) 607 file_to_archive(cpio, p); 608 lafe_line_reader_free(lr); 609 610 /* 611 * The hardlink detection may have queued up a couple of entries 612 * that can now be flushed. 613 */ 614 entry = NULL; 615 archive_entry_linkify(cpio->linkresolver, &entry, &spare); 616 while (entry != NULL) { 617 entry_to_archive(cpio, entry); 618 archive_entry_free(entry); 619 entry = NULL; 620 archive_entry_linkify(cpio->linkresolver, &entry, &spare); 621 } 622 623 r = archive_write_close(cpio->archive); 624 if (cpio->dot) 625 fprintf(stderr, "\n"); 626 if (r != ARCHIVE_OK) 627 lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); 628 629 if (!cpio->quiet) { 630 int64_t blocks = 631 (archive_filter_bytes(cpio->archive, 0) + 511) 632 / 512; 633 fprintf(stderr, "%lu %s\n", (unsigned long)blocks, 634 blocks == 1 ? "block" : "blocks"); 635 } 636 archive_write_free(cpio->archive); 637 archive_entry_linkresolver_free(cpio->linkresolver); 638 } 639 640 static const char * 641 remove_leading_slash(const char *p) 642 { 643 const char *rp; 644 645 /* Remove leading "//./" or "//?/" or "//?/UNC/" 646 * (absolute path prefixes used by Windows API) */ 647 if ((p[0] == '/' || p[0] == '\\') && 648 (p[1] == '/' || p[1] == '\\') && 649 (p[2] == '.' || p[2] == '?') && 650 (p[3] == '/' || p[3] == '\\')) 651 { 652 if (p[2] == '?' && 653 (p[4] == 'U' || p[4] == 'u') && 654 (p[5] == 'N' || p[5] == 'n') && 655 (p[6] == 'C' || p[6] == 'c') && 656 (p[7] == '/' || p[7] == '\\')) 657 p += 8; 658 else 659 p += 4; 660 } 661 do { 662 rp = p; 663 /* Remove leading drive letter from archives created 664 * on Windows. */ 665 if (((p[0] >= 'a' && p[0] <= 'z') || 666 (p[0] >= 'A' && p[0] <= 'Z')) && 667 p[1] == ':') { 668 p += 2; 669 } 670 /* Remove leading "/../", "//", etc. */ 671 while (p[0] == '/' || p[0] == '\\') { 672 if (p[1] == '.' && p[2] == '.' && 673 (p[3] == '/' || p[3] == '\\')) { 674 p += 3; /* Remove "/..", leave "/" 675 * for next pass. */ 676 } else 677 p += 1; /* Remove "/". */ 678 } 679 } while (rp != p); 680 return (p); 681 } 682 683 /* 684 * This is used by both out mode (to copy objects from disk into 685 * an archive) and pass mode (to copy objects from disk to 686 * an archive_write_disk "archive"). 687 */ 688 static int 689 file_to_archive(struct cpio *cpio, const char *srcpath) 690 { 691 const char *destpath; 692 struct archive_entry *entry, *spare; 693 size_t len; 694 int r; 695 696 /* 697 * Create an archive_entry describing the source file. 698 * 699 */ 700 entry = archive_entry_new(); 701 if (entry == NULL) 702 lafe_errc(1, 0, "Couldn't allocate entry"); 703 archive_entry_copy_sourcepath(entry, srcpath); 704 r = archive_read_disk_entry_from_file(cpio->archive_read_disk, 705 entry, -1, NULL); 706 if (r < ARCHIVE_FAILED) 707 lafe_errc(1, 0, "%s", 708 archive_error_string(cpio->archive_read_disk)); 709 if (r < ARCHIVE_OK) 710 lafe_warnc(0, "%s", 711 archive_error_string(cpio->archive_read_disk)); 712 if (r <= ARCHIVE_FAILED) { 713 archive_entry_free(entry); 714 cpio->return_value = 1; 715 return (r); 716 } 717 718 if (cpio->uid_override >= 0) 719 archive_entry_set_uid(entry, cpio->uid_override); 720 if (cpio->gname_override != NULL) 721 archive_entry_set_uname(entry, cpio->uname_override); 722 if (cpio->gid_override >= 0) 723 archive_entry_set_gid(entry, cpio->gid_override); 724 if (cpio->gname_override != NULL) 725 archive_entry_set_gname(entry, cpio->gname_override); 726 727 /* 728 * Generate a destination path for this entry. 729 * "destination path" is the name to which it will be copied in 730 * pass mode or the name that will go into the archive in 731 * output mode. 732 */ 733 destpath = srcpath; 734 if (cpio->destdir) { 735 len = cpio->destdir_len + strlen(srcpath) + 8; 736 if (len >= cpio->pass_destpath_alloc) { 737 while (len >= cpio->pass_destpath_alloc) { 738 cpio->pass_destpath_alloc += 512; 739 cpio->pass_destpath_alloc *= 2; 740 } 741 free(cpio->pass_destpath); 742 cpio->pass_destpath = malloc(cpio->pass_destpath_alloc); 743 if (cpio->pass_destpath == NULL) 744 lafe_errc(1, ENOMEM, 745 "Can't allocate path buffer"); 746 } 747 strcpy(cpio->pass_destpath, cpio->destdir); 748 strcat(cpio->pass_destpath, remove_leading_slash(srcpath)); 749 destpath = cpio->pass_destpath; 750 } 751 if (cpio->option_rename) 752 destpath = cpio_rename(destpath); 753 if (destpath == NULL) { 754 archive_entry_free(entry); 755 return (0); 756 } 757 archive_entry_copy_pathname(entry, destpath); 758 759 /* 760 * If we're trying to preserve hardlinks, match them here. 761 */ 762 spare = NULL; 763 if (cpio->linkresolver != NULL 764 && archive_entry_filetype(entry) != AE_IFDIR) { 765 archive_entry_linkify(cpio->linkresolver, &entry, &spare); 766 } 767 768 if (entry != NULL) { 769 r = entry_to_archive(cpio, entry); 770 archive_entry_free(entry); 771 if (spare != NULL) { 772 if (r == 0) 773 r = entry_to_archive(cpio, spare); 774 archive_entry_free(spare); 775 } 776 } 777 return (r); 778 } 779 780 static int 781 entry_to_archive(struct cpio *cpio, struct archive_entry *entry) 782 { 783 const char *destpath = archive_entry_pathname(entry); 784 const char *srcpath = archive_entry_sourcepath(entry); 785 int fd = -1; 786 ssize_t bytes_read; 787 int r; 788 789 /* Print out the destination name to the user. */ 790 if (cpio->verbose) 791 fprintf(stderr,"%s", destpath); 792 if (cpio->dot) 793 fprintf(stderr, "."); 794 795 /* 796 * Option_link only makes sense in pass mode and for 797 * regular files. Also note: if a link operation fails 798 * because of cross-device restrictions, we'll fall back 799 * to copy mode for that entry. 800 * 801 * TODO: Test other cpio implementations to see if they 802 * hard-link anything other than regular files here. 803 */ 804 if (cpio->option_link 805 && archive_entry_filetype(entry) == AE_IFREG) 806 { 807 struct archive_entry *t; 808 /* Save the original entry in case we need it later. */ 809 t = archive_entry_clone(entry); 810 if (t == NULL) 811 lafe_errc(1, ENOMEM, "Can't create link"); 812 /* Note: link(2) doesn't create parent directories, 813 * so we use archive_write_header() instead as a 814 * convenience. */ 815 archive_entry_set_hardlink(t, srcpath); 816 /* This is a straight link that carries no data. */ 817 archive_entry_set_size(t, 0); 818 r = archive_write_header(cpio->archive, t); 819 archive_entry_free(t); 820 if (r != ARCHIVE_OK) 821 lafe_warnc(archive_errno(cpio->archive), 822 "%s", archive_error_string(cpio->archive)); 823 if (r == ARCHIVE_FATAL) 824 exit(1); 825 #ifdef EXDEV 826 if (r != ARCHIVE_OK && archive_errno(cpio->archive) == EXDEV) { 827 /* Cross-device link: Just fall through and use 828 * the original entry to copy the file over. */ 829 lafe_warnc(0, "Copying file instead"); 830 } else 831 #endif 832 return (0); 833 } 834 835 /* 836 * Make sure we can open the file (if necessary) before 837 * trying to write the header. 838 */ 839 if (archive_entry_filetype(entry) == AE_IFREG) { 840 if (archive_entry_size(entry) > 0) { 841 fd = open(srcpath, O_RDONLY | O_BINARY); 842 if (fd < 0) { 843 lafe_warnc(errno, 844 "%s: could not open file", srcpath); 845 goto cleanup; 846 } 847 } 848 } else { 849 archive_entry_set_size(entry, 0); 850 } 851 852 r = archive_write_header(cpio->archive, entry); 853 854 if (r != ARCHIVE_OK) 855 lafe_warnc(archive_errno(cpio->archive), 856 "%s: %s", 857 srcpath, 858 archive_error_string(cpio->archive)); 859 860 if (r == ARCHIVE_FATAL) 861 exit(1); 862 863 if (r >= ARCHIVE_WARN && archive_entry_size(entry) > 0 && fd >= 0) { 864 bytes_read = read(fd, cpio->buff, (unsigned)cpio->buff_size); 865 while (bytes_read > 0) { 866 ssize_t bytes_write; 867 bytes_write = archive_write_data(cpio->archive, 868 cpio->buff, bytes_read); 869 if (bytes_write < 0) 870 lafe_errc(1, archive_errno(cpio->archive), 871 "%s", archive_error_string(cpio->archive)); 872 if (bytes_write < bytes_read) { 873 lafe_warnc(0, 874 "Truncated write; file may have " 875 "grown while being archived."); 876 } 877 bytes_read = read(fd, cpio->buff, 878 (unsigned)cpio->buff_size); 879 } 880 } 881 882 fd = restore_time(cpio, entry, srcpath, fd); 883 884 cleanup: 885 if (cpio->verbose) 886 fprintf(stderr,"\n"); 887 if (fd >= 0) 888 close(fd); 889 return (0); 890 } 891 892 static int 893 restore_time(struct cpio *cpio, struct archive_entry *entry, 894 const char *name, int fd) 895 { 896 #ifndef HAVE_UTIMES 897 static int warned = 0; 898 899 (void)cpio; /* UNUSED */ 900 (void)entry; /* UNUSED */ 901 (void)name; /* UNUSED */ 902 903 if (!warned) 904 lafe_warnc(0, "Can't restore access times on this platform"); 905 warned = 1; 906 return (fd); 907 #else 908 #if defined(_WIN32) && !defined(__CYGWIN__) 909 struct __timeval times[2]; 910 #else 911 struct timeval times[2]; 912 #endif 913 914 if (!cpio->option_atime_restore) 915 return (fd); 916 917 times[1].tv_sec = archive_entry_mtime(entry); 918 times[1].tv_usec = archive_entry_mtime_nsec(entry) / 1000; 919 920 times[0].tv_sec = archive_entry_atime(entry); 921 times[0].tv_usec = archive_entry_atime_nsec(entry) / 1000; 922 923 #if defined(HAVE_FUTIMES) && !defined(__CYGWIN__) 924 if (fd >= 0 && futimes(fd, times) == 0) 925 return (fd); 926 #endif 927 /* 928 * Some platform cannot restore access times if the file descriptor 929 * is still opened. 930 */ 931 if (fd >= 0) { 932 close(fd); 933 fd = -1; 934 } 935 936 #ifdef HAVE_LUTIMES 937 if (lutimes(name, times) != 0) 938 #else 939 if ((AE_IFLNK != archive_entry_filetype(entry)) 940 && utimes(name, times) != 0) 941 #endif 942 lafe_warnc(errno, "Can't update time for %s", name); 943 #endif 944 return (fd); 945 } 946 947 948 static void 949 mode_in(struct cpio *cpio) 950 { 951 struct archive *a; 952 struct archive_entry *entry; 953 struct archive *ext; 954 const char *destpath; 955 int r; 956 957 ext = archive_write_disk_new(); 958 if (ext == NULL) 959 lafe_errc(1, 0, "Couldn't allocate restore object"); 960 r = archive_write_disk_set_options(ext, cpio->extract_flags); 961 if (r != ARCHIVE_OK) 962 lafe_errc(1, 0, "%s", archive_error_string(ext)); 963 a = archive_read_new(); 964 if (a == NULL) 965 lafe_errc(1, 0, "Couldn't allocate archive object"); 966 archive_read_support_filter_all(a); 967 archive_read_support_format_all(a); 968 if (cpio->option_pwb) 969 archive_read_set_options(a, "pwb"); 970 if (cpio->passphrase != NULL) 971 r = archive_read_add_passphrase(a, cpio->passphrase); 972 else 973 r = archive_read_set_passphrase_callback(a, cpio, 974 &passphrase_callback); 975 if (r != ARCHIVE_OK) 976 lafe_errc(1, 0, "%s", archive_error_string(a)); 977 978 if (archive_read_open_filename(a, cpio->filename, 979 cpio->bytes_per_block)) 980 lafe_errc(1, archive_errno(a), 981 "%s", archive_error_string(a)); 982 for (;;) { 983 r = archive_read_next_header(a, &entry); 984 if (r == ARCHIVE_EOF) 985 break; 986 if (r != ARCHIVE_OK) { 987 lafe_errc(1, archive_errno(a), 988 "%s", archive_error_string(a)); 989 } 990 if (archive_match_path_excluded(cpio->matching, entry)) 991 continue; 992 if (cpio->option_rename) { 993 destpath = cpio_rename(archive_entry_pathname(entry)); 994 archive_entry_set_pathname(entry, destpath); 995 } else 996 destpath = archive_entry_pathname(entry); 997 if (destpath == NULL) 998 continue; 999 if (cpio->verbose) 1000 fprintf(stderr, "%s\n", destpath); 1001 if (cpio->dot) 1002 fprintf(stderr, "."); 1003 if (cpio->uid_override >= 0) 1004 archive_entry_set_uid(entry, cpio->uid_override); 1005 if (cpio->uname_override != NULL) 1006 archive_entry_set_uname(entry, cpio->uname_override); 1007 if (cpio->gid_override >= 0) 1008 archive_entry_set_gid(entry, cpio->gid_override); 1009 if (cpio->gname_override != NULL) 1010 archive_entry_set_gname(entry, cpio->gname_override); 1011 r = archive_write_header(ext, entry); 1012 if (r != ARCHIVE_OK) { 1013 fprintf(stderr, "%s: %s\n", 1014 archive_entry_pathname(entry), 1015 archive_error_string(ext)); 1016 cpio->return_value = 1; 1017 } else if (!archive_entry_size_is_set(entry) 1018 || archive_entry_size(entry) > 0) { 1019 r = extract_data(a, ext); 1020 if (r != ARCHIVE_OK) 1021 cpio->return_value = 1; 1022 } 1023 } 1024 r = archive_read_close(a); 1025 if (cpio->dot) 1026 fprintf(stderr, "\n"); 1027 if (r != ARCHIVE_OK) 1028 lafe_errc(1, 0, "%s", archive_error_string(a)); 1029 r = archive_write_close(ext); 1030 if (r != ARCHIVE_OK) 1031 lafe_errc(1, 0, "%s", archive_error_string(ext)); 1032 if (!cpio->quiet) { 1033 int64_t blocks = (archive_filter_bytes(a, 0) + 511) 1034 / 512; 1035 fprintf(stderr, "%lu %s\n", (unsigned long)blocks, 1036 blocks == 1 ? "block" : "blocks"); 1037 } 1038 archive_read_free(a); 1039 archive_write_free(ext); 1040 exit(cpio->return_value); 1041 } 1042 1043 /* 1044 * Exits if there's a fatal error. Returns ARCHIVE_OK 1045 * if everything is kosher. 1046 */ 1047 static int 1048 extract_data(struct archive *ar, struct archive *aw) 1049 { 1050 int r; 1051 size_t size; 1052 const void *block; 1053 int64_t offset; 1054 1055 for (;;) { 1056 r = archive_read_data_block(ar, &block, &size, &offset); 1057 if (r == ARCHIVE_EOF) 1058 return (ARCHIVE_OK); 1059 if (r != ARCHIVE_OK) { 1060 lafe_warnc(archive_errno(ar), 1061 "%s", archive_error_string(ar)); 1062 exit(1); 1063 } 1064 r = (int)archive_write_data_block(aw, block, size, offset); 1065 if (r != ARCHIVE_OK) { 1066 lafe_warnc(archive_errno(aw), 1067 "%s", archive_error_string(aw)); 1068 return (r); 1069 } 1070 } 1071 } 1072 1073 static void 1074 mode_list(struct cpio *cpio) 1075 { 1076 struct archive *a; 1077 struct archive_entry *entry; 1078 int r; 1079 1080 a = archive_read_new(); 1081 if (a == NULL) 1082 lafe_errc(1, 0, "Couldn't allocate archive object"); 1083 archive_read_support_filter_all(a); 1084 archive_read_support_format_all(a); 1085 if (cpio->option_pwb) 1086 archive_read_set_options(a, "pwb"); 1087 if (cpio->passphrase != NULL) 1088 r = archive_read_add_passphrase(a, cpio->passphrase); 1089 else 1090 r = archive_read_set_passphrase_callback(a, cpio, 1091 &passphrase_callback); 1092 if (r != ARCHIVE_OK) 1093 lafe_errc(1, 0, "%s", archive_error_string(a)); 1094 1095 if (archive_read_open_filename(a, cpio->filename, 1096 cpio->bytes_per_block)) 1097 lafe_errc(1, archive_errno(a), 1098 "%s", archive_error_string(a)); 1099 for (;;) { 1100 r = archive_read_next_header(a, &entry); 1101 if (r == ARCHIVE_EOF) 1102 break; 1103 if (r != ARCHIVE_OK) { 1104 lafe_errc(1, archive_errno(a), 1105 "%s", archive_error_string(a)); 1106 } 1107 if (archive_match_path_excluded(cpio->matching, entry)) 1108 continue; 1109 if (cpio->verbose) 1110 list_item_verbose(cpio, entry); 1111 else 1112 fprintf(stdout, "%s\n", archive_entry_pathname(entry)); 1113 } 1114 r = archive_read_close(a); 1115 if (r != ARCHIVE_OK) 1116 lafe_errc(1, 0, "%s", archive_error_string(a)); 1117 if (!cpio->quiet) { 1118 int64_t blocks = (archive_filter_bytes(a, 0) + 511) 1119 / 512; 1120 fprintf(stderr, "%lu %s\n", (unsigned long)blocks, 1121 blocks == 1 ? "block" : "blocks"); 1122 } 1123 archive_read_free(a); 1124 exit(0); 1125 } 1126 1127 /* 1128 * Display information about the current file. 1129 * 1130 * The format here roughly duplicates the output of 'ls -l'. 1131 * This is based on SUSv2, where 'tar tv' is documented as 1132 * listing additional information in an "unspecified format," 1133 * and 'pax -l' is documented as using the same format as 'ls -l'. 1134 */ 1135 static void 1136 list_item_verbose(struct cpio *cpio, struct archive_entry *entry) 1137 { 1138 char size[32]; 1139 char date[32]; 1140 char uids[22], gids[22]; 1141 const char *uname, *gname; 1142 FILE *out = stdout; 1143 const char *fmt; 1144 time_t mtime; 1145 static time_t now; 1146 struct tm *ltime; 1147 #if defined(HAVE_LOCALTIME_R) || defined(HAVE_LOCALTIME_S) 1148 struct tm tmbuf; 1149 #endif 1150 1151 if (!now) 1152 time(&now); 1153 1154 if (cpio->option_numeric_uid_gid) { 1155 /* Format numeric uid/gid for display. */ 1156 strcpy(uids, cpio_i64toa(archive_entry_uid(entry))); 1157 uname = uids; 1158 strcpy(gids, cpio_i64toa(archive_entry_gid(entry))); 1159 gname = gids; 1160 } else { 1161 /* Use uname if it's present, else lookup name from uid. */ 1162 uname = archive_entry_uname(entry); 1163 if (uname == NULL) 1164 uname = lookup_uname(cpio, (uid_t)archive_entry_uid(entry)); 1165 /* Use gname if it's present, else lookup name from gid. */ 1166 gname = archive_entry_gname(entry); 1167 if (gname == NULL) 1168 gname = lookup_gname(cpio, (uid_t)archive_entry_gid(entry)); 1169 } 1170 1171 /* Print device number or file size. */ 1172 if (archive_entry_filetype(entry) == AE_IFCHR 1173 || archive_entry_filetype(entry) == AE_IFBLK) { 1174 snprintf(size, sizeof(size), "%lu,%lu", 1175 (unsigned long)archive_entry_rdevmajor(entry), 1176 (unsigned long)archive_entry_rdevminor(entry)); 1177 } else { 1178 strcpy(size, cpio_i64toa(archive_entry_size(entry))); 1179 } 1180 1181 /* Format the time using 'ls -l' conventions. */ 1182 mtime = archive_entry_mtime(entry); 1183 #if defined(_WIN32) && !defined(__CYGWIN__) 1184 /* Windows' strftime function does not support %e format. */ 1185 if (mtime - now > 365*86400/2 1186 || mtime - now < -365*86400/2) 1187 fmt = cpio->day_first ? "%d %b %Y" : "%b %d %Y"; 1188 else 1189 fmt = cpio->day_first ? "%d %b %H:%M" : "%b %d %H:%M"; 1190 #else 1191 if (mtime - now > 365*86400/2 1192 || mtime - now < -365*86400/2) 1193 fmt = cpio->day_first ? "%e %b %Y" : "%b %e %Y"; 1194 else 1195 fmt = cpio->day_first ? "%e %b %H:%M" : "%b %e %H:%M"; 1196 #endif 1197 #if defined(HAVE_LOCALTIME_S) 1198 ltime = localtime_s(&tmbuf, &mtime) ? NULL : &tmbuf; 1199 #elif defined(HAVE_LOCALTIME_R) 1200 ltime = localtime_r(&mtime, &tmbuf); 1201 #else 1202 ltime = localtime(&mtime); 1203 #endif 1204 if (ltime != NULL) 1205 strftime(date, sizeof(date), fmt, ltime); 1206 else 1207 strcpy(date, "invalid mtime"); 1208 1209 fprintf(out, "%s%3d %-8s %-8s %8s %12s %s", 1210 archive_entry_strmode(entry), 1211 archive_entry_nlink(entry), 1212 uname, gname, size, date, 1213 archive_entry_pathname(entry)); 1214 1215 /* Extra information for links. */ 1216 if (archive_entry_hardlink(entry)) /* Hard link */ 1217 fprintf(out, " link to %s", archive_entry_hardlink(entry)); 1218 else if (archive_entry_symlink(entry)) /* Symbolic link */ 1219 fprintf(out, " -> %s", archive_entry_symlink(entry)); 1220 fprintf(out, "\n"); 1221 } 1222 1223 static void 1224 mode_pass(struct cpio *cpio, const char *destdir) 1225 { 1226 struct lafe_line_reader *lr; 1227 const char *p; 1228 int r; 1229 1230 /* Ensure target dir has a trailing '/' to simplify path surgery. */ 1231 cpio->destdir_len = strlen(destdir); 1232 cpio->destdir = malloc(cpio->destdir_len + 8); 1233 memcpy(cpio->destdir, destdir, cpio->destdir_len); 1234 if (cpio->destdir_len == 0 || destdir[cpio->destdir_len - 1] != '/') 1235 cpio->destdir[cpio->destdir_len++] = '/'; 1236 cpio->destdir[cpio->destdir_len] = '\0'; 1237 1238 cpio->archive = archive_write_disk_new(); 1239 if (cpio->archive == NULL) 1240 lafe_errc(1, 0, "Failed to allocate archive object"); 1241 r = archive_write_disk_set_options(cpio->archive, cpio->extract_flags); 1242 if (r != ARCHIVE_OK) 1243 lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); 1244 cpio->linkresolver = archive_entry_linkresolver_new(); 1245 archive_write_disk_set_standard_lookup(cpio->archive); 1246 1247 cpio->archive_read_disk = archive_read_disk_new(); 1248 if (cpio->archive_read_disk == NULL) 1249 lafe_errc(1, 0, "Failed to allocate archive object"); 1250 if (cpio->option_follow_links) 1251 archive_read_disk_set_symlink_logical(cpio->archive_read_disk); 1252 else 1253 archive_read_disk_set_symlink_physical(cpio->archive_read_disk); 1254 archive_read_disk_set_standard_lookup(cpio->archive_read_disk); 1255 1256 lr = lafe_line_reader("-", cpio->option_null); 1257 while ((p = lafe_line_reader_next(lr)) != NULL) 1258 file_to_archive(cpio, p); 1259 lafe_line_reader_free(lr); 1260 1261 archive_entry_linkresolver_free(cpio->linkresolver); 1262 r = archive_write_close(cpio->archive); 1263 if (cpio->dot) 1264 fprintf(stderr, "\n"); 1265 if (r != ARCHIVE_OK) 1266 lafe_errc(1, 0, "%s", archive_error_string(cpio->archive)); 1267 1268 if (!cpio->quiet) { 1269 int64_t blocks = 1270 (archive_filter_bytes(cpio->archive, 0) + 511) 1271 / 512; 1272 fprintf(stderr, "%lu %s\n", (unsigned long)blocks, 1273 blocks == 1 ? "block" : "blocks"); 1274 } 1275 1276 archive_write_free(cpio->archive); 1277 free(cpio->pass_destpath); 1278 } 1279 1280 /* 1281 * Prompt for a new name for this entry. Returns a pointer to the 1282 * new name or NULL if the entry should not be copied. This 1283 * implements the semantics defined in POSIX.1-1996, which specifies 1284 * that an input of '.' means the name should be unchanged. GNU cpio 1285 * treats '.' as a literal new name. 1286 */ 1287 static const char * 1288 cpio_rename(const char *name) 1289 { 1290 static char buff[1024]; 1291 FILE *t; 1292 char *p, *ret; 1293 #if defined(_WIN32) && !defined(__CYGWIN__) 1294 FILE *to; 1295 1296 t = fopen("CONIN$", "r"); 1297 if (t == NULL) 1298 return (name); 1299 to = fopen("CONOUT$", "w"); 1300 if (to == NULL) { 1301 fclose(t); 1302 return (name); 1303 } 1304 fprintf(to, "%s (Enter/./(new name))? ", name); 1305 fclose(to); 1306 #else 1307 t = fopen("/dev/tty", "r+"); 1308 if (t == NULL) 1309 return (name); 1310 fprintf(t, "%s (Enter/./(new name))? ", name); 1311 fflush(t); 1312 #endif 1313 1314 p = fgets(buff, sizeof(buff), t); 1315 fclose(t); 1316 if (p == NULL) 1317 /* End-of-file is a blank line. */ 1318 return (NULL); 1319 1320 while (*p == ' ' || *p == '\t') 1321 ++p; 1322 if (*p == '\n' || *p == '\0') 1323 /* Empty line. */ 1324 return (NULL); 1325 if (*p == '.' && p[1] == '\n') 1326 /* Single period preserves original name. */ 1327 return (name); 1328 ret = p; 1329 /* Trim the final newline. */ 1330 while (*p != '\0' && *p != '\n') 1331 ++p; 1332 /* Overwrite the final \n with a null character. */ 1333 *p = '\0'; 1334 return (ret); 1335 } 1336 1337 static void 1338 free_cache(struct name_cache *cache) 1339 { 1340 size_t i; 1341 1342 if (cache != NULL) { 1343 for (i = 0; i < cache->size; i++) 1344 free(cache->cache[i].name); 1345 free(cache); 1346 } 1347 } 1348 1349 /* 1350 * Lookup uname/gname from uid/gid, return NULL if no match. 1351 */ 1352 static const char * 1353 lookup_name(struct cpio *cpio, struct name_cache **name_cache_variable, 1354 int (*lookup_fn)(struct cpio *, const char **, id_t), id_t id) 1355 { 1356 char asnum[16]; 1357 struct name_cache *cache; 1358 const char *name; 1359 int slot; 1360 1361 1362 if (*name_cache_variable == NULL) { 1363 *name_cache_variable = calloc(1, sizeof(struct name_cache)); 1364 if (*name_cache_variable == NULL) 1365 lafe_errc(1, ENOMEM, "No more memory"); 1366 (*name_cache_variable)->size = name_cache_size; 1367 } 1368 1369 cache = *name_cache_variable; 1370 cache->probes++; 1371 1372 slot = id % cache->size; 1373 if (cache->cache[slot].name != NULL) { 1374 if (cache->cache[slot].id == id) { 1375 cache->hits++; 1376 return (cache->cache[slot].name); 1377 } 1378 free(cache->cache[slot].name); 1379 cache->cache[slot].name = NULL; 1380 } 1381 1382 if (lookup_fn(cpio, &name, id)) { 1383 /* If lookup failed, format it as a number. */ 1384 snprintf(asnum, sizeof(asnum), "%u", (unsigned)id); 1385 name = asnum; 1386 } 1387 1388 cache->cache[slot].name = strdup(name); 1389 if (cache->cache[slot].name != NULL) { 1390 cache->cache[slot].id = id; 1391 return (cache->cache[slot].name); 1392 } 1393 1394 /* 1395 * Conveniently, NULL marks an empty slot, so 1396 * if the strdup() fails, we've just failed to 1397 * cache it. No recovery necessary. 1398 */ 1399 return (NULL); 1400 } 1401 1402 static const char * 1403 lookup_uname(struct cpio *cpio, uid_t uid) 1404 { 1405 return (lookup_name(cpio, &cpio->uname_cache, 1406 &lookup_uname_helper, (id_t)uid)); 1407 } 1408 1409 static int 1410 lookup_uname_helper(struct cpio *cpio, const char **name, id_t id) 1411 { 1412 struct passwd *pwent; 1413 1414 (void)cpio; /* UNUSED */ 1415 1416 errno = 0; 1417 pwent = getpwuid((uid_t)id); 1418 if (pwent == NULL) { 1419 if (errno && errno != ENOENT) 1420 lafe_warnc(errno, "getpwuid(%s) failed", 1421 cpio_i64toa((int64_t)id)); 1422 return 1; 1423 } 1424 1425 *name = pwent->pw_name; 1426 return 0; 1427 } 1428 1429 static const char * 1430 lookup_gname(struct cpio *cpio, gid_t gid) 1431 { 1432 return (lookup_name(cpio, &cpio->gname_cache, 1433 &lookup_gname_helper, (id_t)gid)); 1434 } 1435 1436 static int 1437 lookup_gname_helper(struct cpio *cpio, const char **name, id_t id) 1438 { 1439 struct group *grent; 1440 1441 (void)cpio; /* UNUSED */ 1442 1443 errno = 0; 1444 grent = getgrgid((gid_t)id); 1445 if (grent == NULL) { 1446 if (errno && errno != ENOENT) 1447 lafe_warnc(errno, "getgrgid(%s) failed", 1448 cpio_i64toa((int64_t)id)); 1449 return 1; 1450 } 1451 1452 *name = grent->gr_name; 1453 return 0; 1454 } 1455 1456 /* 1457 * It would be nice to just use printf() for formatting large numbers, 1458 * but the compatibility problems are a big headache. Hence the 1459 * following simple utility function. 1460 */ 1461 const char * 1462 cpio_i64toa(int64_t n0) 1463 { 1464 /* 2^64 =~ 1.8 * 10^19, so 20 decimal digits suffice. 1465 * We also need 1 byte for '-' and 1 for '\0'. 1466 */ 1467 static char buff[22]; 1468 int64_t n = n0 < 0 ? -n0 : n0; 1469 char *p = buff + sizeof(buff); 1470 1471 *--p = '\0'; 1472 do { 1473 *--p = '0' + (int)(n % 10); 1474 n /= 10; 1475 } while (n > 0); 1476 if (n0 < 0) 1477 *--p = '-'; 1478 return p; 1479 } 1480 1481 #define PPBUFF_SIZE 1024 1482 static const char * 1483 passphrase_callback(struct archive *a, void *_client_data) 1484 { 1485 struct cpio *cpio = (struct cpio *)_client_data; 1486 (void)a; /* UNUSED */ 1487 1488 if (cpio->ppbuff == NULL) { 1489 cpio->ppbuff = malloc(PPBUFF_SIZE); 1490 if (cpio->ppbuff == NULL) 1491 lafe_errc(1, errno, "Out of memory"); 1492 } 1493 return lafe_readpassphrase("Enter passphrase:", 1494 cpio->ppbuff, PPBUFF_SIZE); 1495 } 1496 1497 static void 1498 passphrase_free(char *ppbuff) 1499 { 1500 if (ppbuff != NULL) { 1501 memset(ppbuff, 0, PPBUFF_SIZE); 1502 free(ppbuff); 1503 } 1504 } 1505