1 /* ar.c - Archive modify and extract. 2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 3 2001, 2002, 2003, 2004, 2005 4 Free Software Foundation, Inc. 5 6 This file is part of GNU Binutils. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ 21 22 /* 23 Bugs: should use getopt the way tar does (complete w/optional -) and 24 should have long options too. GNU ar used to check file against filesystem 25 in quick_update and replace operations (would check mtime). Doesn't warn 26 when name truncated. No way to specify pos_end. Error messages should be 27 more consistent. */ 28 29 #include "bfd.h" 30 #include "libiberty.h" 31 #include "progress.h" 32 #include "bucomm.h" 33 #include "aout/ar.h" 34 #include "libbfd.h" 35 #include "arsup.h" 36 #include "filenames.h" 37 #include "binemul.h" 38 #include <sys/stat.h> 39 40 #ifdef __GO32___ 41 #define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */ 42 #else 43 #define EXT_NAME_LEN 6 /* ditto for *NIX */ 44 #endif 45 46 /* We need to open files in binary modes on system where that makes a 47 difference. */ 48 #ifndef O_BINARY 49 #define O_BINARY 0 50 #endif 51 52 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */ 53 54 struct ar_hdr * 55 bfd_special_undocumented_glue (bfd * abfd, const char *filename); 56 57 /* Static declarations */ 58 59 static void mri_emul (void); 60 static const char *normalize (const char *, bfd *); 61 static void remove_output (void); 62 static void map_over_members (bfd *, void (*)(bfd *), char **, int); 63 static void print_contents (bfd * member); 64 static void delete_members (bfd *, char **files_to_delete); 65 66 static void move_members (bfd *, char **files_to_move); 67 static void replace_members 68 (bfd *, char **files_to_replace, bfd_boolean quick); 69 static void print_descr (bfd * abfd); 70 static void write_archive (bfd *); 71 static void ranlib_only (const char *archname); 72 static void ranlib_touch (const char *archname); 73 static void usage (int); 74 75 /** Globals and flags */ 76 77 static int mri_mode; 78 79 /* This flag distinguishes between ar and ranlib: 80 1 means this is 'ranlib'; 0 means this is 'ar'. 81 -1 means if we should use argv[0] to decide. */ 82 extern int is_ranlib; 83 84 /* Nonzero means don't warn about creating the archive file if necessary. */ 85 int silent_create = 0; 86 87 /* Nonzero means describe each action performed. */ 88 int verbose = 0; 89 90 /* Nonzero means preserve dates of members when extracting them. */ 91 int preserve_dates = 0; 92 93 /* Nonzero means don't replace existing members whose dates are more recent 94 than the corresponding files. */ 95 int newer_only = 0; 96 97 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF 98 member). -1 means we've been explicitly asked to not write a symbol table; 99 +1 means we've been explicitly asked to write it; 100 0 is the default. 101 Traditionally, the default in BSD has been to not write the table. 102 However, for POSIX.2 compliance the default is now to write a symbol table 103 if any of the members are object files. */ 104 int write_armap = 0; 105 106 /* Nonzero means it's the name of an existing member; position new or moved 107 files with respect to this one. */ 108 char *posname = NULL; 109 110 /* Sez how to use `posname': pos_before means position before that member. 111 pos_after means position after that member. pos_end means always at end. 112 pos_default means default appropriately. For the latter two, `posname' 113 should also be zero. */ 114 enum pos 115 { 116 pos_default, pos_before, pos_after, pos_end 117 } postype = pos_default; 118 119 static bfd ** 120 get_pos_bfd (bfd **, enum pos, const char *); 121 122 /* For extract/delete only. If COUNTED_NAME_MODE is TRUE, we only 123 extract the COUNTED_NAME_COUNTER instance of that name. */ 124 static bfd_boolean counted_name_mode = 0; 125 static int counted_name_counter = 0; 126 127 /* Whether to truncate names of files stored in the archive. */ 128 static bfd_boolean ar_truncate = FALSE; 129 130 /* Whether to use a full file name match when searching an archive. 131 This is convenient for archives created by the Microsoft lib 132 program. */ 133 static bfd_boolean full_pathname = FALSE; 134 135 /* Whether archive contents should be deterministic with uid, gid, 136 and mtime set to zero and permissions set to 644. This breaks 137 later use of the 'u' option as well as make's lib(member) feature. 138 Note that the symbol index may have a non-zero timestamp to meet 139 archive format requirements. */ 140 static bfd_boolean deterministic = FALSE; 141 142 int interactive = 0; 143 144 static void 145 mri_emul (void) 146 { 147 interactive = isatty (fileno (stdin)); 148 yyparse (); 149 } 150 151 /* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero, 152 COUNT is the length of the FILES chain; FUNCTION is called on each entry 153 whose name matches one in FILES. */ 154 155 static void 156 map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count) 157 { 158 bfd *head; 159 int match_count; 160 161 if (count == 0) 162 { 163 for (head = arch->next; head; head = head->next) 164 { 165 PROGRESS (1); 166 function (head); 167 } 168 return; 169 } 170 171 /* This may appear to be a baroque way of accomplishing what we want. 172 However we have to iterate over the filenames in order to notice where 173 a filename is requested but does not exist in the archive. Ditto 174 mapping over each file each time -- we want to hack multiple 175 references. */ 176 177 for (; count > 0; files++, count--) 178 { 179 bfd_boolean found = FALSE; 180 181 match_count = 0; 182 for (head = arch->next; head; head = head->next) 183 { 184 PROGRESS (1); 185 if (head->filename == NULL) 186 { 187 /* Some archive formats don't get the filenames filled in 188 until the elements are opened. */ 189 struct stat buf; 190 bfd_stat_arch_elt (head, &buf); 191 } 192 if ((head->filename != NULL) && 193 (!FILENAME_CMP (normalize (*files, arch), head->filename))) 194 { 195 ++match_count; 196 if (counted_name_mode 197 && match_count != counted_name_counter) 198 { 199 /* Counting, and didn't match on count; go on to the 200 next one. */ 201 continue; 202 } 203 204 found = TRUE; 205 function (head); 206 } 207 } 208 if (!found) 209 /* xgettext:c-format */ 210 fprintf (stderr, _("no entry %s in archive\n"), *files); 211 } 212 } 213 214 bfd_boolean operation_alters_arch = FALSE; 215 216 static void 217 usage (int help) 218 { 219 FILE *s; 220 221 s = help ? stdout : stderr; 222 223 if (! is_ranlib) 224 { 225 /* xgettext:c-format */ 226 fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"), 227 program_name); 228 /* xgettext:c-format */ 229 fprintf (s, _(" %s -M [<mri-script]\n"), program_name); 230 fprintf (s, _(" commands:\n")); 231 fprintf (s, _(" d - delete file(s) from the archive\n")); 232 fprintf (s, _(" m[ab] - move file(s) in the archive\n")); 233 fprintf (s, _(" p - print file(s) found in the archive\n")); 234 fprintf (s, _(" q[f] - quick append file(s) to the archive\n")); 235 fprintf (s, _(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n")); 236 fprintf (s, _(" t - display contents of archive\n")); 237 fprintf (s, _(" x[o] - extract file(s) from the archive\n")); 238 fprintf (s, _(" command specific modifiers:\n")); 239 fprintf (s, _(" [a] - put file(s) after [member-name]\n")); 240 fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n")); 241 fprintf (s, _(" [N] - use instance [count] of name\n")); 242 fprintf (s, _(" [f] - truncate inserted file names\n")); 243 fprintf (s, _(" [P] - use full path names when matching\n")); 244 fprintf (s, _(" [o] - preserve original dates\n")); 245 fprintf (s, _(" [u] - only replace files that are newer than current archive contents\n")); 246 fprintf (s, _(" [D] - set deterministic attributes in archive\n")); 247 fprintf (s, _(" [U] - set accurate attributes in archive\n")); 248 fprintf (s, _(" generic modifiers:\n")); 249 fprintf (s, _(" [c] - do not warn if the library had to be created\n")); 250 fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n")); 251 fprintf (s, _(" [S] - do not build a symbol table\n")); 252 fprintf (s, _(" [v] - be verbose\n")); 253 fprintf (s, _(" [V] - display the version number\n")); 254 fprintf (s, _(" @<file> - read options from <file>\n")); 255 256 ar_emul_usage (s); 257 } 258 else 259 { 260 /* xgettext:c-format */ 261 fprintf (s, _("Usage: %s [options] archive\n"), program_name); 262 fprintf (s, _(" Generate an index to speed access to archives\n")); 263 fprintf (s, _(" The options are:\n\ 264 @<file> Read options from <file>\n\ 265 -h --help Print this help message\n\ 266 -V --version Print version information\n")); 267 } 268 269 list_supported_targets (program_name, stderr); 270 271 if (help) 272 fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO); 273 274 xexit (help ? 0 : 1); 275 } 276 277 /* Normalize a file name specified on the command line into a file 278 name which we will use in an archive. */ 279 280 static const char * 281 normalize (const char *file, bfd *abfd) 282 { 283 const char *filename; 284 285 if (full_pathname) 286 return file; 287 288 filename = strrchr (file, '/'); 289 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 290 { 291 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ 292 char *bslash = strrchr (file, '\\'); 293 if (filename == NULL || (bslash != NULL && bslash > filename)) 294 filename = bslash; 295 if (filename == NULL && file[0] != '\0' && file[1] == ':') 296 filename = file + 1; 297 } 298 #endif 299 if (filename != (char *) NULL) 300 filename++; 301 else 302 filename = file; 303 304 if (ar_truncate 305 && abfd != NULL 306 && strlen (filename) > abfd->xvec->ar_max_namelen) 307 { 308 char *s; 309 310 /* Space leak. */ 311 s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1); 312 memcpy (s, filename, abfd->xvec->ar_max_namelen); 313 s[abfd->xvec->ar_max_namelen] = '\0'; 314 filename = s; 315 } 316 317 return filename; 318 } 319 320 /* Remove any output file. This is only called via xatexit. */ 321 322 static const char *output_filename = NULL; 323 static FILE *output_file = NULL; 324 static bfd *output_bfd = NULL; 325 326 static void 327 remove_output (void) 328 { 329 if (output_filename != NULL) 330 { 331 if (output_bfd != NULL) 332 bfd_cache_close (output_bfd); 333 if (output_file != NULL) 334 fclose (output_file); 335 unlink_if_ordinary (output_filename); 336 } 337 } 338 339 /* The option parsing should be in its own function. 340 It will be when I have getopt working. */ 341 342 int main (int, char **); 343 344 int 345 main (int argc, char **argv) 346 { 347 char *arg_ptr; 348 char c; 349 enum 350 { 351 none = 0, delete, replace, print_table, 352 print_files, extract, move, quick_append 353 } operation = none; 354 int arg_index; 355 char **files; 356 int file_count; 357 char *inarch_filename; 358 int show_version; 359 int i; 360 int do_posix = 0; 361 362 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 363 setlocale (LC_MESSAGES, ""); 364 #endif 365 #if defined (HAVE_SETLOCALE) 366 setlocale (LC_CTYPE, ""); 367 #endif 368 bindtextdomain (PACKAGE, LOCALEDIR); 369 textdomain (PACKAGE); 370 371 program_name = argv[0]; 372 xmalloc_set_program_name (program_name); 373 374 if (pledge ("stdio rpath wpath cpath fattr", NULL) == -1) 375 fatal (_("pledge: %s"), strerror (errno)); 376 377 expandargv (&argc, &argv); 378 379 if (is_ranlib < 0) 380 { 381 char *temp; 382 383 temp = strrchr (program_name, '/'); 384 #ifdef HAVE_DOS_BASED_FILE_SYSTEM 385 { 386 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */ 387 char *bslash = strrchr (program_name, '\\'); 388 if (temp == NULL || (bslash != NULL && bslash > temp)) 389 temp = bslash; 390 if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':') 391 temp = program_name + 1; 392 } 393 #endif 394 if (temp == NULL) 395 temp = program_name; 396 else 397 ++temp; 398 if (strlen (temp) >= 6 399 && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0) 400 is_ranlib = 1; 401 else 402 is_ranlib = 0; 403 } 404 405 if (argc > 1 && argv[1][0] == '-') 406 { 407 if (strcmp (argv[1], "--help") == 0) 408 usage (1); 409 else if (strcmp (argv[1], "--version") == 0) 410 { 411 if (is_ranlib) 412 print_version ("ranlib"); 413 else 414 print_version ("ar"); 415 } 416 } 417 418 START_PROGRESS (program_name, 0); 419 420 bfd_init (); 421 set_default_bfd_target (); 422 423 show_version = 0; 424 425 xatexit (remove_output); 426 427 for (i = 1; i < argc; i++) 428 if (! ar_emul_parse_arg (argv[i])) 429 break; 430 argv += (i - 1); 431 argc -= (i - 1); 432 433 if (is_ranlib) 434 { 435 bfd_boolean touch = FALSE; 436 437 if (argc < 2 438 || strcmp (argv[1], "--help") == 0 439 || strcmp (argv[1], "-h") == 0 440 || strcmp (argv[1], "-H") == 0) 441 usage (0); 442 if (strcmp (argv[1], "-V") == 0 443 || strcmp (argv[1], "-v") == 0 444 || strncmp (argv[1], "--v", 3) == 0) 445 print_version ("ranlib"); 446 arg_index = 1; 447 if (strcmp (argv[1], "-t") == 0) 448 { 449 ++arg_index; 450 touch = TRUE; 451 } 452 while (arg_index < argc) 453 { 454 if (! touch) 455 ranlib_only (argv[arg_index]); 456 else 457 ranlib_touch (argv[arg_index]); 458 ++arg_index; 459 } 460 xexit (0); 461 } 462 463 if (argc == 2 && strcmp (argv[1], "-M") == 0) 464 { 465 mri_emul (); 466 xexit (0); 467 } 468 469 if (argc < 2) 470 usage (0); 471 472 arg_index = 1; 473 arg_ptr = argv[arg_index]; 474 475 if (*arg_ptr == '-') 476 { 477 /* When the first option starts with '-' we support POSIX-compatible 478 option parsing. */ 479 do_posix = 1; 480 ++arg_ptr; /* compatibility */ 481 } 482 483 do 484 { 485 while ((c = *arg_ptr++) != '\0') 486 { 487 switch (c) 488 { 489 case 'd': 490 case 'm': 491 case 'p': 492 case 'q': 493 case 'r': 494 case 't': 495 case 'x': 496 if (operation != none) 497 fatal (_("two different operation options specified")); 498 switch (c) 499 { 500 case 'd': 501 operation = delete; 502 operation_alters_arch = TRUE; 503 break; 504 case 'm': 505 operation = move; 506 operation_alters_arch = TRUE; 507 break; 508 case 'p': 509 operation = print_files; 510 break; 511 case 'q': 512 operation = quick_append; 513 operation_alters_arch = TRUE; 514 break; 515 case 'r': 516 operation = replace; 517 operation_alters_arch = TRUE; 518 break; 519 case 't': 520 operation = print_table; 521 break; 522 case 'x': 523 operation = extract; 524 break; 525 } 526 case 'l': 527 break; 528 case 'c': 529 silent_create = 1; 530 break; 531 case 'o': 532 preserve_dates = 1; 533 break; 534 case 'V': 535 show_version = TRUE; 536 break; 537 case 's': 538 write_armap = 1; 539 break; 540 case 'S': 541 write_armap = -1; 542 break; 543 case 'u': 544 newer_only = 1; 545 break; 546 case 'v': 547 verbose = 1; 548 break; 549 case 'a': 550 postype = pos_after; 551 break; 552 case 'b': 553 postype = pos_before; 554 break; 555 case 'i': 556 postype = pos_before; 557 break; 558 case 'M': 559 mri_mode = 1; 560 break; 561 case 'N': 562 counted_name_mode = TRUE; 563 break; 564 case 'f': 565 ar_truncate = TRUE; 566 break; 567 case 'P': 568 full_pathname = TRUE; 569 break; 570 case 'D': 571 deterministic = TRUE; 572 break; 573 case 'U': 574 deterministic = FALSE; 575 break; 576 default: 577 /* xgettext:c-format */ 578 non_fatal (_("illegal option -- %c"), c); 579 usage (0); 580 } 581 } 582 583 /* With POSIX-compatible option parsing continue with the next 584 argument if it starts with '-'. */ 585 if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-') 586 arg_ptr = argv[++arg_index] + 1; 587 else 588 do_posix = 0; 589 } 590 while (do_posix); 591 592 if (show_version) 593 print_version ("ar"); 594 595 ++arg_index; 596 if (arg_index >= argc) 597 usage (0); 598 599 if (mri_mode) 600 { 601 mri_emul (); 602 } 603 else 604 { 605 bfd *arch; 606 607 /* We don't use do_quick_append any more. Too many systems 608 expect ar to always rebuild the symbol table even when q is 609 used. */ 610 611 /* We can't write an armap when using ar q, so just do ar r 612 instead. */ 613 if (operation == quick_append && write_armap) 614 operation = replace; 615 616 if ((operation == none || operation == print_table) 617 && write_armap == 1) 618 { 619 ranlib_only (argv[arg_index]); 620 xexit (0); 621 } 622 623 if (operation == none) 624 fatal (_("no operation specified")); 625 626 if (newer_only && operation != replace) 627 fatal (_("`u' is only meaningful with the `r' option.")); 628 629 if (postype != pos_default) 630 posname = argv[arg_index++]; 631 632 if (counted_name_mode) 633 { 634 if (operation != extract && operation != delete) 635 fatal (_("`N' is only meaningful with the `x' and `d' options.")); 636 counted_name_counter = atoi (argv[arg_index++]); 637 if (counted_name_counter <= 0) 638 fatal (_("Value for `N' must be positive.")); 639 } 640 641 inarch_filename = argv[arg_index++]; 642 643 files = arg_index < argc ? argv + arg_index : NULL; 644 file_count = argc - arg_index; 645 646 arch = open_inarch (inarch_filename, 647 files == NULL ? (char *) NULL : files[0]); 648 649 switch (operation) 650 { 651 case print_table: 652 map_over_members (arch, print_descr, files, file_count); 653 break; 654 655 case print_files: 656 map_over_members (arch, print_contents, files, file_count); 657 break; 658 659 case extract: 660 map_over_members (arch, extract_file, files, file_count); 661 break; 662 663 case delete: 664 if (files != NULL) 665 delete_members (arch, files); 666 else 667 output_filename = NULL; 668 break; 669 670 case move: 671 if (files != NULL) 672 move_members (arch, files); 673 else 674 output_filename = NULL; 675 break; 676 677 case replace: 678 case quick_append: 679 if (files != NULL || write_armap > 0) 680 replace_members (arch, files, operation == quick_append); 681 else 682 output_filename = NULL; 683 break; 684 685 /* Shouldn't happen! */ 686 default: 687 /* xgettext:c-format */ 688 fatal (_("internal error -- this option not implemented")); 689 } 690 } 691 692 END_PROGRESS (program_name); 693 694 xexit (0); 695 return 0; 696 } 697 698 bfd * 699 open_inarch (const char *archive_filename, const char *file) 700 { 701 const char *target; 702 bfd **last_one; 703 bfd *next_one; 704 struct stat sbuf; 705 bfd *arch; 706 char **matching; 707 708 bfd_set_error (bfd_error_no_error); 709 710 target = NULL; 711 712 if (stat (archive_filename, &sbuf) != 0) 713 { 714 #if !defined(__GO32__) || defined(__DJGPP__) 715 716 /* FIXME: I don't understand why this fragment was ifndef'ed 717 away for __GO32__; perhaps it was in the days of DJGPP v1.x. 718 stat() works just fine in v2.x, so I think this should be 719 removed. For now, I enable it for DJGPP v2. -- EZ. */ 720 721 /* KLUDGE ALERT! Temporary fix until I figger why 722 stat() is wrong ... think it's buried in GO32's IDT - Jax */ 723 if (errno != ENOENT) 724 bfd_fatal (archive_filename); 725 #endif 726 727 if (!operation_alters_arch) 728 { 729 fprintf (stderr, "%s: ", program_name); 730 perror (archive_filename); 731 maybequit (); 732 return NULL; 733 } 734 735 /* Try to figure out the target to use for the archive from the 736 first object on the list. */ 737 if (file != NULL) 738 { 739 bfd *obj; 740 741 obj = bfd_openr (file, NULL); 742 if (obj != NULL) 743 { 744 if (bfd_check_format (obj, bfd_object)) 745 target = bfd_get_target (obj); 746 (void) bfd_close (obj); 747 } 748 } 749 750 /* Create an empty archive. */ 751 arch = bfd_openw (archive_filename, target); 752 if (arch == NULL 753 || ! bfd_set_format (arch, bfd_archive) 754 || ! bfd_close (arch)) 755 bfd_fatal (archive_filename); 756 else if (!silent_create) 757 non_fatal (_("creating %s"), archive_filename); 758 759 /* If we die creating a new archive, don't leave it around. */ 760 output_filename = archive_filename; 761 } 762 763 arch = bfd_openr (archive_filename, target); 764 if (arch == NULL) 765 { 766 bloser: 767 bfd_fatal (archive_filename); 768 } 769 770 if (! bfd_check_format_matches (arch, bfd_archive, &matching)) 771 { 772 bfd_nonfatal (archive_filename); 773 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 774 { 775 list_matching_formats (matching); 776 free (matching); 777 } 778 xexit (1); 779 } 780 781 last_one = &(arch->next); 782 /* Read all the contents right away, regardless. */ 783 for (next_one = bfd_openr_next_archived_file (arch, NULL); 784 next_one; 785 next_one = bfd_openr_next_archived_file (arch, next_one)) 786 { 787 PROGRESS (1); 788 *last_one = next_one; 789 last_one = &next_one->next; 790 } 791 *last_one = (bfd *) NULL; 792 if (bfd_get_error () != bfd_error_no_more_archived_files) 793 goto bloser; 794 return arch; 795 } 796 797 static void 798 print_contents (bfd *abfd) 799 { 800 int ncopied = 0; 801 char *cbuf = xmalloc (BUFSIZE); 802 struct stat buf; 803 long size; 804 if (bfd_stat_arch_elt (abfd, &buf) != 0) 805 /* xgettext:c-format */ 806 fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); 807 808 if (verbose) 809 /* xgettext:c-format */ 810 printf (_("\n<%s>\n\n"), bfd_get_filename (abfd)); 811 812 bfd_seek (abfd, (file_ptr) 0, SEEK_SET); 813 814 size = buf.st_size; 815 while (ncopied < size) 816 { 817 818 int nread; 819 int tocopy = size - ncopied; 820 if (tocopy > BUFSIZE) 821 tocopy = BUFSIZE; 822 823 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd); 824 if (nread != tocopy) 825 /* xgettext:c-format */ 826 fatal (_("%s is not a valid archive"), 827 bfd_get_filename (bfd_my_archive (abfd))); 828 fwrite (cbuf, 1, nread, stdout); 829 ncopied += tocopy; 830 } 831 free (cbuf); 832 } 833 834 /* Extract a member of the archive into its own file. 835 836 We defer opening the new file until after we have read a BUFSIZ chunk of the 837 old one, since we know we have just read the archive header for the old 838 one. Since most members are shorter than BUFSIZ, this means we will read 839 the old header, read the old data, write a new inode for the new file, and 840 write the new data, and be done. This 'optimization' is what comes from 841 sitting next to a bare disk and hearing it every time it seeks. -- Gnu 842 Gilmore */ 843 844 void 845 extract_file (bfd *abfd) 846 { 847 FILE *ostream; 848 char *cbuf = xmalloc (BUFSIZE); 849 int nread, tocopy; 850 long ncopied = 0; 851 long size; 852 struct stat buf; 853 854 if (bfd_stat_arch_elt (abfd, &buf) != 0) 855 /* xgettext:c-format */ 856 fatal (_("internal stat error on %s"), bfd_get_filename (abfd)); 857 size = buf.st_size; 858 859 if (size < 0) 860 /* xgettext:c-format */ 861 fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd)); 862 863 if (verbose) 864 printf ("x - %s\n", bfd_get_filename (abfd)); 865 866 bfd_seek (abfd, (file_ptr) 0, SEEK_SET); 867 868 ostream = NULL; 869 if (size == 0) 870 { 871 /* Seems like an abstraction violation, eh? Well it's OK! */ 872 output_filename = bfd_get_filename (abfd); 873 874 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); 875 if (ostream == NULL) 876 { 877 perror (bfd_get_filename (abfd)); 878 xexit (1); 879 } 880 881 output_file = ostream; 882 } 883 else 884 while (ncopied < size) 885 { 886 tocopy = size - ncopied; 887 if (tocopy > BUFSIZE) 888 tocopy = BUFSIZE; 889 890 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd); 891 if (nread != tocopy) 892 /* xgettext:c-format */ 893 fatal (_("%s is not a valid archive"), 894 bfd_get_filename (bfd_my_archive (abfd))); 895 896 /* See comment above; this saves disk arm motion */ 897 if (ostream == NULL) 898 { 899 /* Seems like an abstraction violation, eh? Well it's OK! */ 900 output_filename = bfd_get_filename (abfd); 901 902 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); 903 if (ostream == NULL) 904 { 905 perror (bfd_get_filename (abfd)); 906 xexit (1); 907 } 908 909 output_file = ostream; 910 } 911 fwrite (cbuf, 1, nread, ostream); 912 ncopied += tocopy; 913 } 914 915 if (ostream != NULL) 916 fclose (ostream); 917 918 output_file = NULL; 919 output_filename = NULL; 920 921 chmod (bfd_get_filename (abfd), buf.st_mode & 0777); 922 923 if (preserve_dates) 924 { 925 /* Set access time to modification time. Only st_mtime is 926 initialized by bfd_stat_arch_elt. */ 927 buf.st_atime = buf.st_mtime; 928 set_times (bfd_get_filename (abfd), &buf); 929 } 930 931 free (cbuf); 932 } 933 934 static void 935 write_archive (bfd *iarch) 936 { 937 bfd *obfd; 938 char *old_name, *new_name; 939 bfd *contents_head = iarch->next; 940 941 old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1); 942 strcpy (old_name, bfd_get_filename (iarch)); 943 new_name = make_tempname (old_name, 0); 944 945 output_filename = new_name; 946 947 obfd = bfd_openw (new_name, bfd_get_target (iarch)); 948 949 if (obfd == NULL) 950 bfd_fatal (old_name); 951 952 output_bfd = obfd; 953 954 bfd_set_format (obfd, bfd_archive); 955 956 /* Request writing the archive symbol table unless we've 957 been explicitly requested not to. */ 958 obfd->has_armap = write_armap >= 0; 959 960 if (ar_truncate) 961 { 962 /* This should really use bfd_set_file_flags, but that rejects 963 archives. */ 964 obfd->flags |= BFD_TRADITIONAL_FORMAT; 965 } 966 967 if (deterministic) 968 obfd->flags |= BFD_DETERMINISTIC; 969 970 if (!bfd_set_archive_head (obfd, contents_head)) 971 bfd_fatal (old_name); 972 973 if (!bfd_close (obfd)) 974 bfd_fatal (old_name); 975 976 output_bfd = NULL; 977 output_filename = NULL; 978 979 /* We don't care if this fails; we might be creating the archive. */ 980 bfd_close (iarch); 981 982 if (smart_rename (new_name, old_name, 0) != 0) 983 xexit (1); 984 } 985 986 /* Return a pointer to the pointer to the entry which should be rplacd'd 987 into when altering. DEFAULT_POS should be how to interpret pos_default, 988 and should be a pos value. */ 989 990 static bfd ** 991 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname) 992 { 993 bfd **after_bfd = contents; 994 enum pos realpos; 995 const char *realposname; 996 997 if (postype == pos_default) 998 { 999 realpos = default_pos; 1000 realposname = default_posname; 1001 } 1002 else 1003 { 1004 realpos = postype; 1005 realposname = posname; 1006 } 1007 1008 if (realpos == pos_end) 1009 { 1010 while (*after_bfd) 1011 after_bfd = &((*after_bfd)->next); 1012 } 1013 else 1014 { 1015 for (; *after_bfd; after_bfd = &(*after_bfd)->next) 1016 if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0) 1017 { 1018 if (realpos == pos_after) 1019 after_bfd = &(*after_bfd)->next; 1020 break; 1021 } 1022 } 1023 return after_bfd; 1024 } 1025 1026 static void 1027 delete_members (bfd *arch, char **files_to_delete) 1028 { 1029 bfd **current_ptr_ptr; 1030 bfd_boolean found; 1031 bfd_boolean something_changed = FALSE; 1032 int match_count; 1033 1034 for (; *files_to_delete != NULL; ++files_to_delete) 1035 { 1036 /* In a.out systems, the armap is optional. It's also called 1037 __.SYMDEF. So if the user asked to delete it, we should remember 1038 that fact. This isn't quite right for COFF systems (where 1039 __.SYMDEF might be regular member), but it's very unlikely 1040 to be a problem. FIXME */ 1041 1042 if (!strcmp (*files_to_delete, "__.SYMDEF")) 1043 { 1044 arch->has_armap = FALSE; 1045 write_armap = -1; 1046 continue; 1047 } 1048 1049 found = FALSE; 1050 match_count = 0; 1051 current_ptr_ptr = &(arch->next); 1052 while (*current_ptr_ptr) 1053 { 1054 if (FILENAME_CMP (normalize (*files_to_delete, arch), 1055 (*current_ptr_ptr)->filename) == 0) 1056 { 1057 ++match_count; 1058 if (counted_name_mode 1059 && match_count != counted_name_counter) 1060 { 1061 /* Counting, and didn't match on count; go on to the 1062 next one. */ 1063 } 1064 else 1065 { 1066 found = TRUE; 1067 something_changed = TRUE; 1068 if (verbose) 1069 printf ("d - %s\n", 1070 *files_to_delete); 1071 *current_ptr_ptr = ((*current_ptr_ptr)->next); 1072 goto next_file; 1073 } 1074 } 1075 1076 current_ptr_ptr = &((*current_ptr_ptr)->next); 1077 } 1078 1079 if (verbose && !found) 1080 { 1081 /* xgettext:c-format */ 1082 printf (_("No member named `%s'\n"), *files_to_delete); 1083 } 1084 next_file: 1085 ; 1086 } 1087 1088 if (something_changed) 1089 write_archive (arch); 1090 else 1091 output_filename = NULL; 1092 } 1093 1094 1095 /* Reposition existing members within an archive */ 1096 1097 static void 1098 move_members (bfd *arch, char **files_to_move) 1099 { 1100 bfd **after_bfd; /* New entries go after this one */ 1101 bfd **current_ptr_ptr; /* cdr pointer into contents */ 1102 1103 for (; *files_to_move; ++files_to_move) 1104 { 1105 current_ptr_ptr = &(arch->next); 1106 while (*current_ptr_ptr) 1107 { 1108 bfd *current_ptr = *current_ptr_ptr; 1109 if (FILENAME_CMP (normalize (*files_to_move, arch), 1110 current_ptr->filename) == 0) 1111 { 1112 /* Move this file to the end of the list - first cut from 1113 where it is. */ 1114 bfd *link; 1115 *current_ptr_ptr = current_ptr->next; 1116 1117 /* Now glue to end */ 1118 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL); 1119 link = *after_bfd; 1120 *after_bfd = current_ptr; 1121 current_ptr->next = link; 1122 1123 if (verbose) 1124 printf ("m - %s\n", *files_to_move); 1125 1126 goto next_file; 1127 } 1128 1129 current_ptr_ptr = &((*current_ptr_ptr)->next); 1130 } 1131 /* xgettext:c-format */ 1132 fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename); 1133 1134 next_file:; 1135 } 1136 1137 write_archive (arch); 1138 } 1139 1140 /* Ought to default to replacing in place, but this is existing practice! */ 1141 1142 static void 1143 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick) 1144 { 1145 bfd_boolean changed = FALSE; 1146 bfd **after_bfd; /* New entries go after this one. */ 1147 bfd *current; 1148 bfd **current_ptr; 1149 1150 while (files_to_move && *files_to_move) 1151 { 1152 if (! quick) 1153 { 1154 current_ptr = &arch->next; 1155 while (*current_ptr) 1156 { 1157 current = *current_ptr; 1158 1159 /* For compatibility with existing ar programs, we 1160 permit the same file to be added multiple times. */ 1161 if (FILENAME_CMP (normalize (*files_to_move, arch), 1162 normalize (current->filename, arch)) == 0 1163 && current->arelt_data != NULL) 1164 { 1165 if (newer_only) 1166 { 1167 struct stat fsbuf, asbuf; 1168 1169 if (stat (*files_to_move, &fsbuf) != 0) 1170 { 1171 if (errno != ENOENT) 1172 bfd_fatal (*files_to_move); 1173 goto next_file; 1174 } 1175 if (bfd_stat_arch_elt (current, &asbuf) != 0) 1176 /* xgettext:c-format */ 1177 fatal (_("internal stat error on %s"), 1178 current->filename); 1179 1180 if (fsbuf.st_mtime <= asbuf.st_mtime) 1181 goto next_file; 1182 } 1183 1184 after_bfd = get_pos_bfd (&arch->next, pos_after, 1185 current->filename); 1186 if (ar_emul_replace (after_bfd, *files_to_move, 1187 verbose)) 1188 { 1189 /* Snip out this entry from the chain. */ 1190 *current_ptr = (*current_ptr)->next; 1191 changed = TRUE; 1192 } 1193 1194 goto next_file; 1195 } 1196 current_ptr = &(current->next); 1197 } 1198 } 1199 1200 /* Add to the end of the archive. */ 1201 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL); 1202 1203 if (ar_emul_append (after_bfd, *files_to_move, verbose)) 1204 changed = TRUE; 1205 1206 next_file:; 1207 1208 files_to_move++; 1209 } 1210 1211 if (changed) 1212 write_archive (arch); 1213 else 1214 output_filename = NULL; 1215 } 1216 1217 static void 1218 ranlib_only (const char *archname) 1219 { 1220 bfd *arch; 1221 1222 if (get_file_size (archname) < 1) 1223 return; 1224 write_armap = 1; 1225 arch = open_inarch (archname, (char *) NULL); 1226 if (arch == NULL) 1227 xexit (1); 1228 write_archive (arch); 1229 } 1230 1231 /* Update the timestamp of the symbol map of an archive. */ 1232 1233 static void 1234 ranlib_touch (const char *archname) 1235 { 1236 #ifdef __GO32__ 1237 /* I don't think updating works on go32. */ 1238 ranlib_only (archname); 1239 #else 1240 int f; 1241 bfd *arch; 1242 char **matching; 1243 1244 if (get_file_size (archname) < 1) 1245 return; 1246 f = open (archname, O_RDWR | O_BINARY, 0); 1247 if (f < 0) 1248 { 1249 bfd_set_error (bfd_error_system_call); 1250 bfd_fatal (archname); 1251 } 1252 1253 arch = bfd_fdopenr (archname, (const char *) NULL, f); 1254 if (arch == NULL) 1255 bfd_fatal (archname); 1256 if (! bfd_check_format_matches (arch, bfd_archive, &matching)) 1257 { 1258 bfd_nonfatal (archname); 1259 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 1260 { 1261 list_matching_formats (matching); 1262 free (matching); 1263 } 1264 xexit (1); 1265 } 1266 1267 if (! bfd_has_map (arch)) 1268 /* xgettext:c-format */ 1269 fatal (_("%s: no archive map to update"), archname); 1270 1271 bfd_update_armap_timestamp (arch); 1272 1273 if (! bfd_close (arch)) 1274 bfd_fatal (archname); 1275 #endif 1276 } 1277 1278 /* Things which are interesting to map over all or some of the files: */ 1279 1280 static void 1281 print_descr (bfd *abfd) 1282 { 1283 print_arelt_descr (stdout, abfd, verbose); 1284 } 1285