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