Home | History | Annotate | Download | only in binutils
      1 /* ar.c - Archive modify and extract.
      2    Copyright (C) 1991-2014 Free Software Foundation, Inc.
      3 
      4    This file is part of GNU Binutils.
      5 
      6    This program is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3 of the License, or
      9    (at your option) any later version.
     10 
     11    This program is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with this program; if not, write to the Free Software
     18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
     19    MA 02110-1301, USA.  */
     20 
     21 /*
     23    Bugs: GNU ar used to check file against filesystem in quick_update and
     24    replace operations (would check mtime). Doesn't warn when name truncated.
     25    No way to specify pos_end. Error messages should be more consistent.  */
     26 
     27 #include "sysdep.h"
     28 #include "bfd.h"
     29 #include "libiberty.h"
     30 #include "progress.h"
     31 #include "getopt.h"
     32 #include "aout/ar.h"
     33 #include "libbfd.h"
     34 #include "bucomm.h"
     35 #include "arsup.h"
     36 #include "filenames.h"
     37 #include "binemul.h"
     38 #include "plugin.h"
     39 
     40 #ifdef __GO32___
     41 #define EXT_NAME_LEN 3		/* Bufflen of addition to name if it's MS-DOS.  */
     42 #else
     43 #define EXT_NAME_LEN 6		/* Ditto for *NIX.  */
     44 #endif
     45 
     46 /* Static declarations.  */
     47 
     48 static void mri_emul (void);
     49 static const char *normalize (const char *, bfd *);
     50 static void remove_output (void);
     51 static void map_over_members (bfd *, void (*)(bfd *), char **, int);
     52 static void print_contents (bfd * member);
     53 static void delete_members (bfd *, char **files_to_delete);
     54 
     55 static void move_members (bfd *, char **files_to_move);
     56 static void replace_members
     57   (bfd *, char **files_to_replace, bfd_boolean quick);
     58 static void print_descr (bfd * abfd);
     59 static void write_archive (bfd *);
     60 static int  ranlib_only (const char *archname);
     61 static int  ranlib_touch (const char *archname);
     62 static void usage (int);
     63 
     64 /** Globals and flags.  */
     66 
     67 static int mri_mode;
     68 
     69 /* This flag distinguishes between ar and ranlib:
     70    1 means this is 'ranlib'; 0 means this is 'ar'.
     71    -1 means if we should use argv[0] to decide.  */
     72 extern int is_ranlib;
     73 
     74 /* Nonzero means don't warn about creating the archive file if necessary.  */
     75 int silent_create = 0;
     76 
     77 /* Nonzero means describe each action performed.  */
     78 int verbose = 0;
     79 
     80 /* Nonzero means preserve dates of members when extracting them.  */
     81 int preserve_dates = 0;
     82 
     83 /* Nonzero means don't replace existing members whose dates are more recent
     84    than the corresponding files.  */
     85 int newer_only = 0;
     86 
     87 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
     88    member).  -1 means we've been explicitly asked to not write a symbol table;
     89    +1 means we've been explicitly asked to write it;
     90    0 is the default.
     91    Traditionally, the default in BSD has been to not write the table.
     92    However, for POSIX.2 compliance the default is now to write a symbol table
     93    if any of the members are object files.  */
     94 int write_armap = 0;
     95 
     96 /* Operate in deterministic mode: write zero for timestamps, uids,
     97    and gids for archive members and the archive symbol table, and write
     98    consistent file modes.  */
     99 int deterministic = -1;			/* Determinism indeterminate.  */
    100 
    101 /* Nonzero means it's the name of an existing member; position new or moved
    102    files with respect to this one.  */
    103 char *posname = NULL;
    104 
    105 /* Sez how to use `posname': pos_before means position before that member.
    106    pos_after means position after that member. pos_end means always at end.
    107    pos_default means default appropriately. For the latter two, `posname'
    108    should also be zero.  */
    109 enum pos
    110   {
    111     pos_default, pos_before, pos_after, pos_end
    112   } postype = pos_default;
    113 
    114 enum operations
    115   {
    116     none = 0, del, replace, print_table,
    117     print_files, extract, move, quick_append
    118   } operation = none;
    119 
    120 static bfd **
    121 get_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.  */
    125 static bfd_boolean counted_name_mode = 0;
    126 static int counted_name_counter = 0;
    127 
    128 /* Whether to truncate names of files stored in the archive.  */
    129 static 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.  */
    134 static bfd_boolean full_pathname = FALSE;
    135 
    136 /* Whether to create a "thin" archive (symbol index only -- no files).  */
    137 static bfd_boolean make_thin_archive = FALSE;
    138 
    139 static int show_version = 0;
    140 
    141 static int show_help = 0;
    142 
    143 #if BFD_SUPPORTS_PLUGINS
    144 static const char *plugin_target = "plugin";
    145 #else
    146 static const char *plugin_target = NULL;
    147 #endif
    148 
    149 static const char *target = NULL;
    150 
    151 #define OPTION_PLUGIN 201
    152 #define OPTION_TARGET 202
    153 
    154 static struct option long_options[] =
    155 {
    156   {"help", no_argument, &show_help, 1},
    157   {"plugin", required_argument, NULL, OPTION_PLUGIN},
    158   {"target", required_argument, NULL, OPTION_TARGET},
    159   {"version", no_argument, &show_version, 1},
    160   {NULL, no_argument, NULL, 0}
    161 };
    162 
    163 int interactive = 0;
    164 
    165 static void
    166 mri_emul (void)
    167 {
    168   interactive = isatty (fileno (stdin));
    169   yyparse ();
    170 }
    171 
    172 /* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
    173    COUNT is the length of the FILES chain; FUNCTION is called on each entry
    174    whose name matches one in FILES.  */
    175 
    176 static void
    177 map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
    178 {
    179   bfd *head;
    180   int match_count;
    181 
    182   if (count == 0)
    183     {
    184       for (head = arch->archive_next; head; head = head->archive_next)
    185 	{
    186 	  PROGRESS (1);
    187 	  function (head);
    188 	}
    189       return;
    190     }
    191 
    192   /* This may appear to be a baroque way of accomplishing what we want.
    193      However we have to iterate over the filenames in order to notice where
    194      a filename is requested but does not exist in the archive.  Ditto
    195      mapping over each file each time -- we want to hack multiple
    196      references.  */
    197 
    198   for (head = arch->archive_next; head; head = head->archive_next)
    199     head->archive_pass = 0;
    200 
    201   for (; count > 0; files++, count--)
    202     {
    203       bfd_boolean found = FALSE;
    204 
    205       match_count = 0;
    206       for (head = arch->archive_next; head; head = head->archive_next)
    207 	{
    208 	  const char * filename;
    209 
    210 	  PROGRESS (1);
    211 	  /* PR binutils/15796: Once an archive element has been matched
    212 	     do not match it again.  If the user provides multiple same-named
    213 	     parameters on the command line their intent is to match multiple
    214 	     same-named entries in the archive, not the same entry multiple
    215 	     times.  */
    216 	  if (head->archive_pass)
    217 	    continue;
    218 
    219 	  filename = head->filename;
    220 	  if (filename == NULL)
    221 	    {
    222 	      /* Some archive formats don't get the filenames filled in
    223 		 until the elements are opened.  */
    224 	      struct stat buf;
    225 	      bfd_stat_arch_elt (head, &buf);
    226 	    }
    227 	  else if (bfd_is_thin_archive (arch))
    228 	    {
    229 	      /* Thin archives store full pathnames.  Need to normalize.  */
    230 	      filename = normalize (filename, arch);
    231 	    }
    232 
    233 	  if (filename != NULL
    234 	      && !FILENAME_CMP (normalize (*files, arch), filename))
    235 	    {
    236 	      ++match_count;
    237 	      if (counted_name_mode
    238 		  && match_count != counted_name_counter)
    239 		{
    240 		  /* Counting, and didn't match on count; go on to the
    241                      next one.  */
    242 		  continue;
    243 		}
    244 
    245 	      found = TRUE;
    246 	      function (head);
    247 	      head->archive_pass = 1;
    248 	      /* PR binutils/15796: Once a file has been matched, do not
    249 		 match any more same-named files in the archive.  If the
    250 		 user does want to match multiple same-name files in an
    251 		 archive they should provide multiple same-name parameters
    252 		 to the ar command.  */
    253 	      break;
    254 	    }
    255 	}
    256 
    257       if (!found)
    258 	/* xgettext:c-format */
    259 	fprintf (stderr, _("no entry %s in archive\n"), *files);
    260     }
    261 }
    262 
    263 bfd_boolean operation_alters_arch = FALSE;
    265 
    266 static void
    267 usage (int help)
    268 {
    269   FILE *s;
    270 
    271 #if BFD_SUPPORTS_PLUGINS
    272   /* xgettext:c-format */
    273   const char *command_line
    274     = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilMNoPsSTuvV]"
    275 	" [--plugin <name>] [member-name] [count] archive-file file...\n");
    276 
    277 #else
    278   /* xgettext:c-format */
    279   const char *command_line
    280     = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilMNoPsSTuvV]"
    281 	" [member-name] [count] archive-file file...\n");
    282 #endif
    283   s = help ? stdout : stderr;
    284 
    285   fprintf (s, command_line, program_name);
    286 
    287   /* xgettext:c-format */
    288   fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
    289   fprintf (s, _(" commands:\n"));
    290   fprintf (s, _("  d            - delete file(s) from the archive\n"));
    291   fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
    292   fprintf (s, _("  p            - print file(s) found in the archive\n"));
    293   fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
    294   fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
    295   fprintf (s, _("  s            - act as ranlib\n"));
    296   fprintf (s, _("  t            - display contents of archive\n"));
    297   fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
    298   fprintf (s, _(" command specific modifiers:\n"));
    299   fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
    300   fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
    301   if (DEFAULT_AR_DETERMINISTIC)
    302     {
    303       fprintf (s, _("\
    304   [D]          - use zero for timestamps and uids/gids (default)\n"));
    305       fprintf (s, _("\
    306   [U]          - use actual timestamps and uids/gids\n"));
    307     }
    308   else
    309     {
    310       fprintf (s, _("\
    311   [D]          - use zero for timestamps and uids/gids\n"));
    312       fprintf (s, _("\
    313   [U]          - use actual timestamps and uids/gids (default)\n"));
    314     }
    315   fprintf (s, _("  [N]          - use instance [count] of name\n"));
    316   fprintf (s, _("  [f]          - truncate inserted file names\n"));
    317   fprintf (s, _("  [P]          - use full path names when matching\n"));
    318   fprintf (s, _("  [o]          - preserve original dates\n"));
    319   fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
    320   fprintf (s, _(" generic modifiers:\n"));
    321   fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
    322   fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
    323   fprintf (s, _("  [S]          - do not build a symbol table\n"));
    324   fprintf (s, _("  [T]          - make a thin archive\n"));
    325   fprintf (s, _("  [v]          - be verbose\n"));
    326   fprintf (s, _("  [V]          - display the version number\n"));
    327   fprintf (s, _("  @<file>      - read options from <file>\n"));
    328   fprintf (s, _("  --target=BFDNAME - specify the target object format as BFDNAME\n"));
    329 #if BFD_SUPPORTS_PLUGINS
    330   fprintf (s, _(" optional:\n"));
    331   fprintf (s, _("  --plugin <p> - load the specified plugin\n"));
    332 #endif
    333 
    334   ar_emul_usage (s);
    335 
    336   list_supported_targets (program_name, s);
    337 
    338   if (REPORT_BUGS_TO[0] && help)
    339     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
    340 
    341   xexit (help ? 0 : 1);
    342 }
    343 
    344 static void
    345 ranlib_usage (int help)
    346 {
    347   FILE *s;
    348 
    349   s = help ? stdout : stderr;
    350 
    351   /* xgettext:c-format */
    352   fprintf (s, _("Usage: %s [options] archive\n"), program_name);
    353   fprintf (s, _(" Generate an index to speed access to archives\n"));
    354   fprintf (s, _(" The options are:\n\
    355   @<file>                      Read options from <file>\n"));
    356 #if BFD_SUPPORTS_PLUGINS
    357   fprintf (s, _("\
    358   --plugin <name>              Load the specified plugin\n"));
    359 #endif
    360   if (DEFAULT_AR_DETERMINISTIC)
    361     fprintf (s, _("\
    362   -D                           Use zero for symbol map timestamp (default)\n\
    363   -U                           Use an actual symbol map timestamp\n"));
    364   else
    365     fprintf (s, _("\
    366   -D                           Use zero for symbol map timestamp\n\
    367   -U                           Use actual symbol map timestamp (default)\n"));
    368   fprintf (s, _("\
    369   -t                           Update the archive's symbol map timestamp\n\
    370   -h --help                    Print this help message\n\
    371   -v --version                 Print version information\n"));
    372 
    373   list_supported_targets (program_name, s);
    374 
    375   if (REPORT_BUGS_TO[0] && help)
    376     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
    377 
    378   xexit (help ? 0 : 1);
    379 }
    380 
    381 /* Normalize a file name specified on the command line into a file
    382    name which we will use in an archive.  */
    383 
    384 static const char *
    385 normalize (const char *file, bfd *abfd)
    386 {
    387   const char *filename;
    388 
    389   if (full_pathname)
    390     return file;
    391 
    392   filename = lbasename (file);
    393 
    394   if (ar_truncate
    395       && abfd != NULL
    396       && strlen (filename) > abfd->xvec->ar_max_namelen)
    397     {
    398       char *s;
    399 
    400       /* Space leak.  */
    401       s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
    402       memcpy (s, filename, abfd->xvec->ar_max_namelen);
    403       s[abfd->xvec->ar_max_namelen] = '\0';
    404       filename = s;
    405     }
    406 
    407   return filename;
    408 }
    409 
    410 /* Remove any output file.  This is only called via xatexit.  */
    411 
    412 static const char *output_filename = NULL;
    413 static FILE *output_file = NULL;
    414 static bfd *output_bfd = NULL;
    415 
    416 static void
    417 remove_output (void)
    418 {
    419   if (output_filename != NULL)
    420     {
    421       if (output_bfd != NULL)
    422 	bfd_cache_close (output_bfd);
    423       if (output_file != NULL)
    424 	fclose (output_file);
    425       unlink_if_ordinary (output_filename);
    426     }
    427 }
    428 
    429 static char **
    430 decode_options (int argc, char **argv)
    431 {
    432   int c;
    433 
    434   /* Convert old-style tar call by exploding option element and rearranging
    435      options accordingly.  */
    436 
    437   if (argc > 1 && argv[1][0] != '-')
    438     {
    439       int new_argc;		/* argc value for rearranged arguments */
    440       char **new_argv;		/* argv value for rearranged arguments */
    441       char *const *in;		/* cursor into original argv */
    442       char **out;		/* cursor into rearranged argv */
    443       const char *letter;	/* cursor into old option letters */
    444       char buffer[3];		/* constructed option buffer */
    445 
    446       /* Initialize a constructed option.  */
    447 
    448       buffer[0] = '-';
    449       buffer[2] = '\0';
    450 
    451       /* Allocate a new argument array, and copy program name in it.  */
    452 
    453       new_argc = argc - 1 + strlen (argv[1]);
    454       new_argv = xmalloc ((new_argc + 1) * sizeof (*argv));
    455       in = argv;
    456       out = new_argv;
    457       *out++ = *in++;
    458 
    459       /* Copy each old letter option as a separate option.  */
    460 
    461       for (letter = *in++; *letter; letter++)
    462 	{
    463 	  buffer[1] = *letter;
    464 	  *out++ = xstrdup (buffer);
    465 	}
    466 
    467       /* Copy all remaining options.  */
    468 
    469       while (in < argv + argc)
    470 	*out++ = *in++;
    471       *out = NULL;
    472 
    473       /* Replace the old option list by the new one.  */
    474 
    475       argc = new_argc;
    476       argv = new_argv;
    477     }
    478 
    479   while ((c = getopt_long (argc, argv, "hdmpqrtxlcoVsSuvabiMNfPTDU",
    480 			   long_options, NULL)) != EOF)
    481     {
    482       switch (c)
    483         {
    484         case 'd':
    485         case 'm':
    486         case 'p':
    487         case 'q':
    488         case 'r':
    489         case 't':
    490         case 'x':
    491           if (operation != none)
    492             fatal (_("two different operation options specified"));
    493 	  break;
    494 	}
    495 
    496       switch (c)
    497         {
    498         case 'h':
    499 	  show_help = 1;
    500 	  break;
    501         case 'd':
    502           operation = del;
    503           operation_alters_arch = TRUE;
    504           break;
    505         case 'm':
    506           operation = move;
    507           operation_alters_arch = TRUE;
    508           break;
    509         case 'p':
    510           operation = print_files;
    511           break;
    512         case 'q':
    513           operation = quick_append;
    514           operation_alters_arch = TRUE;
    515           break;
    516         case 'r':
    517           operation = replace;
    518           operation_alters_arch = TRUE;
    519           break;
    520         case 't':
    521           operation = print_table;
    522           break;
    523         case 'x':
    524           operation = extract;
    525           break;
    526         case 'l':
    527           break;
    528         case 'c':
    529           silent_create = 1;
    530           break;
    531         case 'o':
    532           preserve_dates = 1;
    533           break;
    534         case 'V':
    535           show_version = TRUE;
    536           break;
    537         case 's':
    538           write_armap = 1;
    539           break;
    540         case 'S':
    541           write_armap = -1;
    542           break;
    543         case 'u':
    544           newer_only = 1;
    545           break;
    546         case 'v':
    547           verbose = 1;
    548           break;
    549         case 'a':
    550           postype = pos_after;
    551           break;
    552         case 'b':
    553           postype = pos_before;
    554           break;
    555         case 'i':
    556           postype = pos_before;
    557           break;
    558         case 'M':
    559           mri_mode = 1;
    560           break;
    561         case 'N':
    562           counted_name_mode = TRUE;
    563           break;
    564         case 'f':
    565           ar_truncate = TRUE;
    566           break;
    567         case 'P':
    568           full_pathname = TRUE;
    569           break;
    570         case 'T':
    571           make_thin_archive = TRUE;
    572           break;
    573         case 'D':
    574           deterministic = TRUE;
    575           break;
    576         case 'U':
    577           deterministic = FALSE;
    578           break;
    579 	case OPTION_PLUGIN:
    580 #if BFD_SUPPORTS_PLUGINS
    581 	  bfd_plugin_set_plugin (optarg);
    582 #else
    583 	  fprintf (stderr, _("sorry - this program has been built without plugin support\n"));
    584 	  xexit (1);
    585 #endif
    586 	  break;
    587 	case OPTION_TARGET:
    588 	  target = optarg;
    589 	  break;
    590 	case 0:		/* A long option that just sets a flag.  */
    591 	  break;
    592         default:
    593           usage (0);
    594         }
    595     }
    596 
    597   return &argv[optind];
    598 }
    599 
    600 /* If neither -D nor -U was specified explicitly,
    601    then use the configured default.  */
    602 static void
    603 default_deterministic (void)
    604 {
    605   if (deterministic < 0)
    606     deterministic = DEFAULT_AR_DETERMINISTIC;
    607 }
    608 
    609 static void
    610 ranlib_main (int argc, char **argv)
    611 {
    612   int arg_index, status = 0;
    613   bfd_boolean touch = FALSE;
    614   int c;
    615 
    616   while ((c = getopt_long (argc, argv, "DhHUvVt", long_options, NULL)) != EOF)
    617     {
    618       switch (c)
    619         {
    620 	case 'D':
    621 	  deterministic = TRUE;
    622 	  break;
    623         case 'U':
    624           deterministic = FALSE;
    625           break;
    626 	case 'h':
    627 	case 'H':
    628 	  show_help = 1;
    629 	  break;
    630 	case 't':
    631 	  touch = TRUE;
    632 	  break;
    633 	case 'v':
    634 	case 'V':
    635 	  show_version = 1;
    636 	  break;
    637 
    638 	  /* PR binutils/13493: Support plugins.  */
    639 	case OPTION_PLUGIN:
    640 #if BFD_SUPPORTS_PLUGINS
    641 	  bfd_plugin_set_plugin (optarg);
    642 #else
    643 	  fprintf (stderr, _("sorry - this program has been built without plugin support\n"));
    644 	  xexit (1);
    645 #endif
    646 	  break;
    647 	}
    648     }
    649 
    650   if (argc < 2)
    651     ranlib_usage (0);
    652 
    653   if (show_help)
    654     ranlib_usage (1);
    655 
    656   if (show_version)
    657     print_version ("ranlib");
    658 
    659   default_deterministic ();
    660 
    661   arg_index = optind;
    662 
    663   while (arg_index < argc)
    664     {
    665       if (! touch)
    666         status |= ranlib_only (argv[arg_index]);
    667       else
    668         status |= ranlib_touch (argv[arg_index]);
    669       ++arg_index;
    670     }
    671 
    672   xexit (status);
    673 }
    674 
    675 int main (int, char **);
    676 
    677 int
    678 main (int argc, char **argv)
    679 {
    680   int arg_index;
    681   char **files;
    682   int file_count;
    683   char *inarch_filename;
    684   int i;
    685 
    686 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
    687   setlocale (LC_MESSAGES, "");
    688 #endif
    689 #if defined (HAVE_SETLOCALE)
    690   setlocale (LC_CTYPE, "");
    691 #endif
    692   bindtextdomain (PACKAGE, LOCALEDIR);
    693   textdomain (PACKAGE);
    694 
    695   program_name = argv[0];
    696   xmalloc_set_program_name (program_name);
    697 #if BFD_SUPPORTS_PLUGINS
    698   bfd_plugin_set_program_name (program_name);
    699 #endif
    700 
    701   expandargv (&argc, &argv);
    702 
    703   if (is_ranlib < 0)
    704     {
    705       const char *temp = lbasename (program_name);
    706 
    707       if (strlen (temp) >= 6
    708 	  && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
    709 	is_ranlib = 1;
    710       else
    711 	is_ranlib = 0;
    712     }
    713 
    714   START_PROGRESS (program_name, 0);
    715 
    716   bfd_init ();
    717   set_default_bfd_target ();
    718 
    719   xatexit (remove_output);
    720 
    721   for (i = 1; i < argc; i++)
    722     if (! ar_emul_parse_arg (argv[i]))
    723       break;
    724   argv += (i - 1);
    725   argc -= (i - 1);
    726 
    727   if (is_ranlib)
    728     ranlib_main (argc, argv);
    729 
    730   if (argc < 2)
    731     usage (0);
    732 
    733   argv = decode_options (argc, argv);
    734 
    735   if (show_help)
    736     usage (1);
    737 
    738   if (show_version)
    739     print_version ("ar");
    740 
    741   arg_index = 0;
    742 
    743   if (mri_mode)
    744     {
    745       default_deterministic ();
    746       mri_emul ();
    747     }
    748   else
    749     {
    750       bfd *arch;
    751 
    752       /* We don't use do_quick_append any more.  Too many systems
    753 	 expect ar to always rebuild the symbol table even when q is
    754 	 used.  */
    755 
    756       /* We can't write an armap when using ar q, so just do ar r
    757          instead.  */
    758       if (operation == quick_append && write_armap)
    759 	operation = replace;
    760 
    761       if ((operation == none || operation == print_table)
    762 	  && write_armap == 1)
    763 	xexit (ranlib_only (argv[arg_index]));
    764 
    765       if (operation == none)
    766 	fatal (_("no operation specified"));
    767 
    768       if (newer_only && operation != replace)
    769 	fatal (_("`u' is only meaningful with the `r' option."));
    770 
    771       if (newer_only && deterministic > 0)
    772         fatal (_("`u' is not meaningful with the `D' option."));
    773 
    774       if (newer_only && deterministic < 0 && DEFAULT_AR_DETERMINISTIC)
    775         non_fatal (_("\
    776 `u' modifier ignored since `D' is the default (see `U')"));
    777 
    778       default_deterministic ();
    779 
    780       if (postype != pos_default)
    781 	posname = argv[arg_index++];
    782 
    783       if (counted_name_mode)
    784 	{
    785 	  if (operation != extract && operation != del)
    786 	    fatal (_("`N' is only meaningful with the `x' and `d' options."));
    787 	  counted_name_counter = atoi (argv[arg_index++]);
    788 	  if (counted_name_counter <= 0)
    789 	    fatal (_("Value for `N' must be positive."));
    790 	}
    791 
    792       inarch_filename = argv[arg_index++];
    793 
    794       for (file_count = 0; argv[arg_index + file_count] != NULL; file_count++)
    795 	continue;
    796 
    797       files = (file_count > 0) ? argv + arg_index : NULL;
    798 
    799       arch = open_inarch (inarch_filename,
    800 			  files == NULL ? (char *) NULL : files[0]);
    801 
    802       if (operation == extract && bfd_is_thin_archive (arch))
    803 	fatal (_("`x' cannot be used on thin archives."));
    804 
    805       switch (operation)
    806 	{
    807 	case print_table:
    808 	  map_over_members (arch, print_descr, files, file_count);
    809 	  break;
    810 
    811 	case print_files:
    812 	  map_over_members (arch, print_contents, files, file_count);
    813 	  break;
    814 
    815 	case extract:
    816 	  map_over_members (arch, extract_file, files, file_count);
    817 	  break;
    818 
    819 	case del:
    820 	  if (files != NULL)
    821 	    delete_members (arch, files);
    822 	  else
    823 	    output_filename = NULL;
    824 	  break;
    825 
    826 	case move:
    827 	  /* PR 12558: Creating and moving at the same time does
    828 	     not make sense.  Just create the archive instead.  */
    829 	  if (! silent_create)
    830 	    {
    831 	      if (files != NULL)
    832 		move_members (arch, files);
    833 	      else
    834 		output_filename = NULL;
    835 	      break;
    836 	    }
    837 	  /* Fall through.  */
    838 
    839 	case replace:
    840 	case quick_append:
    841 	  if (files != NULL || write_armap > 0)
    842 	    replace_members (arch, files, operation == quick_append);
    843 	  else
    844 	    output_filename = NULL;
    845 	  break;
    846 
    847 	  /* Shouldn't happen! */
    848 	default:
    849 	  /* xgettext:c-format */
    850 	  fatal (_("internal error -- this option not implemented"));
    851 	}
    852     }
    853 
    854   END_PROGRESS (program_name);
    855 
    856   xexit (0);
    857   return 0;
    858 }
    859 
    860 bfd *
    861 open_inarch (const char *archive_filename, const char *file)
    862 {
    863   bfd **last_one;
    864   bfd *next_one;
    865   struct stat sbuf;
    866   bfd *arch;
    867   char **matching;
    868 
    869   bfd_set_error (bfd_error_no_error);
    870 
    871   if (target == NULL)
    872     target = plugin_target;
    873 
    874   if (stat (archive_filename, &sbuf) != 0)
    875     {
    876 #if !defined(__GO32__) || defined(__DJGPP__)
    877 
    878       /* FIXME: I don't understand why this fragment was ifndef'ed
    879 	 away for __GO32__; perhaps it was in the days of DJGPP v1.x.
    880 	 stat() works just fine in v2.x, so I think this should be
    881 	 removed.  For now, I enable it for DJGPP v2. -- EZ.  */
    882 
    883       /* KLUDGE ALERT! Temporary fix until I figger why
    884 	 stat() is wrong ... think it's buried in GO32's IDT - Jax */
    885       if (errno != ENOENT)
    886 	bfd_fatal (archive_filename);
    887 #endif
    888 
    889       if (!operation_alters_arch)
    890 	{
    891 	  fprintf (stderr, "%s: ", program_name);
    892 	  perror (archive_filename);
    893 	  maybequit ();
    894 	  return NULL;
    895 	}
    896 
    897       /* If the target isn't set, try to figure out the target to use
    898 	 for the archive from the first object on the list.  */
    899       if (target == NULL && file != NULL)
    900 	{
    901 	  bfd *obj;
    902 
    903 	  obj = bfd_openr (file, target);
    904 	  if (obj != NULL)
    905 	    {
    906 	      if (bfd_check_format (obj, bfd_object))
    907 		target = bfd_get_target (obj);
    908 	      (void) bfd_close (obj);
    909 	    }
    910 	}
    911 
    912       /* Create an empty archive.  */
    913       arch = bfd_openw (archive_filename, target);
    914       if (arch == NULL
    915 	  || ! bfd_set_format (arch, bfd_archive)
    916 	  || ! bfd_close (arch))
    917 	bfd_fatal (archive_filename);
    918       else if (!silent_create)
    919         non_fatal (_("creating %s"), archive_filename);
    920 
    921       /* If we die creating a new archive, don't leave it around.  */
    922       output_filename = archive_filename;
    923     }
    924 
    925   arch = bfd_openr (archive_filename, target);
    926   if (arch == NULL)
    927     {
    928     bloser:
    929       bfd_fatal (archive_filename);
    930     }
    931 
    932   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
    933     {
    934       bfd_nonfatal (archive_filename);
    935       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
    936 	{
    937 	  list_matching_formats (matching);
    938 	  free (matching);
    939 	}
    940       xexit (1);
    941     }
    942 
    943   if ((operation == replace || operation == quick_append)
    944       && bfd_openr_next_archived_file (arch, NULL) != NULL)
    945     {
    946       /* PR 15140: Catch attempts to convert a normal
    947 	 archive into a thin archive or vice versa.  */
    948       if (make_thin_archive && ! bfd_is_thin_archive (arch))
    949 	{
    950 	  fatal (_("Cannot convert existing library %s to thin format"),
    951 		 bfd_get_filename (arch));
    952 	  goto bloser;
    953 	}
    954       else if (! make_thin_archive && bfd_is_thin_archive (arch))
    955 	{
    956 	  fatal (_("Cannot convert existing thin library %s to normal format"),
    957 		 bfd_get_filename (arch));
    958 	  goto bloser;
    959 	}
    960     }
    961 
    962   last_one = &(arch->archive_next);
    963   /* Read all the contents right away, regardless.  */
    964   for (next_one = bfd_openr_next_archived_file (arch, NULL);
    965        next_one;
    966        next_one = bfd_openr_next_archived_file (arch, next_one))
    967     {
    968       PROGRESS (1);
    969       *last_one = next_one;
    970       last_one = &next_one->archive_next;
    971     }
    972   *last_one = (bfd *) NULL;
    973   if (bfd_get_error () != bfd_error_no_more_archived_files)
    974     goto bloser;
    975   return arch;
    976 }
    977 
    978 static void
    979 print_contents (bfd *abfd)
    980 {
    981   bfd_size_type ncopied = 0;
    982   bfd_size_type size;
    983   char *cbuf = (char *) xmalloc (BUFSIZE);
    984   struct stat buf;
    985 
    986   if (bfd_stat_arch_elt (abfd, &buf) != 0)
    987     /* xgettext:c-format */
    988     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
    989 
    990   if (verbose)
    991     printf ("\n<%s>\n\n", bfd_get_filename (abfd));
    992 
    993   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
    994 
    995   size = buf.st_size;
    996   while (ncopied < size)
    997     {
    998       bfd_size_type nread;
    999       bfd_size_type tocopy = size - ncopied;
   1000 
   1001       if (tocopy > BUFSIZE)
   1002 	tocopy = BUFSIZE;
   1003 
   1004       nread = bfd_bread (cbuf, tocopy, abfd);
   1005       if (nread != tocopy)
   1006 	/* xgettext:c-format */
   1007 	fatal (_("%s is not a valid archive"),
   1008 	       bfd_get_filename (bfd_my_archive (abfd)));
   1009 
   1010       /* fwrite in mingw32 may return int instead of bfd_size_type. Cast the
   1011 	 return value to bfd_size_type to avoid comparison between signed and
   1012 	 unsigned values.  */
   1013       if ((bfd_size_type) fwrite (cbuf, 1, nread, stdout) != nread)
   1014 	fatal ("stdout: %s", strerror (errno));
   1015       ncopied += tocopy;
   1016     }
   1017   free (cbuf);
   1018 }
   1019 
   1020 /* Extract a member of the archive into its own file.
   1021 
   1022    We defer opening the new file until after we have read a BUFSIZ chunk of the
   1023    old one, since we know we have just read the archive header for the old
   1024    one.  Since most members are shorter than BUFSIZ, this means we will read
   1025    the old header, read the old data, write a new inode for the new file, and
   1026    write the new data, and be done. This 'optimization' is what comes from
   1027    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
   1028    Gilmore  */
   1029 
   1030 void
   1031 extract_file (bfd *abfd)
   1032 {
   1033   FILE *ostream;
   1034   char *cbuf = (char *) xmalloc (BUFSIZE);
   1035   bfd_size_type nread, tocopy;
   1036   bfd_size_type ncopied = 0;
   1037   bfd_size_type size;
   1038   struct stat buf;
   1039 
   1040   /* PR binutils/17533: Do not allow directory traversal
   1041      outside of the current directory tree.  */
   1042   if (! is_valid_archive_path (bfd_get_filename (abfd)))
   1043     {
   1044       non_fatal (_("illegal pathname found in archive member: %s"),
   1045 		 bfd_get_filename (abfd));
   1046       return;
   1047     }
   1048 
   1049   if (bfd_stat_arch_elt (abfd, &buf) != 0)
   1050     /* xgettext:c-format */
   1051     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
   1052   size = buf.st_size;
   1053 
   1054   if (verbose)
   1055     printf ("x - %s\n", bfd_get_filename (abfd));
   1056 
   1057   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
   1058 
   1059   ostream = NULL;
   1060   if (size == 0)
   1061     {
   1062       /* Seems like an abstraction violation, eh?  Well it's OK! */
   1063       output_filename = bfd_get_filename (abfd);
   1064 
   1065       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
   1066       if (ostream == NULL)
   1067 	{
   1068 	  perror (bfd_get_filename (abfd));
   1069 	  xexit (1);
   1070 	}
   1071 
   1072       output_file = ostream;
   1073     }
   1074   else
   1075     while (ncopied < size)
   1076       {
   1077 	tocopy = size - ncopied;
   1078 	if (tocopy > BUFSIZE)
   1079 	  tocopy = BUFSIZE;
   1080 
   1081 	nread = bfd_bread (cbuf, tocopy, abfd);
   1082 	if (nread != tocopy)
   1083 	  /* xgettext:c-format */
   1084 	  fatal (_("%s is not a valid archive"),
   1085 		 bfd_get_filename (bfd_my_archive (abfd)));
   1086 
   1087 	/* See comment above; this saves disk arm motion */
   1088 	if (ostream == NULL)
   1089 	  {
   1090 	    /* Seems like an abstraction violation, eh?  Well it's OK! */
   1091 	    output_filename = bfd_get_filename (abfd);
   1092 
   1093 	    ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
   1094 	    if (ostream == NULL)
   1095 	      {
   1096 		perror (bfd_get_filename (abfd));
   1097 		xexit (1);
   1098 	      }
   1099 
   1100 	    output_file = ostream;
   1101 	  }
   1102 
   1103 	/* fwrite in mingw32 may return int instead of bfd_size_type. Cast
   1104 	   the return value to bfd_size_type to avoid comparison between
   1105 	   signed and unsigned values.  */
   1106 	if ((bfd_size_type) fwrite (cbuf, 1, nread, ostream) != nread)
   1107 	  fatal ("%s: %s", output_filename, strerror (errno));
   1108 	ncopied += tocopy;
   1109       }
   1110 
   1111   if (ostream != NULL)
   1112     fclose (ostream);
   1113 
   1114   output_file = NULL;
   1115   output_filename = NULL;
   1116 
   1117   chmod (bfd_get_filename (abfd), buf.st_mode);
   1118 
   1119   if (preserve_dates)
   1120     {
   1121       /* Set access time to modification time.  Only st_mtime is
   1122 	 initialized by bfd_stat_arch_elt.  */
   1123       buf.st_atime = buf.st_mtime;
   1124       set_times (bfd_get_filename (abfd), &buf);
   1125     }
   1126 
   1127   free (cbuf);
   1128 }
   1129 
   1130 static void
   1131 write_archive (bfd *iarch)
   1132 {
   1133   bfd *obfd;
   1134   char *old_name, *new_name;
   1135   bfd *contents_head = iarch->archive_next;
   1136 
   1137   old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
   1138   strcpy (old_name, bfd_get_filename (iarch));
   1139   new_name = make_tempname (old_name);
   1140 
   1141   if (new_name == NULL)
   1142     bfd_fatal (_("could not create temporary file whilst writing archive"));
   1143 
   1144   output_filename = new_name;
   1145 
   1146   obfd = bfd_openw (new_name, bfd_get_target (iarch));
   1147 
   1148   if (obfd == NULL)
   1149     bfd_fatal (old_name);
   1150 
   1151   output_bfd = obfd;
   1152 
   1153   bfd_set_format (obfd, bfd_archive);
   1154 
   1155   /* Request writing the archive symbol table unless we've
   1156      been explicitly requested not to.  */
   1157   obfd->has_armap = write_armap >= 0;
   1158 
   1159   if (ar_truncate)
   1160     {
   1161       /* This should really use bfd_set_file_flags, but that rejects
   1162          archives.  */
   1163       obfd->flags |= BFD_TRADITIONAL_FORMAT;
   1164     }
   1165 
   1166   if (deterministic)
   1167     obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
   1168 
   1169   if (make_thin_archive || bfd_is_thin_archive (iarch))
   1170     bfd_is_thin_archive (obfd) = 1;
   1171 
   1172   if (!bfd_set_archive_head (obfd, contents_head))
   1173     bfd_fatal (old_name);
   1174 
   1175   if (!bfd_close (obfd))
   1176     bfd_fatal (old_name);
   1177 
   1178   output_bfd = NULL;
   1179   output_filename = NULL;
   1180 
   1181   /* We don't care if this fails; we might be creating the archive.  */
   1182   bfd_close (iarch);
   1183 
   1184   if (smart_rename (new_name, old_name, 0) != 0)
   1185     xexit (1);
   1186   free (old_name);
   1187 }
   1188 
   1189 /* Return a pointer to the pointer to the entry which should be rplacd'd
   1190    into when altering.  DEFAULT_POS should be how to interpret pos_default,
   1191    and should be a pos value.  */
   1192 
   1193 static bfd **
   1194 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
   1195 {
   1196   bfd **after_bfd = contents;
   1197   enum pos realpos;
   1198   const char *realposname;
   1199 
   1200   if (postype == pos_default)
   1201     {
   1202       realpos = default_pos;
   1203       realposname = default_posname;
   1204     }
   1205   else
   1206     {
   1207       realpos = postype;
   1208       realposname = posname;
   1209     }
   1210 
   1211   if (realpos == pos_end)
   1212     {
   1213       while (*after_bfd)
   1214 	after_bfd = &((*after_bfd)->archive_next);
   1215     }
   1216   else
   1217     {
   1218       for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
   1219 	if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
   1220 	  {
   1221 	    if (realpos == pos_after)
   1222 	      after_bfd = &(*after_bfd)->archive_next;
   1223 	    break;
   1224 	  }
   1225     }
   1226   return after_bfd;
   1227 }
   1228 
   1229 static void
   1230 delete_members (bfd *arch, char **files_to_delete)
   1231 {
   1232   bfd **current_ptr_ptr;
   1233   bfd_boolean found;
   1234   bfd_boolean something_changed = FALSE;
   1235   int match_count;
   1236 
   1237   for (; *files_to_delete != NULL; ++files_to_delete)
   1238     {
   1239       /* In a.out systems, the armap is optional.  It's also called
   1240 	 __.SYMDEF.  So if the user asked to delete it, we should remember
   1241 	 that fact. This isn't quite right for COFF systems (where
   1242 	 __.SYMDEF might be regular member), but it's very unlikely
   1243 	 to be a problem.  FIXME */
   1244 
   1245       if (!strcmp (*files_to_delete, "__.SYMDEF"))
   1246 	{
   1247 	  arch->has_armap = FALSE;
   1248 	  write_armap = -1;
   1249 	  continue;
   1250 	}
   1251 
   1252       found = FALSE;
   1253       match_count = 0;
   1254       current_ptr_ptr = &(arch->archive_next);
   1255       while (*current_ptr_ptr)
   1256 	{
   1257 	  if (FILENAME_CMP (normalize (*files_to_delete, arch),
   1258 			    (*current_ptr_ptr)->filename) == 0)
   1259 	    {
   1260 	      ++match_count;
   1261 	      if (counted_name_mode
   1262 		  && match_count != counted_name_counter)
   1263 		{
   1264 		  /* Counting, and didn't match on count; go on to the
   1265                      next one.  */
   1266 		}
   1267 	      else
   1268 		{
   1269 		  found = TRUE;
   1270 		  something_changed = TRUE;
   1271 		  if (verbose)
   1272 		    printf ("d - %s\n",
   1273 			    *files_to_delete);
   1274 		  *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
   1275 		  goto next_file;
   1276 		}
   1277 	    }
   1278 
   1279 	  current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
   1280 	}
   1281 
   1282       if (verbose && !found)
   1283 	{
   1284 	  /* xgettext:c-format */
   1285 	  printf (_("No member named `%s'\n"), *files_to_delete);
   1286 	}
   1287     next_file:
   1288       ;
   1289     }
   1290 
   1291   if (something_changed)
   1292     write_archive (arch);
   1293   else
   1294     output_filename = NULL;
   1295 }
   1296 
   1297 
   1298 /* Reposition existing members within an archive */
   1299 
   1300 static void
   1301 move_members (bfd *arch, char **files_to_move)
   1302 {
   1303   bfd **after_bfd;		/* New entries go after this one */
   1304   bfd **current_ptr_ptr;	/* cdr pointer into contents */
   1305 
   1306   for (; *files_to_move; ++files_to_move)
   1307     {
   1308       current_ptr_ptr = &(arch->archive_next);
   1309       while (*current_ptr_ptr)
   1310 	{
   1311 	  bfd *current_ptr = *current_ptr_ptr;
   1312 	  if (FILENAME_CMP (normalize (*files_to_move, arch),
   1313 			    current_ptr->filename) == 0)
   1314 	    {
   1315 	      /* Move this file to the end of the list - first cut from
   1316 		 where it is.  */
   1317 	      bfd *link_bfd;
   1318 	      *current_ptr_ptr = current_ptr->archive_next;
   1319 
   1320 	      /* Now glue to end */
   1321 	      after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
   1322 	      link_bfd = *after_bfd;
   1323 	      *after_bfd = current_ptr;
   1324 	      current_ptr->archive_next = link_bfd;
   1325 
   1326 	      if (verbose)
   1327 		printf ("m - %s\n", *files_to_move);
   1328 
   1329 	      goto next_file;
   1330 	    }
   1331 
   1332 	  current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
   1333 	}
   1334       /* xgettext:c-format */
   1335       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
   1336 
   1337     next_file:;
   1338     }
   1339 
   1340   write_archive (arch);
   1341 }
   1342 
   1343 /* Ought to default to replacing in place, but this is existing practice!  */
   1344 
   1345 static void
   1346 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
   1347 {
   1348   bfd_boolean changed = FALSE;
   1349   bfd **after_bfd;		/* New entries go after this one.  */
   1350   bfd *current;
   1351   bfd **current_ptr;
   1352 
   1353   while (files_to_move && *files_to_move)
   1354     {
   1355       if (! quick)
   1356 	{
   1357 	  current_ptr = &arch->archive_next;
   1358 	  while (*current_ptr)
   1359 	    {
   1360 	      current = *current_ptr;
   1361 
   1362 	      /* For compatibility with existing ar programs, we
   1363 		 permit the same file to be added multiple times.  */
   1364 	      if (FILENAME_CMP (normalize (*files_to_move, arch),
   1365 				normalize (current->filename, arch)) == 0
   1366 		  && current->arelt_data != NULL)
   1367 		{
   1368 		  if (newer_only)
   1369 		    {
   1370 		      struct stat fsbuf, asbuf;
   1371 
   1372 		      if (stat (*files_to_move, &fsbuf) != 0)
   1373 			{
   1374 			  if (errno != ENOENT)
   1375 			    bfd_fatal (*files_to_move);
   1376 			  goto next_file;
   1377 			}
   1378 		      if (bfd_stat_arch_elt (current, &asbuf) != 0)
   1379 			/* xgettext:c-format */
   1380 			fatal (_("internal stat error on %s"),
   1381 			       current->filename);
   1382 
   1383 		      if (fsbuf.st_mtime <= asbuf.st_mtime)
   1384 			goto next_file;
   1385 		    }
   1386 
   1387 		  after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
   1388 					   current->filename);
   1389 		  if (ar_emul_replace (after_bfd, *files_to_move,
   1390 				       target, verbose))
   1391 		    {
   1392 		      /* Snip out this entry from the chain.  */
   1393 		      *current_ptr = (*current_ptr)->archive_next;
   1394 		      changed = TRUE;
   1395 		    }
   1396 
   1397 		  goto next_file;
   1398 		}
   1399 	      current_ptr = &(current->archive_next);
   1400 	    }
   1401 	}
   1402 
   1403       /* Add to the end of the archive.  */
   1404       after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
   1405 
   1406       if (ar_emul_append (after_bfd, *files_to_move, target,
   1407 			  verbose, make_thin_archive))
   1408 	changed = TRUE;
   1409 
   1410     next_file:;
   1411 
   1412       files_to_move++;
   1413     }
   1414 
   1415   if (changed)
   1416     write_archive (arch);
   1417   else
   1418     output_filename = NULL;
   1419 }
   1420 
   1421 static int
   1422 ranlib_only (const char *archname)
   1423 {
   1424   bfd *arch;
   1425 
   1426   if (get_file_size (archname) < 1)
   1427     return 1;
   1428   write_armap = 1;
   1429   arch = open_inarch (archname, (char *) NULL);
   1430   if (arch == NULL)
   1431     xexit (1);
   1432   write_archive (arch);
   1433   return 0;
   1434 }
   1435 
   1436 /* Update the timestamp of the symbol map of an archive.  */
   1437 
   1438 static int
   1439 ranlib_touch (const char *archname)
   1440 {
   1441 #ifdef __GO32__
   1442   /* I don't think updating works on go32.  */
   1443   ranlib_only (archname);
   1444 #else
   1445   int f;
   1446   bfd *arch;
   1447   char **matching;
   1448 
   1449   if (get_file_size (archname) < 1)
   1450     return 1;
   1451   f = open (archname, O_RDWR | O_BINARY, 0);
   1452   if (f < 0)
   1453     {
   1454       bfd_set_error (bfd_error_system_call);
   1455       bfd_fatal (archname);
   1456     }
   1457 
   1458   arch = bfd_fdopenr (archname, (const char *) NULL, f);
   1459   if (arch == NULL)
   1460     bfd_fatal (archname);
   1461   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
   1462     {
   1463       bfd_nonfatal (archname);
   1464       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
   1465 	{
   1466 	  list_matching_formats (matching);
   1467 	  free (matching);
   1468 	}
   1469       xexit (1);
   1470     }
   1471 
   1472   if (! bfd_has_map (arch))
   1473     /* xgettext:c-format */
   1474     fatal (_("%s: no archive map to update"), archname);
   1475 
   1476   if (deterministic)
   1477     arch->flags |= BFD_DETERMINISTIC_OUTPUT;
   1478 
   1479   bfd_update_armap_timestamp (arch);
   1480 
   1481   if (! bfd_close (arch))
   1482     bfd_fatal (archname);
   1483 #endif
   1484   return 0;
   1485 }
   1486 
   1487 /* Things which are interesting to map over all or some of the files: */
   1488 
   1489 static void
   1490 print_descr (bfd *abfd)
   1491 {
   1492   print_arelt_descr (stdout, abfd, verbose);
   1493 }
   1494