ar.c revision 33965
1246074Sgabor/* ar.c - Archive modify and extract. 2246074Sgabor Copyright 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. 3246074Sgabor 4246074SgaborThis file is part of GNU Binutils. 5246074Sgabor 6246074SgaborThis program is free software; you can redistribute it and/or modify 7246074Sgaborit under the terms of the GNU General Public License as published by 8246074Sgaborthe Free Software Foundation; either version 2 of the License, or 9246074Sgabor(at your option) any later version. 10246074Sgabor 11246074SgaborThis program is distributed in the hope that it will be useful, 12246074Sgaborbut WITHOUT ANY WARRANTY; without even the implied warranty of 13246074SgaborMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14246074SgaborGNU General Public License for more details. 15246074Sgabor 16246074SgaborYou should have received a copy of the GNU General Public License 17246074Sgaboralong with this program; if not, write to the Free Software 18246074SgaborFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 19246074Sgabor 20246074Sgabor/* 21246074Sgabor Bugs: should use getopt the way tar does (complete w/optional -) and 22246074Sgabor should have long options too. GNU ar used to check file against filesystem 23246074Sgabor in quick_update and replace operations (would check mtime). Doesn't warn 24246074Sgabor when name truncated. No way to specify pos_end. Error messages should be 25246074Sgabor more consistant. 26246091Sdelphij*/ 27246091Sdelphij#include "bfd.h" 28246074Sgabor#include "libiberty.h" 29246074Sgabor#include "progress.h" 30246074Sgabor#include "bucomm.h" 31246074Sgabor#include "aout/ar.h" 32246074Sgabor#include "libbfd.h" 33246074Sgabor#include "arsup.h" 34246074Sgabor#include <sys/stat.h> 35246074Sgabor 36287223Sdelphij#ifdef HAVE_GOOD_UTIME_H 37246074Sgabor#include <utime.h> 38246074Sgabor#else /* ! HAVE_GOOD_UTIME_H */ 39246074Sgabor#ifdef HAVE_UTIMES 40246074Sgabor#include <sys/time.h> 41246074Sgabor#endif /* HAVE_UTIMES */ 42246074Sgabor#endif /* ! HAVE_GOOD_UTIME_H */ 43246074Sgabor 44246074Sgabor#ifdef __GO32___ 45246074Sgabor#define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */ 46246074Sgabor#else 47246074Sgabor#define EXT_NAME_LEN 6 /* ditto for *NIX */ 48246074Sgabor#endif 49246074Sgabor 50246074Sgabor#define BUFSIZE 8192 51246074Sgabor 52246074Sgabor/* Kludge declaration from BFD! This is ugly! FIXME! XXX */ 53246074Sgabor 54246074Sgaborstruct ar_hdr * 55246074Sgabor bfd_special_undocumented_glue PARAMS ((bfd * abfd, char *filename)); 56246074Sgabor 57246074Sgabor/* Static declarations */ 58246074Sgabor 59246074Sgaborstatic void 60246074Sgabormri_emul PARAMS ((void)); 61246074Sgabor 62246074Sgaborstatic const char * 63246074Sgabornormalize PARAMS ((const char *, bfd *)); 64246074Sgabor 65246074Sgaborstatic void 66246074Sgaborremove_output PARAMS ((void)); 67246074Sgabor 68246074Sgaborstatic void 69246074Sgabormap_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int)); 70246074Sgabor 71246074Sgaborstatic void 72246074Sgaborprint_contents PARAMS ((bfd * member)); 73246074Sgabor 74246074Sgaborstatic void 75246074Sgabordelete_members PARAMS ((bfd *, char **files_to_delete)); 76246074Sgabor 77246074Sgabor#if 0 78246074Sgaborstatic void 79246074Sgabordo_quick_append PARAMS ((const char *archive_filename, 80246074Sgabor char **files_to_append)); 81246074Sgabor#endif 82246074Sgabor 83246074Sgaborstatic void 84246074Sgabormove_members PARAMS ((bfd *, char **files_to_move)); 85246074Sgabor 86246074Sgaborstatic void 87246074Sgaborreplace_members PARAMS ((bfd *, char **files_to_replace, boolean quick)); 88246074Sgabor 89246074Sgaborstatic void 90246074Sgaborprint_descr PARAMS ((bfd * abfd)); 91246074Sgabor 92246074Sgaborstatic void 93246074Sgaborwrite_archive PARAMS ((bfd *)); 94246074Sgabor 95246074Sgaborstatic void 96246074Sgaborranlib_only PARAMS ((const char *archname)); 97246074Sgabor 98246074Sgaborstatic void 99287223Sdelphijranlib_touch PARAMS ((const char *archname)); 100246074Sgabor 101246074Sgaborstatic void 102246074Sgaborusage PARAMS ((int)); 103246074Sgabor 104246074Sgabor/** Globals and flags */ 105246074Sgabor 106246074Sgaborint mri_mode; 107246074Sgabor 108246074Sgabor/* This flag distinguishes between ar and ranlib: 109246074Sgabor 1 means this is 'ranlib'; 0 means this is 'ar'. 110246074Sgabor -1 means if we should use argv[0] to decide. */ 111246074Sgaborextern int is_ranlib; 112246074Sgabor 113246074Sgabor/* Nonzero means don't warn about creating the archive file if necessary. */ 114246074Sgaborint silent_create = 0; 115246074Sgabor 116246074Sgabor/* Nonzero means describe each action performed. */ 117246074Sgaborint verbose = 0; 118246074Sgabor 119246074Sgabor/* Nonzero means preserve dates of members when extracting them. */ 120246074Sgaborint preserve_dates = 0; 121246074Sgabor 122246074Sgabor/* Nonzero means don't replace existing members whose dates are more recent 123246074Sgabor than the corresponding files. */ 124246074Sgaborint newer_only = 0; 125246074Sgabor 126246074Sgabor/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF 127246074Sgabor member). -1 means we've been explicitly asked to not write a symbol table; 128246074Sgabor +1 means we've been explictly asked to write it; 129246074Sgabor 0 is the default. 130246074Sgabor Traditionally, the default in BSD has been to not write the table. 131246074Sgabor However, for POSIX.2 compliance the default is now to write a symbol table 132246074Sgabor if any of the members are object files. */ 133246074Sgaborint write_armap = 0; 134246074Sgabor 135246074Sgabor/* Nonzero means it's the name of an existing member; position new or moved 136246074Sgabor files with respect to this one. */ 137246074Sgaborchar *posname = NULL; 138246074Sgabor 139246074Sgabor/* Sez how to use `posname': pos_before means position before that member. 140246074Sgabor pos_after means position after that member. pos_end means always at end. 141246074Sgabor pos_default means default appropriately. For the latter two, `posname' 142246074Sgabor should also be zero. */ 143246074Sgaborenum pos 144246074Sgabor { 145246074Sgabor pos_default, pos_before, pos_after, pos_end 146246074Sgabor } postype = pos_default; 147246074Sgabor 148246074Sgaborstatic bfd ** 149246074Sgaborget_pos_bfd PARAMS ((bfd **, enum pos)); 150246074Sgabor 151246074Sgabor/* Whether to truncate names of files stored in the archive. */ 152246074Sgaborstatic boolean ar_truncate = false; 153246074Sgabor 154246074Sgaborint interactive = 0; 155246074Sgabor 156246074Sgaborstatic void 157246074Sgabormri_emul () 158246074Sgabor{ 159246074Sgabor interactive = isatty (fileno (stdin)); 160246074Sgabor yyparse (); 161246074Sgabor} 162246074Sgabor 163246074Sgabor/* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero, 164246074Sgabor COUNT is the length of the FILES chain; FUNCTION is called on each entry 165246074Sgabor whose name matches one in FILES. */ 166246074Sgabor 167246074Sgaborstatic void 168246074Sgabormap_over_members (arch, function, files, count) 169246074Sgabor bfd *arch; 170246074Sgabor void (*function) PARAMS ((bfd *)); 171246074Sgabor char **files; 172246074Sgabor int count; 173246074Sgabor{ 174246074Sgabor bfd *head; 175246074Sgabor 176246074Sgabor if (count == 0) 177246074Sgabor { 178246074Sgabor for (head = arch->next; head; head = head->next) 179246074Sgabor { 180246074Sgabor PROGRESS (1); 181246074Sgabor function (head); 182246074Sgabor } 183246074Sgabor return; 184246074Sgabor } 185246074Sgabor /* This may appear to be a baroque way of accomplishing what we want. 186246074Sgabor However we have to iterate over the filenames in order to notice where 187246074Sgabor a filename is requested but does not exist in the archive. Ditto 188246074Sgabor mapping over each file each time -- we want to hack multiple 189246074Sgabor references. */ 190246074Sgabor 191246074Sgabor for (; count > 0; files++, count--) 192246074Sgabor { 193246074Sgabor boolean found = false; 194246074Sgabor 195246074Sgabor for (head = arch->next; head; head = head->next) 196246074Sgabor { 197246074Sgabor PROGRESS (1); 198246074Sgabor if (head->filename == NULL) 199246074Sgabor { 200246074Sgabor /* Some archive formats don't get the filenames filled in 201246074Sgabor until the elements are opened. */ 202246074Sgabor struct stat buf; 203246074Sgabor bfd_stat_arch_elt (head, &buf); 204246074Sgabor } 205276807Spfg if ((head->filename != NULL) && 206276807Spfg (!strcmp (*files, head->filename))) 207276807Spfg { 208276807Spfg found = true; 209276807Spfg function (head); 210276807Spfg } 211276807Spfg } 212276807Spfg if (!found) 213276807Spfg fprintf (stderr, "no entry %s in archive\n", *files); 214276807Spfg } 215276807Spfg} 216276807Spfg 217276807Spfgboolean operation_alters_arch = false; 218276807Spfg 219276807Spfgstatic void 220276807Spfgusage (help) 221246074Sgabor int help; 222246074Sgabor{ 223246074Sgabor FILE *s; 224246074Sgabor 225246074Sgabor s = help ? stdout : stderr; 226246074Sgabor if (! is_ranlib) 227246074Sgabor fprintf (s, "\ 228246074SgaborUsage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\ 229246091Sdelphij %s -M [<mri-script]\n", 230246074Sgabor program_name, program_name); 231246091Sdelphij else 232246074Sgabor fprintf (s, "\ 233246074SgaborUsage: %s [-vV] archive\n", program_name); 234246074Sgabor 235246074Sgabor list_supported_targets (program_name, stderr); 236246074Sgabor 237246074Sgabor if (help) 238246074Sgabor fprintf (s, "Report bugs to bug-gnu-utils@prep.ai.mit.edu\n"); 239246074Sgabor 240246074Sgabor xexit (help ? 0 : 1); 241246074Sgabor} 242246074Sgabor 243246074Sgabor/* Normalize a file name specified on the command line into a file 244246074Sgabor name which we will use in an archive. */ 245246074Sgabor 246246074Sgaborstatic const char * 247246074Sgabornormalize (file, abfd) 248246074Sgabor const char *file; 249246074Sgabor bfd *abfd; 250246074Sgabor{ 251246074Sgabor const char *filename; 252246074Sgabor 253246074Sgabor filename = strrchr (file, '/'); 254246074Sgabor if (filename != (char *) NULL) 255246074Sgabor filename++; 256246074Sgabor else 257246074Sgabor filename = file; 258246074Sgabor 259246074Sgabor if (ar_truncate 260246074Sgabor && abfd != NULL 261246074Sgabor && strlen (filename) > abfd->xvec->ar_max_namelen) 262246074Sgabor { 263246074Sgabor char *s; 264246074Sgabor 265246074Sgabor /* Space leak. */ 266246074Sgabor s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1); 267246074Sgabor memcpy (s, filename, abfd->xvec->ar_max_namelen); 268246074Sgabor s[abfd->xvec->ar_max_namelen] = '\0'; 269246074Sgabor filename = s; 270246074Sgabor } 271246074Sgabor 272246074Sgabor return filename; 273246074Sgabor} 274246074Sgabor 275246074Sgabor/* Remove any output file. This is only called via xatexit. */ 276246074Sgabor 277246074Sgaborstatic char *output_filename = NULL; 278246074Sgaborstatic FILE *output_file = NULL; 279246074Sgaborstatic bfd *output_bfd = NULL; 280246074Sgabor 281246074Sgaborstatic void 282246074Sgaborremove_output () 283246074Sgabor{ 284246074Sgabor if (output_filename != NULL) 285246074Sgabor { 286246074Sgabor if (output_bfd != NULL && output_bfd->iostream != NULL) 287246074Sgabor fclose ((FILE *) (output_bfd->iostream)); 288246074Sgabor if (output_file != NULL) 289246074Sgabor fclose (output_file); 290246074Sgabor unlink (output_filename); 291246074Sgabor } 292246074Sgabor} 293246074Sgabor 294246074Sgabor/* The option parsing should be in its own function. 295246074Sgabor It will be when I have getopt working. */ 296246074Sgabor 297246074Sgaborint 298246074Sgabormain (argc, argv) 299246074Sgabor int argc; 300246074Sgabor char **argv; 301246074Sgabor{ 302246074Sgabor char *arg_ptr; 303246074Sgabor char c; 304246074Sgabor enum 305246074Sgabor { 306246074Sgabor none = 0, delete, replace, print_table, 307246074Sgabor print_files, extract, move, quick_append 308246074Sgabor } operation = none; 309246074Sgabor int arg_index; 310246074Sgabor char **files; 311246074Sgabor char *inarch_filename; 312246074Sgabor int show_version; 313246074Sgabor 314246074Sgabor program_name = argv[0]; 315246074Sgabor xmalloc_set_program_name (program_name); 316246074Sgabor 317246074Sgabor if (is_ranlib < 0) 318246074Sgabor { 319246074Sgabor char *temp; 320246074Sgabor 321246074Sgabor temp = strrchr (program_name, '/'); 322246074Sgabor if (temp == NULL) 323246074Sgabor temp = program_name; 324246074Sgabor else 325246074Sgabor ++temp; 326246074Sgabor if (strlen (temp) >= 6 327246074Sgabor && strcmp (temp + strlen (temp) - 6, "ranlib") == 0) 328246074Sgabor is_ranlib = 1; 329246074Sgabor else 330246074Sgabor is_ranlib = 0; 331246074Sgabor } 332246074Sgabor 333246074Sgabor if (argc > 1 && argv[1][0] == '-') 334246074Sgabor { 335246074Sgabor if (strcmp (argv[1], "--help") == 0) 336246074Sgabor usage (1); 337246074Sgabor else if (strcmp (argv[1], "--version") == 0) 338246074Sgabor { 339246074Sgabor if (is_ranlib) 340246074Sgabor print_version ("ranlib"); 341246074Sgabor else 342246074Sgabor print_version ("ar"); 343246074Sgabor } 344246074Sgabor } 345246074Sgabor 346246074Sgabor START_PROGRESS (program_name, 0); 347246074Sgabor 348246074Sgabor bfd_init (); 349246074Sgabor set_default_bfd_target (); 350246074Sgabor 351246074Sgabor show_version = 0; 352246074Sgabor 353246074Sgabor xatexit (remove_output); 354246074Sgabor 355246074Sgabor if (is_ranlib) 356246074Sgabor { 357246074Sgabor boolean touch = false; 358246074Sgabor 359246074Sgabor if (argc < 2 || strcmp (argv[1], "--help") == 0) 360246074Sgabor usage (0); 361246074Sgabor if (strcmp (argv[1], "-V") == 0 362246074Sgabor || strcmp (argv[1], "-v") == 0 363246074Sgabor || strncmp (argv[1], "--v", 3) == 0) 364246074Sgabor print_version ("ranlib"); 365246074Sgabor arg_index = 1; 366246074Sgabor if (strcmp (argv[1], "-t") == 0) 367246074Sgabor { 368246074Sgabor ++arg_index; 369246074Sgabor touch = true; 370246074Sgabor } 371246074Sgabor while (arg_index < argc) 372246074Sgabor { 373246074Sgabor if (! touch) 374246074Sgabor ranlib_only (argv[arg_index]); 375246074Sgabor else 376246074Sgabor ranlib_touch (argv[arg_index]); 377246074Sgabor ++arg_index; 378246074Sgabor } 379246074Sgabor xexit (0); 380246074Sgabor } 381246074Sgabor 382246074Sgabor if (argc == 2 && strcmp (argv[1], "-M") == 0) 383246074Sgabor { 384246074Sgabor mri_emul (); 385246074Sgabor xexit (0); 386246074Sgabor } 387246074Sgabor 388246074Sgabor if (argc < 2) 389246074Sgabor usage (0); 390246074Sgabor 391246074Sgabor arg_ptr = argv[1]; 392246074Sgabor 393246074Sgabor if (*arg_ptr == '-') 394246074Sgabor ++arg_ptr; /* compatibility */ 395246074Sgabor 396246074Sgabor while ((c = *arg_ptr++) != '\0') 397246074Sgabor { 398246074Sgabor switch (c) 399246074Sgabor { 400246074Sgabor case 'd': 401246074Sgabor case 'm': 402246074Sgabor case 'p': 403246074Sgabor case 'q': 404246074Sgabor case 'r': 405246074Sgabor case 't': 406246074Sgabor case 'x': 407246074Sgabor if (operation != none) 408246074Sgabor fatal ("two different operation options specified"); 409287223Sdelphij switch (c) 410246074Sgabor { 411246074Sgabor case 'd': 412246074Sgabor operation = delete; 413246074Sgabor operation_alters_arch = true; 414246074Sgabor break; 415246074Sgabor case 'm': 416246074Sgabor operation = move; 417246074Sgabor operation_alters_arch = true; 418246074Sgabor break; 419246074Sgabor case 'p': 420246074Sgabor operation = print_files; 421246074Sgabor break; 422246074Sgabor case 'q': 423246074Sgabor operation = quick_append; 424246074Sgabor operation_alters_arch = true; 425246074Sgabor break; 426246074Sgabor case 'r': 427246074Sgabor operation = replace; 428246074Sgabor operation_alters_arch = true; 429246074Sgabor break; 430246074Sgabor case 't': 431276706Spfg operation = print_table; 432246074Sgabor break; 433246074Sgabor case 'x': 434246074Sgabor operation = extract; 435246074Sgabor break; 436246074Sgabor } 437246074Sgabor case 'l': 438246074Sgabor break; 439246074Sgabor case 'c': 440246074Sgabor silent_create = 1; 441246074Sgabor break; 442246074Sgabor case 'o': 443246074Sgabor preserve_dates = 1; 444246074Sgabor break; 445246074Sgabor case 'V': 446246074Sgabor show_version = true; 447246074Sgabor break; 448246074Sgabor case 's': 449 write_armap = 1; 450 break; 451 case 'u': 452 newer_only = 1; 453 break; 454 case 'v': 455 verbose = 1; 456 break; 457 case 'a': 458 postype = pos_after; 459 break; 460 case 'b': 461 postype = pos_before; 462 break; 463 case 'i': 464 postype = pos_before; 465 break; 466 case 'M': 467 mri_mode = 1; 468 break; 469 case 'f': 470 ar_truncate = true; 471 break; 472 default: 473 fprintf (stderr, "%s: illegal option -- %c\n", program_name, c); 474 usage (0); 475 } 476 } 477 478 if (show_version) 479 print_version ("ar"); 480 481 if (argc < 3) 482 usage (0); 483 484 if (mri_mode) 485 { 486 mri_emul (); 487 } 488 else 489 { 490 bfd *arch; 491 492 /* We can't write an armap when using ar q, so just do ar r 493 instead. */ 494 if (operation == quick_append && write_armap) 495 operation = replace; 496 497 if ((operation == none || operation == print_table) 498 && write_armap == 1) 499 { 500 ranlib_only (argv[2]); 501 xexit (0); 502 } 503 504 if (operation == none) 505 fatal ("no operation specified"); 506 507 if (newer_only && operation != replace) 508 fatal ("`u' is only meaningful with the `r' option."); 509 510 arg_index = 2; 511 512 if (postype != pos_default) 513 posname = argv[arg_index++]; 514 515 inarch_filename = argv[arg_index++]; 516 517 files = arg_index < argc ? argv + arg_index : NULL; 518 519#if 0 520 /* We don't use do_quick_append any more. Too many systems 521 expect ar to always rebuild the symbol table even when q is 522 used. */ 523 524 /* We can't do a quick append if we need to construct an 525 extended name table, because do_quick_append won't be able to 526 rebuild the name table. Unfortunately, at this point we 527 don't actually know the maximum name length permitted by this 528 object file format. So, we guess. FIXME. */ 529 if (operation == quick_append && ! ar_truncate) 530 { 531 char **chk; 532 533 for (chk = files; chk != NULL && *chk != '\0'; chk++) 534 { 535 if (strlen (normalize (*chk, (bfd *) NULL)) > 14) 536 { 537 operation = replace; 538 break; 539 } 540 } 541 } 542 543 if (operation == quick_append) 544 { 545 /* Note that quick appending to a non-existent archive creates it, 546 even if there are no files to append. */ 547 do_quick_append (inarch_filename, files); 548 xexit (0); 549 } 550#endif 551 552 arch = open_inarch (inarch_filename, 553 files == NULL ? (char *) NULL : files[0]); 554 555 switch (operation) 556 { 557 case print_table: 558 map_over_members (arch, print_descr, files, argc - 3); 559 break; 560 561 case print_files: 562 map_over_members (arch, print_contents, files, argc - 3); 563 break; 564 565 case extract: 566 map_over_members (arch, extract_file, files, argc - 3); 567 break; 568 569 case delete: 570 if (files != NULL) 571 delete_members (arch, files); 572 break; 573 574 case move: 575 if (files != NULL) 576 move_members (arch, files); 577 break; 578 579 case replace: 580 case quick_append: 581 if (files != NULL || write_armap > 0) 582 replace_members (arch, files, operation == quick_append); 583 break; 584 585 /* Shouldn't happen! */ 586 default: 587 fprintf (stderr, "%s: internal error -- this option not implemented\n", 588 program_name); 589 xexit (1); 590 } 591 } 592 593 END_PROGRESS (program_name); 594 595 xexit (0); 596 return 0; 597} 598 599bfd * 600open_inarch (archive_filename, file) 601 const char *archive_filename; 602 const char *file; 603{ 604 const char *target; 605 bfd **last_one; 606 bfd *next_one; 607 struct stat sbuf; 608 bfd *arch; 609 char **matching; 610 611 bfd_set_error (bfd_error_no_error); 612 613 target = NULL; 614 615 if (stat (archive_filename, &sbuf) != 0) 616 { 617#ifndef __GO32__ 618 619/* KLUDGE ALERT! Temporary fix until I figger why 620 * stat() is wrong ... think it's buried in GO32's IDT 621 * - Jax 622 */ 623 if (errno != ENOENT) 624 bfd_fatal (archive_filename); 625#endif 626 627 if (!operation_alters_arch) 628 { 629 fprintf (stderr, "%s: ", program_name); 630 perror (archive_filename); 631 maybequit (); 632 return NULL; 633 } 634 635 /* Try to figure out the target to use for the archive from the 636 first object on the list. */ 637 if (file != NULL) 638 { 639 bfd *obj; 640 641 obj = bfd_openr (file, NULL); 642 if (obj != NULL) 643 { 644 if (bfd_check_format (obj, bfd_object)) 645 target = bfd_get_target (obj); 646 (void) bfd_close (obj); 647 } 648 } 649 650 /* Create an empty archive. */ 651 arch = bfd_openw (archive_filename, target); 652 if (arch == NULL 653 || ! bfd_set_format (arch, bfd_archive) 654 || ! bfd_close (arch)) 655 bfd_fatal (archive_filename); 656 } 657 658 arch = bfd_openr (archive_filename, target); 659 if (arch == NULL) 660 { 661 bloser: 662 bfd_fatal (archive_filename); 663 } 664 665 if (! bfd_check_format_matches (arch, bfd_archive, &matching)) 666 { 667 bfd_nonfatal (archive_filename); 668 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 669 { 670 list_matching_formats (matching); 671 free (matching); 672 } 673 xexit (1); 674 } 675 676 last_one = &(arch->next); 677 /* Read all the contents right away, regardless. */ 678 for (next_one = bfd_openr_next_archived_file (arch, NULL); 679 next_one; 680 next_one = bfd_openr_next_archived_file (arch, next_one)) 681 { 682 PROGRESS (1); 683 *last_one = next_one; 684 last_one = &next_one->next; 685 } 686 *last_one = (bfd *) NULL; 687 if (bfd_get_error () != bfd_error_no_more_archived_files) 688 goto bloser; 689 return arch; 690} 691 692static void 693print_contents (abfd) 694 bfd *abfd; 695{ 696 int ncopied = 0; 697 char *cbuf = xmalloc (BUFSIZE); 698 struct stat buf; 699 long size; 700 if (bfd_stat_arch_elt (abfd, &buf) != 0) 701 fatal ("internal stat error on %s", bfd_get_filename (abfd)); 702 703 if (verbose) 704 printf ("\n<member %s>\n\n", bfd_get_filename (abfd)); 705 706 bfd_seek (abfd, 0, SEEK_SET); 707 708 size = buf.st_size; 709 while (ncopied < size) 710 { 711 712 int nread; 713 int tocopy = size - ncopied; 714 if (tocopy > BUFSIZE) 715 tocopy = BUFSIZE; 716 717 nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke 718 abstraction! */ 719 if (nread != tocopy) 720 fatal ("%s is not a valid archive", 721 bfd_get_filename (bfd_my_archive (abfd))); 722 fwrite (cbuf, 1, nread, stdout); 723 ncopied += tocopy; 724 } 725 free (cbuf); 726} 727 728/* Extract a member of the archive into its own file. 729 730 We defer opening the new file until after we have read a BUFSIZ chunk of the 731 old one, since we know we have just read the archive header for the old 732 one. Since most members are shorter than BUFSIZ, this means we will read 733 the old header, read the old data, write a new inode for the new file, and 734 write the new data, and be done. This 'optimization' is what comes from 735 sitting next to a bare disk and hearing it every time it seeks. -- Gnu 736 Gilmore */ 737 738void 739extract_file (abfd) 740 bfd *abfd; 741{ 742 FILE *ostream; 743 char *cbuf = xmalloc (BUFSIZE); 744 int nread, tocopy; 745 int ncopied = 0; 746 long size; 747 struct stat buf; 748 if (bfd_stat_arch_elt (abfd, &buf) != 0) 749 fatal ("internal stat error on %s", bfd_get_filename (abfd)); 750 size = buf.st_size; 751 752 if (verbose) 753 printf ("x - %s\n", bfd_get_filename (abfd)); 754 755 bfd_seek (abfd, 0, SEEK_SET); 756 757 ostream = 0; 758 if (size == 0) 759 { 760 /* Seems like an abstraction violation, eh? Well it's OK! */ 761 output_filename = bfd_get_filename (abfd); 762 763 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); 764 if (!ostream) 765 { 766 perror (bfd_get_filename (abfd)); 767 xexit (1); 768 } 769 770 output_file = ostream; 771 } 772 else 773 while (ncopied < size) 774 { 775 tocopy = size - ncopied; 776 if (tocopy > BUFSIZE) 777 tocopy = BUFSIZE; 778 779 nread = bfd_read (cbuf, 1, tocopy, abfd); 780 if (nread != tocopy) 781 fatal ("%s is not a valid archive", 782 bfd_get_filename (bfd_my_archive (abfd))); 783 784 /* See comment above; this saves disk arm motion */ 785 if (!ostream) 786 { 787 /* Seems like an abstraction violation, eh? Well it's OK! */ 788 output_filename = bfd_get_filename (abfd); 789 790 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB); 791 if (!ostream) 792 { 793 perror (bfd_get_filename (abfd)); 794 xexit (1); 795 } 796 797 output_file = ostream; 798 } 799 fwrite (cbuf, 1, nread, ostream); 800 ncopied += tocopy; 801 } 802 803 fclose (ostream); 804 805 output_file = NULL; 806 output_filename = NULL; 807 808 chmod (bfd_get_filename (abfd), buf.st_mode); 809 810 if (preserve_dates) 811 { 812#ifdef HAVE_GOOD_UTIME_H 813 struct utimbuf tb; 814 tb.actime = buf.st_mtime; 815 tb.modtime = buf.st_mtime; 816 utime (bfd_get_filename (abfd), &tb); /* FIXME check result */ 817#else /* ! HAVE_GOOD_UTIME_H */ 818#ifndef HAVE_UTIMES 819 long tb[2]; 820 tb[0] = buf.st_mtime; 821 tb[1] = buf.st_mtime; 822 utime (bfd_get_filename (abfd), tb); /* FIXME check result */ 823#else /* HAVE_UTIMES */ 824 struct timeval tv[2]; 825 tv[0].tv_sec = buf.st_mtime; 826 tv[0].tv_usec = 0; 827 tv[1].tv_sec = buf.st_mtime; 828 tv[1].tv_usec = 0; 829 utimes (bfd_get_filename (abfd), tv); /* FIXME check result */ 830#endif /* HAVE_UTIMES */ 831#endif /* ! HAVE_GOOD_UTIME_H */ 832 } 833free (cbuf); 834} 835 836#if 0 837 838/* We don't use this anymore. Too many systems expect ar to rebuild 839 the symbol table even when q is used. */ 840 841/* Just do it quickly; don't worry about dups, armap, or anything like that */ 842 843static void 844do_quick_append (archive_filename, files_to_append) 845 const char *archive_filename; 846 char **files_to_append; 847{ 848 FILE *ofile, *ifile; 849 char *buf = xmalloc (BUFSIZE); 850 long tocopy, thistime; 851 bfd *temp; 852 struct stat sbuf; 853 boolean newfile = false; 854 bfd_set_error (bfd_error_no_error); 855 856 if (stat (archive_filename, &sbuf) != 0) 857 { 858 859#ifndef __GO32__ 860 861/* KLUDGE ALERT! Temporary fix until I figger why 862 * stat() is wrong ... think it's buried in GO32's IDT 863 * - Jax 864 */ 865 866 if (errno != ENOENT) 867 bfd_fatal (archive_filename); 868#endif 869 870 newfile = true; 871 } 872 873 ofile = fopen (archive_filename, FOPEN_AUB); 874 if (ofile == NULL) 875 { 876 perror (program_name); 877 xexit (1); 878 } 879 880 temp = bfd_openr (archive_filename, NULL); 881 if (temp == NULL) 882 { 883 bfd_fatal (archive_filename); 884 } 885 if (newfile == false) 886 { 887 if (bfd_check_format (temp, bfd_archive) != true) 888 fatal ("%s is not an archive", archive_filename); 889 } 890 else 891 { 892 fwrite (ARMAG, 1, SARMAG, ofile); 893 if (!silent_create) 894 fprintf (stderr, "%s: creating %s\n", 895 program_name, archive_filename); 896 } 897 898 if (ar_truncate) 899 temp->flags |= BFD_TRADITIONAL_FORMAT; 900 901 /* assume it's an achive, go straight to the end, sans $200 */ 902 fseek (ofile, 0, 2); 903 904 for (; files_to_append && *files_to_append; ++files_to_append) 905 { 906 struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append); 907 if (hdr == NULL) 908 { 909 bfd_fatal (*files_to_append); 910 } 911 912 BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr)); 913 914 ifile = fopen (*files_to_append, FOPEN_RB); 915 if (ifile == NULL) 916 { 917 bfd_nonfatal (*files_to_append); 918 } 919 920 if (stat (*files_to_append, &sbuf) != 0) 921 { 922 bfd_nonfatal (*files_to_append); 923 } 924 925 tocopy = sbuf.st_size; 926 927 /* XXX should do error-checking! */ 928 fwrite (hdr, 1, sizeof (struct ar_hdr), ofile); 929 930 while (tocopy > 0) 931 { 932 thistime = tocopy; 933 if (thistime > BUFSIZE) 934 thistime = BUFSIZE; 935 fread (buf, 1, thistime, ifile); 936 fwrite (buf, 1, thistime, ofile); 937 tocopy -= thistime; 938 } 939 fclose (ifile); 940 if ((sbuf.st_size % 2) == 1) 941 putc ('\012', ofile); 942 } 943 fclose (ofile); 944 bfd_close (temp); 945 free (buf); 946} 947 948#endif /* 0 */ 949 950static void 951write_archive (iarch) 952 bfd *iarch; 953{ 954 bfd *obfd; 955 char *old_name, *new_name; 956 bfd *contents_head = iarch->next; 957 958 old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1); 959 strcpy (old_name, bfd_get_filename (iarch)); 960 new_name = make_tempname (old_name); 961 962 output_filename = new_name; 963 964 obfd = bfd_openw (new_name, bfd_get_target (iarch)); 965 966 if (obfd == NULL) 967 bfd_fatal (old_name); 968 969 output_bfd = obfd; 970 971 bfd_set_format (obfd, bfd_archive); 972 973 /* Request writing the archive symbol table unless we've 974 been explicitly requested not to. */ 975 obfd->has_armap = write_armap >= 0; 976 977 if (ar_truncate) 978 { 979 /* This should really use bfd_set_file_flags, but that rejects 980 archives. */ 981 obfd->flags |= BFD_TRADITIONAL_FORMAT; 982 } 983 984 if (bfd_set_archive_head (obfd, contents_head) != true) 985 bfd_fatal (old_name); 986 987 if (!bfd_close (obfd)) 988 bfd_fatal (old_name); 989 990 output_bfd = NULL; 991 output_filename = NULL; 992 993 /* We don't care if this fails; we might be creating the archive. */ 994 bfd_close (iarch); 995 unlink (old_name); 996 997 if (rename (new_name, old_name) != 0) 998 bfd_fatal (old_name); 999} 1000 1001/* Return a pointer to the pointer to the entry which should be rplacd'd 1002 into when altering. DEFAULT_POS should be how to interpret pos_default, 1003 and should be a pos value. */ 1004 1005static bfd ** 1006get_pos_bfd (contents, default_pos) 1007 bfd **contents; 1008 enum pos default_pos; 1009{ 1010 bfd **after_bfd = contents; 1011 enum pos realpos = (postype == pos_default ? default_pos : postype); 1012 1013 if (realpos == pos_end) 1014 { 1015 while (*after_bfd) 1016 after_bfd = &((*after_bfd)->next); 1017 } 1018 else 1019 { 1020 for (; *after_bfd; after_bfd = &(*after_bfd)->next) 1021 if (!strcmp ((*after_bfd)->filename, posname)) 1022 { 1023 if (realpos == pos_after) 1024 after_bfd = &(*after_bfd)->next; 1025 break; 1026 } 1027 } 1028 return after_bfd; 1029} 1030 1031static void 1032delete_members (arch, files_to_delete) 1033 bfd *arch; 1034 char **files_to_delete; 1035{ 1036 bfd **current_ptr_ptr; 1037 boolean found; 1038 boolean something_changed = false; 1039 for (; *files_to_delete != NULL; ++files_to_delete) 1040 { 1041 /* In a.out systems, the armap is optional. It's also called 1042 __.SYMDEF. So if the user asked to delete it, we should remember 1043 that fact. This isn't quite right for COFF systems (where 1044 __.SYMDEF might be regular member), but it's very unlikely 1045 to be a problem. FIXME */ 1046 1047 if (!strcmp (*files_to_delete, "__.SYMDEF")) 1048 { 1049 arch->has_armap = false; 1050 write_armap = -1; 1051 continue; 1052 } 1053 1054 found = false; 1055 current_ptr_ptr = &(arch->next); 1056 while (*current_ptr_ptr) 1057 { 1058 if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0) 1059 { 1060 found = true; 1061 something_changed = true; 1062 if (verbose) 1063 printf ("d - %s\n", 1064 *files_to_delete); 1065 *current_ptr_ptr = ((*current_ptr_ptr)->next); 1066 goto next_file; 1067 } 1068 else 1069 { 1070 current_ptr_ptr = &((*current_ptr_ptr)->next); 1071 } 1072 } 1073 1074 if (verbose && found == false) 1075 { 1076 printf ("No member named `%s'\n", *files_to_delete); 1077 } 1078 next_file: 1079 ; 1080 } 1081 1082 if (something_changed == true) 1083 { 1084 write_archive (arch); 1085 } 1086} 1087 1088 1089/* Reposition existing members within an archive */ 1090 1091static void 1092move_members (arch, files_to_move) 1093 bfd *arch; 1094 char **files_to_move; 1095{ 1096 bfd **after_bfd; /* New entries go after this one */ 1097 bfd **current_ptr_ptr; /* cdr pointer into contents */ 1098 1099 for (; *files_to_move; ++files_to_move) 1100 { 1101 current_ptr_ptr = &(arch->next); 1102 while (*current_ptr_ptr) 1103 { 1104 bfd *current_ptr = *current_ptr_ptr; 1105 if (strcmp (normalize (*files_to_move, arch), 1106 current_ptr->filename) == 0) 1107 { 1108 /* Move this file to the end of the list - first cut from 1109 where it is. */ 1110 bfd *link; 1111 *current_ptr_ptr = current_ptr->next; 1112 1113 /* Now glue to end */ 1114 after_bfd = get_pos_bfd (&arch->next, pos_end); 1115 link = *after_bfd; 1116 *after_bfd = current_ptr; 1117 current_ptr->next = link; 1118 1119 if (verbose) 1120 printf ("m - %s\n", *files_to_move); 1121 1122 goto next_file; 1123 } 1124 1125 current_ptr_ptr = &((*current_ptr_ptr)->next); 1126 } 1127 fprintf (stderr, "%s: no entry %s in archive %s!\n", 1128 program_name, *files_to_move, arch->filename); 1129 xexit (1); 1130 next_file:; 1131 } 1132 1133 write_archive (arch); 1134} 1135 1136/* Ought to default to replacing in place, but this is existing practice! */ 1137 1138static void 1139replace_members (arch, files_to_move, quick) 1140 bfd *arch; 1141 char **files_to_move; 1142 boolean quick; 1143{ 1144 boolean changed = false; 1145 bfd **after_bfd; /* New entries go after this one */ 1146 bfd *current; 1147 bfd **current_ptr; 1148 bfd *temp; 1149 1150 while (files_to_move && *files_to_move) 1151 { 1152 if (! quick) 1153 { 1154 current_ptr = &arch->next; 1155 while (*current_ptr) 1156 { 1157 current = *current_ptr; 1158 1159 /* For compatibility with existing ar programs, we 1160 permit the same file to be added multiple times. */ 1161 if (strcmp (normalize (*files_to_move, arch), 1162 normalize (current->filename, arch)) == 0 1163 && current->arelt_data != NULL) 1164 { 1165 if (newer_only) 1166 { 1167 struct stat fsbuf, asbuf; 1168 1169 if (stat (*files_to_move, &fsbuf) != 0) 1170 { 1171 if (errno != ENOENT) 1172 bfd_fatal (*files_to_move); 1173 goto next_file; 1174 } 1175 if (bfd_stat_arch_elt (current, &asbuf) != 0) 1176 fatal ("internal stat error on %s", current->filename); 1177 1178 if (fsbuf.st_mtime <= asbuf.st_mtime) 1179 goto next_file; 1180 } 1181 1182 /* snip out this entry from the chain */ 1183 *current_ptr = current->next; 1184 1185 after_bfd = get_pos_bfd (&arch->next, pos_end); 1186 temp = *after_bfd; 1187 *after_bfd = bfd_openr (*files_to_move, NULL); 1188 if (*after_bfd == (bfd *) NULL) 1189 { 1190 bfd_fatal (*files_to_move); 1191 } 1192 (*after_bfd)->next = temp; 1193 1194 if (verbose) 1195 { 1196 printf ("r - %s\n", *files_to_move); 1197 } 1198 1199 changed = true; 1200 1201 goto next_file; 1202 } 1203 current_ptr = &(current->next); 1204 } 1205 } 1206 1207 /* Add to the end of the archive. */ 1208 1209 after_bfd = get_pos_bfd (&arch->next, pos_end); 1210 temp = *after_bfd; 1211 *after_bfd = bfd_openr (*files_to_move, NULL); 1212 if (*after_bfd == (bfd *) NULL) 1213 { 1214 bfd_fatal (*files_to_move); 1215 } 1216 if (verbose) 1217 { 1218 printf ("a - %s\n", *files_to_move); 1219 } 1220 1221 (*after_bfd)->next = temp; 1222 1223 changed = true; 1224 1225 next_file:; 1226 1227 files_to_move++; 1228 } 1229 1230 if (changed) 1231 write_archive (arch); 1232} 1233 1234static void 1235ranlib_only (archname) 1236 const char *archname; 1237{ 1238 bfd *arch; 1239 1240 write_armap = 1; 1241 arch = open_inarch (archname, (char *) NULL); 1242 if (arch == NULL) 1243 xexit (1); 1244 write_archive (arch); 1245} 1246 1247/* Update the timestamp of the symbol map of an archive. */ 1248 1249static void 1250ranlib_touch (archname) 1251 const char *archname; 1252{ 1253#ifdef __GO32__ 1254 /* I don't think updating works on go32. */ 1255 ranlib_only (archname); 1256#else 1257 int f; 1258 bfd *arch; 1259 char **matching; 1260 1261 f = open (archname, O_RDWR, 0); 1262 if (f < 0) 1263 { 1264 bfd_set_error (bfd_error_system_call); 1265 bfd_fatal (archname); 1266 } 1267 1268 arch = bfd_fdopenr (archname, (const char *) NULL, f); 1269 if (arch == NULL) 1270 bfd_fatal (archname); 1271 if (! bfd_check_format_matches (arch, bfd_archive, &matching)) 1272 { 1273 bfd_nonfatal (archname); 1274 if (bfd_get_error () == bfd_error_file_ambiguously_recognized) 1275 { 1276 list_matching_formats (matching); 1277 free (matching); 1278 } 1279 xexit (1); 1280 } 1281 1282 if (! bfd_has_map (arch)) 1283 fatal ("%s: no archive map to update", archname); 1284 1285 bfd_update_armap_timestamp (arch); 1286 1287 if (! bfd_close (arch)) 1288 bfd_fatal (archname); 1289#endif 1290} 1291 1292/* Things which are interesting to map over all or some of the files: */ 1293 1294static void 1295print_descr (abfd) 1296 bfd *abfd; 1297{ 1298 print_arelt_descr (stdout, abfd, verbose); 1299} 1300