Back to index

cell-binutils  2.17cvs20070401
ar.c
Go to the documentation of this file.
00001 /* ar.c - Archive modify and extract.
00002    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
00003    2001, 2002, 2003, 2004, 2005, 2006, 2007
00004    Free Software Foundation, Inc.
00005 
00006    This file is part of GNU Binutils.
00007 
00008    This program is free software; you can redistribute it and/or modify
00009    it under the terms of the GNU General Public License as published by
00010    the Free Software Foundation; either version 2 of the License, or
00011    (at your option) any later version.
00012 
00013    This program is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016    GNU General Public License for more details.
00017 
00018    You should have received a copy of the GNU General Public License
00019    along with this program; if not, write to the Free Software
00020    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
00021 
00022 /*
00023    Bugs: should use getopt the way tar does (complete w/optional -) and
00024    should have long options too. GNU ar used to check file against filesystem
00025    in quick_update and replace operations (would check mtime). Doesn't warn
00026    when name truncated. No way to specify pos_end. Error messages should be
00027    more consistent.  */
00028 
00029 #include "bfd.h"
00030 #include "libiberty.h"
00031 #include "progress.h"
00032 #include "bucomm.h"
00033 #include "aout/ar.h"
00034 #include "libbfd.h"
00035 #include "arsup.h"
00036 #include "filenames.h"
00037 #include "binemul.h"
00038 #include <sys/stat.h>
00039 
00040 #ifdef __GO32___
00041 #define EXT_NAME_LEN 3             /* bufflen of addition to name if it's MS-DOS */
00042 #else
00043 #define EXT_NAME_LEN 6             /* ditto for *NIX */
00044 #endif
00045 
00046 /* We need to open files in binary modes on system where that makes a
00047    difference.  */
00048 #ifndef O_BINARY
00049 #define O_BINARY 0
00050 #endif
00051 
00052 /* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
00053 
00054 struct ar_hdr *
00055   bfd_special_undocumented_glue (bfd * abfd, const char *filename);
00056 
00057 /* Static declarations */
00058 
00059 static void mri_emul (void);
00060 static const char *normalize (const char *, bfd *);
00061 static void remove_output (void);
00062 static void map_over_members (bfd *, void (*)(bfd *), char **, int);
00063 static void print_contents (bfd * member);
00064 static void delete_members (bfd *, char **files_to_delete);
00065 
00066 static void move_members (bfd *, char **files_to_move);
00067 static void replace_members
00068   (bfd *, char **files_to_replace, bfd_boolean quick);
00069 static void print_descr (bfd * abfd);
00070 static void write_archive (bfd *);
00071 static int  ranlib_only (const char *archname);
00072 static int  ranlib_touch (const char *archname);
00073 static void usage (int);
00074 
00077 static int mri_mode;
00078 
00079 /* This flag distinguishes between ar and ranlib:
00080    1 means this is 'ranlib'; 0 means this is 'ar'.
00081    -1 means if we should use argv[0] to decide.  */
00082 extern int is_ranlib;
00083 
00084 /* Nonzero means don't warn about creating the archive file if necessary.  */
00085 int silent_create = 0;
00086 
00087 /* Nonzero means describe each action performed.  */
00088 int verbose = 0;
00089 
00090 /* Nonzero means preserve dates of members when extracting them.  */
00091 int preserve_dates = 0;
00092 
00093 /* Nonzero means don't replace existing members whose dates are more recent
00094    than the corresponding files.  */
00095 int newer_only = 0;
00096 
00097 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
00098    member).  -1 means we've been explicitly asked to not write a symbol table;
00099    +1 means we've been explicitly asked to write it;
00100    0 is the default.
00101    Traditionally, the default in BSD has been to not write the table.
00102    However, for POSIX.2 compliance the default is now to write a symbol table
00103    if any of the members are object files.  */
00104 int write_armap = 0;
00105 
00106 /* Nonzero means it's the name of an existing member; position new or moved
00107    files with respect to this one.  */
00108 char *posname = NULL;
00109 
00110 /* Sez how to use `posname': pos_before means position before that member.
00111    pos_after means position after that member. pos_end means always at end.
00112    pos_default means default appropriately. For the latter two, `posname'
00113    should also be zero.  */
00114 enum pos
00115   {
00116     pos_default, pos_before, pos_after, pos_end
00117   } postype = pos_default;
00118 
00119 static bfd **
00120 get_pos_bfd (bfd **, enum pos, const char *);
00121 
00122 /* For extract/delete only.  If COUNTED_NAME_MODE is TRUE, we only
00123    extract the COUNTED_NAME_COUNTER instance of that name.  */
00124 static bfd_boolean counted_name_mode = 0;
00125 static int counted_name_counter = 0;
00126 
00127 /* Whether to truncate names of files stored in the archive.  */
00128 static bfd_boolean ar_truncate = FALSE;
00129 
00130 /* Whether to use a full file name match when searching an archive.
00131    This is convenient for archives created by the Microsoft lib
00132    program.  */
00133 static bfd_boolean full_pathname = FALSE;
00134 
00135 int interactive = 0;
00136 
00137 static void
00138 mri_emul (void)
00139 {
00140   interactive = isatty (fileno (stdin));
00141   yyparse ();
00142 }
00143 
00144 /* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
00145    COUNT is the length of the FILES chain; FUNCTION is called on each entry
00146    whose name matches one in FILES.  */
00147 
00148 static void
00149 map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
00150 {
00151   bfd *head;
00152   int match_count;
00153 
00154   if (count == 0)
00155     {
00156       for (head = arch->next; head; head = head->next)
00157        {
00158          PROGRESS (1);
00159          function (head);
00160        }
00161       return;
00162     }
00163 
00164   /* This may appear to be a baroque way of accomplishing what we want.
00165      However we have to iterate over the filenames in order to notice where
00166      a filename is requested but does not exist in the archive.  Ditto
00167      mapping over each file each time -- we want to hack multiple
00168      references.  */
00169 
00170   for (; count > 0; files++, count--)
00171     {
00172       bfd_boolean found = FALSE;
00173 
00174       match_count = 0;
00175       for (head = arch->next; head; head = head->next)
00176        {
00177          PROGRESS (1);
00178          if (head->filename == NULL)
00179            {
00180              /* Some archive formats don't get the filenames filled in
00181                until the elements are opened.  */
00182              struct stat buf;
00183              bfd_stat_arch_elt (head, &buf);
00184            }
00185          if ((head->filename != NULL) &&
00186              (!FILENAME_CMP (normalize (*files, arch), head->filename)))
00187            {
00188              ++match_count;
00189              if (counted_name_mode
00190                 && match_count != counted_name_counter)
00191               {
00192                 /* Counting, and didn't match on count; go on to the
00193                      next one.  */
00194                 continue;
00195               }
00196 
00197              found = TRUE;
00198              function (head);
00199            }
00200        }
00201       if (!found)
00202        /* xgettext:c-format */
00203        fprintf (stderr, _("no entry %s in archive\n"), *files);
00204     }
00205 }
00206 
00207 bfd_boolean operation_alters_arch = FALSE;
00208 
00209 static void
00210 usage (int help)
00211 {
00212   FILE *s;
00213 
00214   s = help ? stdout : stderr;
00215 
00216   if (! is_ranlib)
00217     {
00218       /* xgettext:c-format */
00219       fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
00220               program_name);
00221       /* xgettext:c-format */
00222       fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
00223       fprintf (s, _(" commands:\n"));
00224       fprintf (s, _("  d            - delete file(s) from the archive\n"));
00225       fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
00226       fprintf (s, _("  p            - print file(s) found in the archive\n"));
00227       fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
00228       fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
00229       fprintf (s, _("  t            - display contents of archive\n"));
00230       fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
00231       fprintf (s, _(" command specific modifiers:\n"));
00232       fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
00233       fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
00234       fprintf (s, _("  [N]          - use instance [count] of name\n"));
00235       fprintf (s, _("  [f]          - truncate inserted file names\n"));
00236       fprintf (s, _("  [P]          - use full path names when matching\n"));
00237       fprintf (s, _("  [o]          - preserve original dates\n"));
00238       fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
00239       fprintf (s, _(" generic modifiers:\n"));
00240       fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
00241       fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
00242       fprintf (s, _("  [S]          - do not build a symbol table\n"));
00243       fprintf (s, _("  [v]          - be verbose\n"));
00244       fprintf (s, _("  [V]          - display the version number\n"));
00245       fprintf (s, _("  @<file>      - read options from <file>\n"));
00246  
00247       ar_emul_usage (s);
00248     }
00249   else
00250     {
00251       /* xgettext:c-format */
00252       fprintf (s, _("Usage: %s [options] archive\n"), program_name);
00253       fprintf (s, _(" Generate an index to speed access to archives\n"));
00254       fprintf (s, _(" The options are:\n\
00255   @<file>                      Read options from <file>\n\
00256   -h --help                    Print this help message\n\
00257   -V --version                 Print version information\n"));
00258     }
00259 
00260   list_supported_targets (program_name, s);
00261 
00262   if (REPORT_BUGS_TO[0] && help)
00263     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
00264 
00265   xexit (help ? 0 : 1);
00266 }
00267 
00268 /* Normalize a file name specified on the command line into a file
00269    name which we will use in an archive.  */
00270 
00271 static const char *
00272 normalize (const char *file, bfd *abfd)
00273 {
00274   const char *filename;
00275 
00276   if (full_pathname)
00277     return file;
00278 
00279   filename = strrchr (file, '/');
00280 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00281   {
00282     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
00283     char *bslash = strrchr (file, '\\');
00284     if (filename == NULL || (bslash != NULL && bslash > filename))
00285       filename = bslash;
00286     if (filename == NULL && file[0] != '\0' && file[1] == ':')
00287       filename = file + 1;
00288   }
00289 #endif
00290   if (filename != (char *) NULL)
00291     filename++;
00292   else
00293     filename = file;
00294 
00295   if (ar_truncate
00296       && abfd != NULL
00297       && strlen (filename) > abfd->xvec->ar_max_namelen)
00298     {
00299       char *s;
00300 
00301       /* Space leak.  */
00302       s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
00303       memcpy (s, filename, abfd->xvec->ar_max_namelen);
00304       s[abfd->xvec->ar_max_namelen] = '\0';
00305       filename = s;
00306     }
00307 
00308   return filename;
00309 }
00310 
00311 /* Remove any output file.  This is only called via xatexit.  */
00312 
00313 static const char *output_filename = NULL;
00314 static FILE *output_file = NULL;
00315 static bfd *output_bfd = NULL;
00316 
00317 static void
00318 remove_output (void)
00319 {
00320   if (output_filename != NULL)
00321     {
00322       if (output_bfd != NULL)
00323        bfd_cache_close (output_bfd);
00324       if (output_file != NULL)
00325        fclose (output_file);
00326       unlink_if_ordinary (output_filename);
00327     }
00328 }
00329 
00330 /* The option parsing should be in its own function.
00331    It will be when I have getopt working.  */
00332 
00333 int main (int, char **);
00334 
00335 int
00336 main (int argc, char **argv)
00337 {
00338   char *arg_ptr;
00339   char c;
00340   enum
00341     {
00342       none = 0, delete, replace, print_table,
00343       print_files, extract, move, quick_append
00344     } operation = none;
00345   int arg_index;
00346   char **files;
00347   int file_count;
00348   char *inarch_filename;
00349   int show_version;
00350   int i;
00351   int do_posix = 0;
00352 
00353 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
00354   setlocale (LC_MESSAGES, "");
00355 #endif
00356 #if defined (HAVE_SETLOCALE)
00357   setlocale (LC_CTYPE, "");
00358 #endif
00359   bindtextdomain (PACKAGE, LOCALEDIR);
00360   textdomain (PACKAGE);
00361 
00362   program_name = argv[0];
00363   xmalloc_set_program_name (program_name);
00364 
00365   expandargv (&argc, &argv);
00366 
00367   if (is_ranlib < 0)
00368     {
00369       char *temp;
00370 
00371       temp = strrchr (program_name, '/');
00372 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
00373       {
00374        /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
00375        char *bslash = strrchr (program_name, '\\');
00376        if (temp == NULL || (bslash != NULL && bslash > temp))
00377          temp = bslash;
00378        if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
00379          temp = program_name + 1;
00380       }
00381 #endif
00382       if (temp == NULL)
00383        temp = program_name;
00384       else
00385        ++temp;
00386       if (strlen (temp) >= 6
00387          && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
00388        is_ranlib = 1;
00389       else
00390        is_ranlib = 0;
00391     }
00392 
00393   if (argc > 1 && argv[1][0] == '-')
00394     {
00395       if (strcmp (argv[1], "--help") == 0)
00396        usage (1);
00397       else if (strcmp (argv[1], "--version") == 0)
00398        {
00399          if (is_ranlib)
00400            print_version ("ranlib");
00401          else
00402            print_version ("ar");
00403        }
00404     }
00405 
00406   START_PROGRESS (program_name, 0);
00407 
00408   bfd_init ();
00409   set_default_bfd_target ();
00410 
00411   show_version = 0;
00412 
00413   xatexit (remove_output);
00414 
00415   for (i = 1; i < argc; i++)
00416     if (! ar_emul_parse_arg (argv[i]))
00417       break;
00418   argv += (i - 1);
00419   argc -= (i - 1);
00420 
00421   if (is_ranlib)
00422     {
00423       int status = 0;
00424       bfd_boolean touch = FALSE;
00425 
00426       if (argc < 2
00427          || strcmp (argv[1], "--help") == 0
00428          || strcmp (argv[1], "-h") == 0
00429          || strcmp (argv[1], "-H") == 0)
00430        usage (0);
00431       if (strcmp (argv[1], "-V") == 0
00432          || strcmp (argv[1], "-v") == 0
00433          || CONST_STRNEQ (argv[1], "--v"))
00434        print_version ("ranlib");
00435       arg_index = 1;
00436       if (strcmp (argv[1], "-t") == 0)
00437        {
00438          ++arg_index;
00439          touch = TRUE;
00440        }
00441       while (arg_index < argc)
00442        {
00443          if (! touch)
00444            status |= ranlib_only (argv[arg_index]);
00445          else
00446            status |= ranlib_touch (argv[arg_index]);
00447          ++arg_index;
00448        }
00449       xexit (status);
00450     }
00451 
00452   if (argc == 2 && strcmp (argv[1], "-M") == 0)
00453     {
00454       mri_emul ();
00455       xexit (0);
00456     }
00457 
00458   if (argc < 2)
00459     usage (0);
00460 
00461   arg_index = 1;
00462   arg_ptr = argv[arg_index];
00463 
00464   if (*arg_ptr == '-')
00465     {
00466       /* When the first option starts with '-' we support POSIX-compatible
00467         option parsing.  */
00468       do_posix = 1;
00469       ++arg_ptr;                   /* compatibility */
00470     }
00471 
00472   do
00473     {
00474       while ((c = *arg_ptr++) != '\0')
00475        {
00476          switch (c)
00477            {
00478            case 'd':
00479            case 'm':
00480            case 'p':
00481            case 'q':
00482            case 'r':
00483            case 't':
00484            case 'x':
00485              if (operation != none)
00486               fatal (_("two different operation options specified"));
00487              switch (c)
00488               {
00489               case 'd':
00490                 operation = delete;
00491                 operation_alters_arch = TRUE;
00492                 break;
00493               case 'm':
00494                 operation = move;
00495                 operation_alters_arch = TRUE;
00496                 break;
00497               case 'p':
00498                 operation = print_files;
00499                 break;
00500               case 'q':
00501                 operation = quick_append;
00502                 operation_alters_arch = TRUE;
00503                 break;
00504               case 'r':
00505                 operation = replace;
00506                 operation_alters_arch = TRUE;
00507                 break;
00508               case 't':
00509                 operation = print_table;
00510                 break;
00511               case 'x':
00512                 operation = extract;
00513                 break;
00514               }
00515            case 'l':
00516              break;
00517            case 'c':
00518              silent_create = 1;
00519              break;
00520            case 'o':
00521              preserve_dates = 1;
00522              break;
00523            case 'V':
00524              show_version = TRUE;
00525              break;
00526            case 's':
00527              write_armap = 1;
00528              break;
00529            case 'S':
00530              write_armap = -1;
00531              break;
00532            case 'u':
00533              newer_only = 1;
00534              break;
00535            case 'v':
00536              verbose = 1;
00537              break;
00538            case 'a':
00539              postype = pos_after;
00540              break;
00541            case 'b':
00542              postype = pos_before;
00543              break;
00544            case 'i':
00545              postype = pos_before;
00546              break;
00547            case 'M':
00548              mri_mode = 1;
00549              break;
00550            case 'N':
00551              counted_name_mode = TRUE;
00552              break;
00553            case 'f':
00554              ar_truncate = TRUE;
00555              break;
00556            case 'P':
00557              full_pathname = TRUE;
00558              break;
00559            default:
00560              /* xgettext:c-format */
00561              non_fatal (_("illegal option -- %c"), c);
00562              usage (0);
00563            }
00564        }
00565 
00566       /* With POSIX-compatible option parsing continue with the next
00567         argument if it starts with '-'.  */
00568       if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
00569        arg_ptr = argv[++arg_index] + 1;
00570       else
00571        do_posix = 0;
00572     }
00573   while (do_posix);
00574 
00575   if (show_version)
00576     print_version ("ar");
00577 
00578   ++arg_index;
00579   if (arg_index >= argc)
00580     usage (0);
00581 
00582   if (mri_mode)
00583     {
00584       mri_emul ();
00585     }
00586   else
00587     {
00588       bfd *arch;
00589 
00590       /* We don't use do_quick_append any more.  Too many systems
00591         expect ar to always rebuild the symbol table even when q is
00592         used.  */
00593 
00594       /* We can't write an armap when using ar q, so just do ar r
00595          instead.  */
00596       if (operation == quick_append && write_armap)
00597        operation = replace;
00598 
00599       if ((operation == none || operation == print_table)
00600          && write_armap == 1)
00601        xexit (ranlib_only (argv[arg_index]));
00602 
00603       if (operation == none)
00604        fatal (_("no operation specified"));
00605 
00606       if (newer_only && operation != replace)
00607        fatal (_("`u' is only meaningful with the `r' option."));
00608 
00609       if (postype != pos_default)
00610        posname = argv[arg_index++];
00611 
00612       if (counted_name_mode)
00613        {
00614          if (operation != extract && operation != delete)
00615             fatal (_("`N' is only meaningful with the `x' and `d' options."));
00616          counted_name_counter = atoi (argv[arg_index++]);
00617          if (counted_name_counter <= 0)
00618            fatal (_("Value for `N' must be positive."));
00619        }
00620 
00621       inarch_filename = argv[arg_index++];
00622 
00623       files = arg_index < argc ? argv + arg_index : NULL;
00624       file_count = argc - arg_index;
00625 
00626       arch = open_inarch (inarch_filename,
00627                        files == NULL ? (char *) NULL : files[0]);
00628 
00629       switch (operation)
00630        {
00631        case print_table:
00632          map_over_members (arch, print_descr, files, file_count);
00633          break;
00634 
00635        case print_files:
00636          map_over_members (arch, print_contents, files, file_count);
00637          break;
00638 
00639        case extract:
00640          map_over_members (arch, extract_file, files, file_count);
00641          break;
00642 
00643        case delete:
00644          if (files != NULL)
00645            delete_members (arch, files);
00646          else
00647            output_filename = NULL;
00648          break;
00649 
00650        case move:
00651          if (files != NULL)
00652            move_members (arch, files);
00653          else
00654            output_filename = NULL;
00655          break;
00656 
00657        case replace:
00658        case quick_append:
00659          if (files != NULL || write_armap > 0)
00660            replace_members (arch, files, operation == quick_append);
00661          else
00662            output_filename = NULL;
00663          break;
00664 
00665          /* Shouldn't happen! */
00666        default:
00667          /* xgettext:c-format */
00668          fatal (_("internal error -- this option not implemented"));
00669        }
00670     }
00671 
00672   END_PROGRESS (program_name);
00673 
00674   xexit (0);
00675   return 0;
00676 }
00677 
00678 bfd *
00679 open_inarch (const char *archive_filename, const char *file)
00680 {
00681   const char *target;
00682   bfd **last_one;
00683   bfd *next_one;
00684   struct stat sbuf;
00685   bfd *arch;
00686   char **matching;
00687 
00688   bfd_set_error (bfd_error_no_error);
00689 
00690   target = NULL;
00691 
00692   if (stat (archive_filename, &sbuf) != 0)
00693     {
00694 #if !defined(__GO32__) || defined(__DJGPP__)
00695 
00696       /* FIXME: I don't understand why this fragment was ifndef'ed
00697         away for __GO32__; perhaps it was in the days of DJGPP v1.x.
00698         stat() works just fine in v2.x, so I think this should be
00699         removed.  For now, I enable it for DJGPP v2. -- EZ.  */
00700 
00701 /* KLUDGE ALERT! Temporary fix until I figger why
00702    stat() is wrong ... think it's buried in GO32's IDT - Jax */
00703       if (errno != ENOENT)
00704        bfd_fatal (archive_filename);
00705 #endif
00706 
00707       if (!operation_alters_arch)
00708        {
00709          fprintf (stderr, "%s: ", program_name);
00710          perror (archive_filename);
00711          maybequit ();
00712          return NULL;
00713        }
00714 
00715       /* Try to figure out the target to use for the archive from the
00716          first object on the list.  */
00717       if (file != NULL)
00718        {
00719          bfd *obj;
00720 
00721          obj = bfd_openr (file, NULL);
00722          if (obj != NULL)
00723            {
00724              if (bfd_check_format (obj, bfd_object))
00725               target = bfd_get_target (obj);
00726              (void) bfd_close (obj);
00727            }
00728        }
00729 
00730       /* Create an empty archive.  */
00731       arch = bfd_openw (archive_filename, target);
00732       if (arch == NULL
00733          || ! bfd_set_format (arch, bfd_archive)
00734          || ! bfd_close (arch))
00735        bfd_fatal (archive_filename);
00736       else if (!silent_create)
00737         non_fatal (_("creating %s"), archive_filename);
00738 
00739       /* If we die creating a new archive, don't leave it around.  */
00740       output_filename = archive_filename;
00741     }
00742 
00743   arch = bfd_openr (archive_filename, target);
00744   if (arch == NULL)
00745     {
00746     bloser:
00747       bfd_fatal (archive_filename);
00748     }
00749 
00750   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
00751     {
00752       bfd_nonfatal (archive_filename);
00753       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
00754        {
00755          list_matching_formats (matching);
00756          free (matching);
00757        }
00758       xexit (1);
00759     }
00760 
00761   last_one = &(arch->next);
00762   /* Read all the contents right away, regardless.  */
00763   for (next_one = bfd_openr_next_archived_file (arch, NULL);
00764        next_one;
00765        next_one = bfd_openr_next_archived_file (arch, next_one))
00766     {
00767       PROGRESS (1);
00768       *last_one = next_one;
00769       last_one = &next_one->next;
00770     }
00771   *last_one = (bfd *) NULL;
00772   if (bfd_get_error () != bfd_error_no_more_archived_files)
00773     goto bloser;
00774   return arch;
00775 }
00776 
00777 static void
00778 print_contents (bfd *abfd)
00779 {
00780   size_t ncopied = 0;
00781   char *cbuf = xmalloc (BUFSIZE);
00782   struct stat buf;
00783   size_t size;
00784   if (bfd_stat_arch_elt (abfd, &buf) != 0)
00785     /* xgettext:c-format */
00786     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
00787 
00788   if (verbose)
00789     /* xgettext:c-format */
00790     printf (_("\n<%s>\n\n"), bfd_get_filename (abfd));
00791 
00792   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
00793 
00794   size = buf.st_size;
00795   while (ncopied < size)
00796     {
00797 
00798       size_t nread;
00799       size_t tocopy = size - ncopied;
00800       if (tocopy > BUFSIZE)
00801        tocopy = BUFSIZE;
00802 
00803       nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
00804       if (nread != tocopy)
00805        /* xgettext:c-format */
00806        fatal (_("%s is not a valid archive"),
00807               bfd_get_filename (bfd_my_archive (abfd)));
00808 
00809       /* fwrite in mingw32 may return int instead of size_t. Cast the
00810         return value to size_t to avoid comparison between signed and
00811         unsigned values.  */
00812       if ((size_t) fwrite (cbuf, 1, nread, stdout) != nread)
00813        fatal ("stdout: %s", strerror (errno));
00814       ncopied += tocopy;
00815     }
00816   free (cbuf);
00817 }
00818 
00819 /* Extract a member of the archive into its own file.
00820 
00821    We defer opening the new file until after we have read a BUFSIZ chunk of the
00822    old one, since we know we have just read the archive header for the old
00823    one.  Since most members are shorter than BUFSIZ, this means we will read
00824    the old header, read the old data, write a new inode for the new file, and
00825    write the new data, and be done. This 'optimization' is what comes from
00826    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
00827    Gilmore  */
00828 
00829 void
00830 extract_file (bfd *abfd)
00831 {
00832   FILE *ostream;
00833   char *cbuf = xmalloc (BUFSIZE);
00834   size_t nread, tocopy;
00835   size_t ncopied = 0;
00836   size_t size;
00837   struct stat buf;
00838 
00839   if (bfd_stat_arch_elt (abfd, &buf) != 0)
00840     /* xgettext:c-format */
00841     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
00842   size = buf.st_size;
00843 
00844   if (verbose)
00845     printf ("x - %s\n", bfd_get_filename (abfd));
00846 
00847   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
00848 
00849   ostream = NULL;
00850   if (size == 0)
00851     {
00852       /* Seems like an abstraction violation, eh?  Well it's OK! */
00853       output_filename = bfd_get_filename (abfd);
00854 
00855       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
00856       if (ostream == NULL)
00857        {
00858          perror (bfd_get_filename (abfd));
00859          xexit (1);
00860        }
00861 
00862       output_file = ostream;
00863     }
00864   else
00865     while (ncopied < size)
00866       {
00867        tocopy = size - ncopied;
00868        if (tocopy > BUFSIZE)
00869          tocopy = BUFSIZE;
00870 
00871        nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
00872        if (nread != tocopy)
00873          /* xgettext:c-format */
00874          fatal (_("%s is not a valid archive"),
00875                bfd_get_filename (bfd_my_archive (abfd)));
00876 
00877        /* See comment above; this saves disk arm motion */
00878        if (ostream == NULL)
00879          {
00880            /* Seems like an abstraction violation, eh?  Well it's OK! */
00881            output_filename = bfd_get_filename (abfd);
00882 
00883            ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
00884            if (ostream == NULL)
00885              {
00886               perror (bfd_get_filename (abfd));
00887               xexit (1);
00888              }
00889 
00890            output_file = ostream;
00891          }
00892 
00893        /* fwrite in mingw32 may return int instead of size_t. Cast
00894           the return value to size_t to avoid comparison between
00895           signed and unsigned values.  */
00896        if ((size_t) fwrite (cbuf, 1, nread, ostream) != nread)
00897          fatal ("%s: %s", output_filename, strerror (errno));
00898        ncopied += tocopy;
00899       }
00900 
00901   if (ostream != NULL)
00902     fclose (ostream);
00903 
00904   output_file = NULL;
00905   output_filename = NULL;
00906 
00907   chmod (bfd_get_filename (abfd), buf.st_mode);
00908 
00909   if (preserve_dates)
00910     {
00911       /* Set access time to modification time.  Only st_mtime is
00912         initialized by bfd_stat_arch_elt.  */
00913       buf.st_atime = buf.st_mtime;
00914       set_times (bfd_get_filename (abfd), &buf);
00915     }
00916 
00917   free (cbuf);
00918 }
00919 
00920 static void
00921 write_archive (bfd *iarch)
00922 {
00923   bfd *obfd;
00924   char *old_name, *new_name;
00925   bfd *contents_head = iarch->next;
00926 
00927   old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
00928   strcpy (old_name, bfd_get_filename (iarch));
00929   new_name = make_tempname (old_name);
00930 
00931   if (new_name == NULL)
00932     bfd_fatal ("could not create temporary file whilst writing archive");
00933   
00934   output_filename = new_name;
00935 
00936   obfd = bfd_openw (new_name, bfd_get_target (iarch));
00937 
00938   if (obfd == NULL)
00939     bfd_fatal (old_name);
00940 
00941   output_bfd = obfd;
00942 
00943   bfd_set_format (obfd, bfd_archive);
00944 
00945   /* Request writing the archive symbol table unless we've
00946      been explicitly requested not to.  */
00947   obfd->has_armap = write_armap >= 0;
00948 
00949   if (ar_truncate)
00950     {
00951       /* This should really use bfd_set_file_flags, but that rejects
00952          archives.  */
00953       obfd->flags |= BFD_TRADITIONAL_FORMAT;
00954     }
00955 
00956   if (!bfd_set_archive_head (obfd, contents_head))
00957     bfd_fatal (old_name);
00958 
00959   if (!bfd_close (obfd))
00960     bfd_fatal (old_name);
00961 
00962   output_bfd = NULL;
00963   output_filename = NULL;
00964 
00965   /* We don't care if this fails; we might be creating the archive.  */
00966   bfd_close (iarch);
00967 
00968   if (smart_rename (new_name, old_name, 0) != 0)
00969     xexit (1);
00970 }
00971 
00972 /* Return a pointer to the pointer to the entry which should be rplacd'd
00973    into when altering.  DEFAULT_POS should be how to interpret pos_default,
00974    and should be a pos value.  */
00975 
00976 static bfd **
00977 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
00978 {
00979   bfd **after_bfd = contents;
00980   enum pos realpos;
00981   const char *realposname;
00982 
00983   if (postype == pos_default)
00984     {
00985       realpos = default_pos;
00986       realposname = default_posname;
00987     }
00988   else
00989     {
00990       realpos = postype;
00991       realposname = posname;
00992     }
00993 
00994   if (realpos == pos_end)
00995     {
00996       while (*after_bfd)
00997        after_bfd = &((*after_bfd)->next);
00998     }
00999   else
01000     {
01001       for (; *after_bfd; after_bfd = &(*after_bfd)->next)
01002        if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
01003          {
01004            if (realpos == pos_after)
01005              after_bfd = &(*after_bfd)->next;
01006            break;
01007          }
01008     }
01009   return after_bfd;
01010 }
01011 
01012 static void
01013 delete_members (bfd *arch, char **files_to_delete)
01014 {
01015   bfd **current_ptr_ptr;
01016   bfd_boolean found;
01017   bfd_boolean something_changed = FALSE;
01018   int match_count;
01019 
01020   for (; *files_to_delete != NULL; ++files_to_delete)
01021     {
01022       /* In a.out systems, the armap is optional.  It's also called
01023         __.SYMDEF.  So if the user asked to delete it, we should remember
01024         that fact. This isn't quite right for COFF systems (where
01025         __.SYMDEF might be regular member), but it's very unlikely
01026         to be a problem.  FIXME */
01027 
01028       if (!strcmp (*files_to_delete, "__.SYMDEF"))
01029        {
01030          arch->has_armap = FALSE;
01031          write_armap = -1;
01032          continue;
01033        }
01034 
01035       found = FALSE;
01036       match_count = 0;
01037       current_ptr_ptr = &(arch->next);
01038       while (*current_ptr_ptr)
01039        {
01040          if (FILENAME_CMP (normalize (*files_to_delete, arch),
01041                          (*current_ptr_ptr)->filename) == 0)
01042            {
01043              ++match_count;
01044              if (counted_name_mode
01045                 && match_count != counted_name_counter)
01046               {
01047                 /* Counting, and didn't match on count; go on to the
01048                      next one.  */
01049               }
01050              else
01051               {
01052                 found = TRUE;
01053                 something_changed = TRUE;
01054                 if (verbose)
01055                   printf ("d - %s\n",
01056                          *files_to_delete);
01057                 *current_ptr_ptr = ((*current_ptr_ptr)->next);
01058                 goto next_file;
01059               }
01060            }
01061 
01062          current_ptr_ptr = &((*current_ptr_ptr)->next);
01063        }
01064 
01065       if (verbose && !found)
01066        {
01067          /* xgettext:c-format */
01068          printf (_("No member named `%s'\n"), *files_to_delete);
01069        }
01070     next_file:
01071       ;
01072     }
01073 
01074   if (something_changed)
01075     write_archive (arch);
01076   else
01077     output_filename = NULL;
01078 }
01079 
01080 
01081 /* Reposition existing members within an archive */
01082 
01083 static void
01084 move_members (bfd *arch, char **files_to_move)
01085 {
01086   bfd **after_bfd;          /* New entries go after this one */
01087   bfd **current_ptr_ptr;    /* cdr pointer into contents */
01088 
01089   for (; *files_to_move; ++files_to_move)
01090     {
01091       current_ptr_ptr = &(arch->next);
01092       while (*current_ptr_ptr)
01093        {
01094          bfd *current_ptr = *current_ptr_ptr;
01095          if (FILENAME_CMP (normalize (*files_to_move, arch),
01096                          current_ptr->filename) == 0)
01097            {
01098              /* Move this file to the end of the list - first cut from
01099                where it is.  */
01100              bfd *link;
01101              *current_ptr_ptr = current_ptr->next;
01102 
01103              /* Now glue to end */
01104              after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
01105              link = *after_bfd;
01106              *after_bfd = current_ptr;
01107              current_ptr->next = link;
01108 
01109              if (verbose)
01110               printf ("m - %s\n", *files_to_move);
01111 
01112              goto next_file;
01113            }
01114 
01115          current_ptr_ptr = &((*current_ptr_ptr)->next);
01116        }
01117       /* xgettext:c-format */
01118       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
01119 
01120     next_file:;
01121     }
01122 
01123   write_archive (arch);
01124 }
01125 
01126 /* Ought to default to replacing in place, but this is existing practice!  */
01127 
01128 static void
01129 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
01130 {
01131   bfd_boolean changed = FALSE;
01132   bfd **after_bfd;          /* New entries go after this one.  */
01133   bfd *current;
01134   bfd **current_ptr;
01135 
01136   while (files_to_move && *files_to_move)
01137     {
01138       if (! quick)
01139        {
01140          current_ptr = &arch->next;
01141          while (*current_ptr)
01142            {
01143              current = *current_ptr;
01144 
01145              /* For compatibility with existing ar programs, we
01146                permit the same file to be added multiple times.  */
01147              if (FILENAME_CMP (normalize (*files_to_move, arch),
01148                             normalize (current->filename, arch)) == 0
01149                 && current->arelt_data != NULL)
01150               {
01151                 if (newer_only)
01152                   {
01153                     struct stat fsbuf, asbuf;
01154 
01155                     if (stat (*files_to_move, &fsbuf) != 0)
01156                      {
01157                        if (errno != ENOENT)
01158                          bfd_fatal (*files_to_move);
01159                        goto next_file;
01160                      }
01161                     if (bfd_stat_arch_elt (current, &asbuf) != 0)
01162                      /* xgettext:c-format */
01163                      fatal (_("internal stat error on %s"),
01164                             current->filename);
01165 
01166                     if (fsbuf.st_mtime <= asbuf.st_mtime)
01167                      goto next_file;
01168                   }
01169 
01170                 after_bfd = get_pos_bfd (&arch->next, pos_after,
01171                                       current->filename);
01172                 if (ar_emul_replace (after_bfd, *files_to_move,
01173                                    verbose))
01174                   {
01175                     /* Snip out this entry from the chain.  */
01176                     *current_ptr = (*current_ptr)->next;
01177                     changed = TRUE;
01178                   }
01179 
01180                 goto next_file;
01181               }
01182              current_ptr = &(current->next);
01183            }
01184        }
01185 
01186       /* Add to the end of the archive.  */
01187       after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
01188 
01189       if (ar_emul_append (after_bfd, *files_to_move, verbose))
01190        changed = TRUE;
01191 
01192     next_file:;
01193 
01194       files_to_move++;
01195     }
01196 
01197   if (changed)
01198     write_archive (arch);
01199   else
01200     output_filename = NULL;
01201 }
01202 
01203 static int
01204 ranlib_only (const char *archname)
01205 {
01206   bfd *arch;
01207 
01208   if (get_file_size (archname) < 1)
01209     return 1;
01210   write_armap = 1;
01211   arch = open_inarch (archname, (char *) NULL);
01212   if (arch == NULL)
01213     xexit (1);
01214   write_archive (arch);
01215   return 0;
01216 }
01217 
01218 /* Update the timestamp of the symbol map of an archive.  */
01219 
01220 static int
01221 ranlib_touch (const char *archname)
01222 {
01223 #ifdef __GO32__
01224   /* I don't think updating works on go32.  */
01225   ranlib_only (archname);
01226 #else
01227   int f;
01228   bfd *arch;
01229   char **matching;
01230 
01231   if (get_file_size (archname) < 1)
01232     return 1;
01233   f = open (archname, O_RDWR | O_BINARY, 0);
01234   if (f < 0)
01235     {
01236       bfd_set_error (bfd_error_system_call);
01237       bfd_fatal (archname);
01238     }
01239 
01240   arch = bfd_fdopenr (archname, (const char *) NULL, f);
01241   if (arch == NULL)
01242     bfd_fatal (archname);
01243   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
01244     {
01245       bfd_nonfatal (archname);
01246       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
01247        {
01248          list_matching_formats (matching);
01249          free (matching);
01250        }
01251       xexit (1);
01252     }
01253 
01254   if (! bfd_has_map (arch))
01255     /* xgettext:c-format */
01256     fatal (_("%s: no archive map to update"), archname);
01257 
01258   bfd_update_armap_timestamp (arch);
01259 
01260   if (! bfd_close (arch))
01261     bfd_fatal (archname);
01262 #endif
01263   return 0;
01264 }
01265 
01266 /* Things which are interesting to map over all or some of the files: */
01267 
01268 static void
01269 print_descr (bfd *abfd)
01270 {
01271   print_arelt_descr (stdout, abfd, verbose);
01272 }