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