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