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