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