Home | History | Annotate | Download | only in binutils
      1 /* ar.c - Archive modify and extract.
      2    Copyright (C) 1991-2016 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   bfd_set_error_program_name (program_name);
    698 #if BFD_SUPPORTS_PLUGINS
    699   bfd_plugin_set_program_name (program_name);
    700 #endif
    701 
    702   expandargv (&argc, &argv);
    703 
    704   if (is_ranlib < 0)
    705     {
    706       const char *temp = lbasename (program_name);
    707 
    708       if (strlen (temp) >= 6
    709 	  && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
    710 	is_ranlib = 1;
    711       else
    712 	is_ranlib = 0;
    713     }
    714 
    715   START_PROGRESS (program_name, 0);
    716 
    717   bfd_init ();
    718   set_default_bfd_target ();
    719 
    720   xatexit (remove_output);
    721 
    722   for (i = 1; i < argc; i++)
    723     if (! ar_emul_parse_arg (argv[i]))
    724       break;
    725   argv += (i - 1);
    726   argc -= (i - 1);
    727 
    728   if (is_ranlib)
    729     ranlib_main (argc, argv);
    730 
    731   if (argc < 2)
    732     usage (0);
    733 
    734   argv = decode_options (argc, argv);
    735 
    736   if (show_help)
    737     usage (1);
    738 
    739   if (show_version)
    740     print_version ("ar");
    741 
    742   arg_index = 0;
    743 
    744   if (mri_mode)
    745     {
    746       default_deterministic ();
    747       mri_emul ();
    748     }
    749   else
    750     {
    751       bfd *arch;
    752 
    753       /* We don't use do_quick_append any more.  Too many systems
    754 	 expect ar to always rebuild the symbol table even when q is
    755 	 used.  */
    756 
    757       /* We can't write an armap when using ar q, so just do ar r
    758          instead.  */
    759       if (operation == quick_append && write_armap)
    760 	operation = replace;
    761 
    762       if ((operation == none || operation == print_table)
    763 	  && write_armap == 1)
    764 	xexit (ranlib_only (argv[arg_index]));
    765 
    766       if (operation == none)
    767 	fatal (_("no operation specified"));
    768 
    769       if (newer_only && operation != replace)
    770 	fatal (_("`u' is only meaningful with the `r' option."));
    771 
    772       if (newer_only && deterministic > 0)
    773         fatal (_("`u' is not meaningful with the `D' option."));
    774 
    775       if (newer_only && deterministic < 0 && DEFAULT_AR_DETERMINISTIC)
    776         non_fatal (_("\
    777 `u' modifier ignored since `D' is the default (see `U')"));
    778 
    779       default_deterministic ();
    780 
    781       if (postype != pos_default)
    782 	posname = argv[arg_index++];
    783 
    784       if (counted_name_mode)
    785 	{
    786 	  if (operation != extract && operation != del)
    787 	    fatal (_("`N' is only meaningful with the `x' and `d' options."));
    788 	  counted_name_counter = atoi (argv[arg_index++]);
    789 	  if (counted_name_counter <= 0)
    790 	    fatal (_("Value for `N' must be positive."));
    791 	}
    792 
    793       inarch_filename = argv[arg_index++];
    794 
    795       for (file_count = 0; argv[arg_index + file_count] != NULL; file_count++)
    796 	continue;
    797 
    798       files = (file_count > 0) ? argv + arg_index : NULL;
    799 
    800       arch = open_inarch (inarch_filename,
    801 			  files == NULL ? (char *) NULL : files[0]);
    802 
    803       if (operation == extract && bfd_is_thin_archive (arch))
    804 	fatal (_("`x' cannot be used on thin archives."));
    805 
    806       switch (operation)
    807 	{
    808 	case print_table:
    809 	  map_over_members (arch, print_descr, files, file_count);
    810 	  break;
    811 
    812 	case print_files:
    813 	  map_over_members (arch, print_contents, files, file_count);
    814 	  break;
    815 
    816 	case extract:
    817 	  map_over_members (arch, extract_file, files, file_count);
    818 	  break;
    819 
    820 	case del:
    821 	  if (files != NULL)
    822 	    delete_members (arch, files);
    823 	  else
    824 	    output_filename = NULL;
    825 	  break;
    826 
    827 	case move:
    828 	  /* PR 12558: Creating and moving at the same time does
    829 	     not make sense.  Just create the archive instead.  */
    830 	  if (! silent_create)
    831 	    {
    832 	      if (files != NULL)
    833 		move_members (arch, files);
    834 	      else
    835 		output_filename = NULL;
    836 	      break;
    837 	    }
    838 	  /* Fall through.  */
    839 
    840 	case replace:
    841 	case quick_append:
    842 	  if (files != NULL || write_armap > 0)
    843 	    replace_members (arch, files, operation == quick_append);
    844 	  else
    845 	    output_filename = NULL;
    846 	  break;
    847 
    848 	  /* Shouldn't happen! */
    849 	default:
    850 	  /* xgettext:c-format */
    851 	  fatal (_("internal error -- this option not implemented"));
    852 	}
    853     }
    854 
    855   END_PROGRESS (program_name);
    856 
    857   xexit (0);
    858   return 0;
    859 }
    860 
    861 bfd *
    862 open_inarch (const char *archive_filename, const char *file)
    863 {
    864   bfd **last_one;
    865   bfd *next_one;
    866   struct stat sbuf;
    867   bfd *arch;
    868   char **matching;
    869 
    870   bfd_set_error (bfd_error_no_error);
    871 
    872   if (target == NULL)
    873     target = plugin_target;
    874 
    875   if (stat (archive_filename, &sbuf) != 0)
    876     {
    877 #if !defined(__GO32__) || defined(__DJGPP__)
    878 
    879       /* FIXME: I don't understand why this fragment was ifndef'ed
    880 	 away for __GO32__; perhaps it was in the days of DJGPP v1.x.
    881 	 stat() works just fine in v2.x, so I think this should be
    882 	 removed.  For now, I enable it for DJGPP v2. -- EZ.  */
    883 
    884       /* KLUDGE ALERT! Temporary fix until I figger why
    885 	 stat() is wrong ... think it's buried in GO32's IDT - Jax */
    886       if (errno != ENOENT)
    887 	bfd_fatal (archive_filename);
    888 #endif
    889 
    890       if (!operation_alters_arch)
    891 	{
    892 	  fprintf (stderr, "%s: ", program_name);
    893 	  perror (archive_filename);
    894 	  maybequit ();
    895 	  return NULL;
    896 	}
    897 
    898       /* If the target isn't set, try to figure out the target to use
    899 	 for the archive from the first object on the list.  */
    900       if (target == NULL && file != NULL)
    901 	{
    902 	  bfd *obj;
    903 
    904 	  obj = bfd_openr (file, target);
    905 	  if (obj != NULL)
    906 	    {
    907 	      if (bfd_check_format (obj, bfd_object))
    908 		target = bfd_get_target (obj);
    909 	      (void) bfd_close (obj);
    910 	    }
    911 	}
    912 
    913       /* Create an empty archive.  */
    914       arch = bfd_openw (archive_filename, target);
    915       if (arch == NULL
    916 	  || ! bfd_set_format (arch, bfd_archive)
    917 	  || ! bfd_close (arch))
    918 	bfd_fatal (archive_filename);
    919       else if (!silent_create)
    920         non_fatal (_("creating %s"), archive_filename);
    921 
    922       /* If we die creating a new archive, don't leave it around.  */
    923       output_filename = archive_filename;
    924     }
    925 
    926   arch = bfd_openr (archive_filename, target);
    927   if (arch == NULL)
    928     {
    929     bloser:
    930       bfd_fatal (archive_filename);
    931     }
    932 
    933   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
    934     {
    935       bfd_nonfatal (archive_filename);
    936       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
    937 	{
    938 	  list_matching_formats (matching);
    939 	  free (matching);
    940 	}
    941       xexit (1);
    942     }
    943 
    944   if ((operation == replace || operation == quick_append)
    945       && bfd_openr_next_archived_file (arch, NULL) != NULL)
    946     {
    947       /* PR 15140: Catch attempts to convert a normal
    948 	 archive into a thin archive or vice versa.  */
    949       if (make_thin_archive && ! bfd_is_thin_archive (arch))
    950 	{
    951 	  fatal (_("Cannot convert existing library %s to thin format"),
    952 		 bfd_get_filename (arch));
    953 	  goto bloser;
    954 	}
    955       else if (! make_thin_archive && bfd_is_thin_archive (arch))
    956 	{
    957 	  fatal (_("Cannot convert existing thin library %s to normal format"),
    958 		 bfd_get_filename (arch));
    959 	  goto bloser;
    960 	}
    961     }
    962 
    963   last_one = &(arch->archive_next);
    964   /* Read all the contents right away, regardless.  */
    965   for (next_one = bfd_openr_next_archived_file (arch, NULL);
    966        next_one;
    967        next_one = bfd_openr_next_archived_file (arch, next_one))
    968     {
    969       PROGRESS (1);
    970       *last_one = next_one;
    971       last_one = &next_one->archive_next;
    972     }
    973   *last_one = (bfd *) NULL;
    974   if (bfd_get_error () != bfd_error_no_more_archived_files)
    975     goto bloser;
    976   return arch;
    977 }
    978 
    979 static void
    980 print_contents (bfd *abfd)
    981 {
    982   bfd_size_type ncopied = 0;
    983   bfd_size_type size;
    984   char *cbuf = (char *) xmalloc (BUFSIZE);
    985   struct stat buf;
    986 
    987   if (bfd_stat_arch_elt (abfd, &buf) != 0)
    988     /* xgettext:c-format */
    989     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
    990 
    991   if (verbose)
    992     printf ("\n<%s>\n\n", bfd_get_filename (abfd));
    993 
    994   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
    995 
    996   size = buf.st_size;
    997   while (ncopied < size)
    998     {
    999       bfd_size_type nread;
   1000       bfd_size_type tocopy = size - ncopied;
   1001 
   1002       if (tocopy > BUFSIZE)
   1003 	tocopy = BUFSIZE;
   1004 
   1005       nread = bfd_bread (cbuf, tocopy, abfd);
   1006       if (nread != tocopy)
   1007 	/* xgettext:c-format */
   1008 	fatal (_("%s is not a valid archive"),
   1009 	       bfd_get_filename (abfd->my_archive));
   1010 
   1011       /* fwrite in mingw32 may return int instead of bfd_size_type. Cast the
   1012 	 return value to bfd_size_type to avoid comparison between signed and
   1013 	 unsigned values.  */
   1014       if ((bfd_size_type) fwrite (cbuf, 1, nread, stdout) != nread)
   1015 	fatal ("stdout: %s", strerror (errno));
   1016       ncopied += tocopy;
   1017     }
   1018   free (cbuf);
   1019 }
   1020 
   1021 /* Extract a member of the archive into its own file.
   1022 
   1023    We defer opening the new file until after we have read a BUFSIZ chunk of the
   1024    old one, since we know we have just read the archive header for the old
   1025    one.  Since most members are shorter than BUFSIZ, this means we will read
   1026    the old header, read the old data, write a new inode for the new file, and
   1027    write the new data, and be done. This 'optimization' is what comes from
   1028    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
   1029    Gilmore  */
   1030 
   1031 void
   1032 extract_file (bfd *abfd)
   1033 {
   1034   FILE *ostream;
   1035   char *cbuf = (char *) xmalloc (BUFSIZE);
   1036   bfd_size_type nread, tocopy;
   1037   bfd_size_type ncopied = 0;
   1038   bfd_size_type size;
   1039   struct stat buf;
   1040 
   1041   /* PR binutils/17533: Do not allow directory traversal
   1042      outside of the current directory tree.  */
   1043   if (! is_valid_archive_path (bfd_get_filename (abfd)))
   1044     {
   1045       non_fatal (_("illegal pathname found in archive member: %s"),
   1046 		 bfd_get_filename (abfd));
   1047       free (cbuf);
   1048       return;
   1049     }
   1050 
   1051   if (bfd_stat_arch_elt (abfd, &buf) != 0)
   1052     /* xgettext:c-format */
   1053     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
   1054   size = buf.st_size;
   1055 
   1056   if (verbose)
   1057     printf ("x - %s\n", bfd_get_filename (abfd));
   1058 
   1059   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
   1060 
   1061   ostream = NULL;
   1062   if (size == 0)
   1063     {
   1064       /* Seems like an abstraction violation, eh?  Well it's OK! */
   1065       output_filename = bfd_get_filename (abfd);
   1066 
   1067       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
   1068       if (ostream == NULL)
   1069 	{
   1070 	  perror (bfd_get_filename (abfd));
   1071 	  xexit (1);
   1072 	}
   1073 
   1074       output_file = ostream;
   1075     }
   1076   else
   1077     while (ncopied < size)
   1078       {
   1079 	tocopy = size - ncopied;
   1080 	if (tocopy > BUFSIZE)
   1081 	  tocopy = BUFSIZE;
   1082 
   1083 	nread = bfd_bread (cbuf, tocopy, abfd);
   1084 	if (nread != tocopy)
   1085 	  /* xgettext:c-format */
   1086 	  fatal (_("%s is not a valid archive"),
   1087 		 bfd_get_filename (abfd->my_archive));
   1088 
   1089 	/* See comment above; this saves disk arm motion */
   1090 	if (ostream == NULL)
   1091 	  {
   1092 	    /* Seems like an abstraction violation, eh?  Well it's OK! */
   1093 	    output_filename = bfd_get_filename (abfd);
   1094 
   1095 	    ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
   1096 	    if (ostream == NULL)
   1097 	      {
   1098 		perror (bfd_get_filename (abfd));
   1099 		xexit (1);
   1100 	      }
   1101 
   1102 	    output_file = ostream;
   1103 	  }
   1104 
   1105 	/* fwrite in mingw32 may return int instead of bfd_size_type. Cast
   1106 	   the return value to bfd_size_type to avoid comparison between
   1107 	   signed and unsigned values.  */
   1108 	if ((bfd_size_type) fwrite (cbuf, 1, nread, ostream) != nread)
   1109 	  fatal ("%s: %s", output_filename, strerror (errno));
   1110 	ncopied += tocopy;
   1111       }
   1112 
   1113   if (ostream != NULL)
   1114     fclose (ostream);
   1115 
   1116   output_file = NULL;
   1117   output_filename = NULL;
   1118 
   1119   chmod (bfd_get_filename (abfd), buf.st_mode);
   1120 
   1121   if (preserve_dates)
   1122     {
   1123       /* Set access time to modification time.  Only st_mtime is
   1124 	 initialized by bfd_stat_arch_elt.  */
   1125       buf.st_atime = buf.st_mtime;
   1126       set_times (bfd_get_filename (abfd), &buf);
   1127     }
   1128 
   1129   free (cbuf);
   1130 }
   1131 
   1132 static void
   1133 write_archive (bfd *iarch)
   1134 {
   1135   bfd *obfd;
   1136   char *old_name, *new_name;
   1137   bfd *contents_head = iarch->archive_next;
   1138 
   1139   old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
   1140   strcpy (old_name, bfd_get_filename (iarch));
   1141   new_name = make_tempname (old_name);
   1142 
   1143   if (new_name == NULL)
   1144     bfd_fatal (_("could not create temporary file whilst writing archive"));
   1145 
   1146   output_filename = new_name;
   1147 
   1148   obfd = bfd_openw (new_name, bfd_get_target (iarch));
   1149 
   1150   if (obfd == NULL)
   1151     bfd_fatal (old_name);
   1152 
   1153   output_bfd = obfd;
   1154 
   1155   bfd_set_format (obfd, bfd_archive);
   1156 
   1157   /* Request writing the archive symbol table unless we've
   1158      been explicitly requested not to.  */
   1159   obfd->has_armap = write_armap >= 0;
   1160 
   1161   if (ar_truncate)
   1162     {
   1163       /* This should really use bfd_set_file_flags, but that rejects
   1164          archives.  */
   1165       obfd->flags |= BFD_TRADITIONAL_FORMAT;
   1166     }
   1167 
   1168   if (deterministic)
   1169     obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
   1170 
   1171   if (make_thin_archive || bfd_is_thin_archive (iarch))
   1172     bfd_is_thin_archive (obfd) = 1;
   1173 
   1174   if (!bfd_set_archive_head (obfd, contents_head))
   1175     bfd_fatal (old_name);
   1176 
   1177   if (!bfd_close (obfd))
   1178     bfd_fatal (old_name);
   1179 
   1180   output_bfd = NULL;
   1181   output_filename = NULL;
   1182 
   1183   /* We don't care if this fails; we might be creating the archive.  */
   1184   bfd_close (iarch);
   1185 
   1186   if (smart_rename (new_name, old_name, 0) != 0)
   1187     xexit (1);
   1188   free (old_name);
   1189 }
   1190 
   1191 /* Return a pointer to the pointer to the entry which should be rplacd'd
   1192    into when altering.  DEFAULT_POS should be how to interpret pos_default,
   1193    and should be a pos value.  */
   1194 
   1195 static bfd **
   1196 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
   1197 {
   1198   bfd **after_bfd = contents;
   1199   enum pos realpos;
   1200   const char *realposname;
   1201 
   1202   if (postype == pos_default)
   1203     {
   1204       realpos = default_pos;
   1205       realposname = default_posname;
   1206     }
   1207   else
   1208     {
   1209       realpos = postype;
   1210       realposname = posname;
   1211     }
   1212 
   1213   if (realpos == pos_end)
   1214     {
   1215       while (*after_bfd)
   1216 	after_bfd = &((*after_bfd)->archive_next);
   1217     }
   1218   else
   1219     {
   1220       for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
   1221 	if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
   1222 	  {
   1223 	    if (realpos == pos_after)
   1224 	      after_bfd = &(*after_bfd)->archive_next;
   1225 	    break;
   1226 	  }
   1227     }
   1228   return after_bfd;
   1229 }
   1230 
   1231 static void
   1232 delete_members (bfd *arch, char **files_to_delete)
   1233 {
   1234   bfd **current_ptr_ptr;
   1235   bfd_boolean found;
   1236   bfd_boolean something_changed = FALSE;
   1237   int match_count;
   1238 
   1239   for (; *files_to_delete != NULL; ++files_to_delete)
   1240     {
   1241       /* In a.out systems, the armap is optional.  It's also called
   1242 	 __.SYMDEF.  So if the user asked to delete it, we should remember
   1243 	 that fact. This isn't quite right for COFF systems (where
   1244 	 __.SYMDEF might be regular member), but it's very unlikely
   1245 	 to be a problem.  FIXME */
   1246 
   1247       if (!strcmp (*files_to_delete, "__.SYMDEF"))
   1248 	{
   1249 	  arch->has_armap = FALSE;
   1250 	  write_armap = -1;
   1251 	  continue;
   1252 	}
   1253 
   1254       found = FALSE;
   1255       match_count = 0;
   1256       current_ptr_ptr = &(arch->archive_next);
   1257       while (*current_ptr_ptr)
   1258 	{
   1259 	  if (FILENAME_CMP (normalize (*files_to_delete, arch),
   1260 			    (*current_ptr_ptr)->filename) == 0)
   1261 	    {
   1262 	      ++match_count;
   1263 	      if (counted_name_mode
   1264 		  && match_count != counted_name_counter)
   1265 		{
   1266 		  /* Counting, and didn't match on count; go on to the
   1267                      next one.  */
   1268 		}
   1269 	      else
   1270 		{
   1271 		  found = TRUE;
   1272 		  something_changed = TRUE;
   1273 		  if (verbose)
   1274 		    printf ("d - %s\n",
   1275 			    *files_to_delete);
   1276 		  *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
   1277 		  goto next_file;
   1278 		}
   1279 	    }
   1280 
   1281 	  current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
   1282 	}
   1283 
   1284       if (verbose && !found)
   1285 	{
   1286 	  /* xgettext:c-format */
   1287 	  printf (_("No member named `%s'\n"), *files_to_delete);
   1288 	}
   1289     next_file:
   1290       ;
   1291     }
   1292 
   1293   if (something_changed)
   1294     write_archive (arch);
   1295   else
   1296     output_filename = NULL;
   1297 }
   1298 
   1299 
   1300 /* Reposition existing members within an archive */
   1301 
   1302 static void
   1303 move_members (bfd *arch, char **files_to_move)
   1304 {
   1305   bfd **after_bfd;		/* New entries go after this one */
   1306   bfd **current_ptr_ptr;	/* cdr pointer into contents */
   1307 
   1308   for (; *files_to_move; ++files_to_move)
   1309     {
   1310       current_ptr_ptr = &(arch->archive_next);
   1311       while (*current_ptr_ptr)
   1312 	{
   1313 	  bfd *current_ptr = *current_ptr_ptr;
   1314 	  if (FILENAME_CMP (normalize (*files_to_move, arch),
   1315 			    current_ptr->filename) == 0)
   1316 	    {
   1317 	      /* Move this file to the end of the list - first cut from
   1318 		 where it is.  */
   1319 	      bfd *link_bfd;
   1320 	      *current_ptr_ptr = current_ptr->archive_next;
   1321 
   1322 	      /* Now glue to end */
   1323 	      after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
   1324 	      link_bfd = *after_bfd;
   1325 	      *after_bfd = current_ptr;
   1326 	      current_ptr->archive_next = link_bfd;
   1327 
   1328 	      if (verbose)
   1329 		printf ("m - %s\n", *files_to_move);
   1330 
   1331 	      goto next_file;
   1332 	    }
   1333 
   1334 	  current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
   1335 	}
   1336       /* xgettext:c-format */
   1337       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
   1338 
   1339     next_file:;
   1340     }
   1341 
   1342   write_archive (arch);
   1343 }
   1344 
   1345 /* Ought to default to replacing in place, but this is existing practice!  */
   1346 
   1347 static void
   1348 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
   1349 {
   1350   bfd_boolean changed = FALSE;
   1351   bfd **after_bfd;		/* New entries go after this one.  */
   1352   bfd *current;
   1353   bfd **current_ptr;
   1354 
   1355   while (files_to_move && *files_to_move)
   1356     {
   1357       if (! quick)
   1358 	{
   1359 	  current_ptr = &arch->archive_next;
   1360 	  while (*current_ptr)
   1361 	    {
   1362 	      current = *current_ptr;
   1363 
   1364 	      /* For compatibility with existing ar programs, we
   1365 		 permit the same file to be added multiple times.  */
   1366 	      if (FILENAME_CMP (normalize (*files_to_move, arch),
   1367 				normalize (current->filename, arch)) == 0
   1368 		  && current->arelt_data != NULL)
   1369 		{
   1370 		  if (newer_only)
   1371 		    {
   1372 		      struct stat fsbuf, asbuf;
   1373 
   1374 		      if (stat (*files_to_move, &fsbuf) != 0)
   1375 			{
   1376 			  if (errno != ENOENT)
   1377 			    bfd_fatal (*files_to_move);
   1378 			  goto next_file;
   1379 			}
   1380 		      if (bfd_stat_arch_elt (current, &asbuf) != 0)
   1381 			/* xgettext:c-format */
   1382 			fatal (_("internal stat error on %s"),
   1383 			       current->filename);
   1384 
   1385 		      if (fsbuf.st_mtime <= asbuf.st_mtime)
   1386 			goto next_file;
   1387 		    }
   1388 
   1389 		  after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
   1390 					   current->filename);
   1391 		  if (ar_emul_replace (after_bfd, *files_to_move,
   1392 				       target, verbose))
   1393 		    {
   1394 		      /* Snip out this entry from the chain.  */
   1395 		      *current_ptr = (*current_ptr)->archive_next;
   1396 		      changed = TRUE;
   1397 		    }
   1398 
   1399 		  goto next_file;
   1400 		}
   1401 	      current_ptr = &(current->archive_next);
   1402 	    }
   1403 	}
   1404 
   1405       /* Add to the end of the archive.  */
   1406       after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
   1407 
   1408       if (ar_emul_append (after_bfd, *files_to_move, target,
   1409 			  verbose, make_thin_archive))
   1410 	changed = TRUE;
   1411 
   1412     next_file:;
   1413 
   1414       files_to_move++;
   1415     }
   1416 
   1417   if (changed)
   1418     write_archive (arch);
   1419   else
   1420     output_filename = NULL;
   1421 }
   1422 
   1423 static int
   1424 ranlib_only (const char *archname)
   1425 {
   1426   bfd *arch;
   1427 
   1428   if (get_file_size (archname) < 1)
   1429     return 1;
   1430   write_armap = 1;
   1431   arch = open_inarch (archname, (char *) NULL);
   1432   if (arch == NULL)
   1433     xexit (1);
   1434   write_archive (arch);
   1435   return 0;
   1436 }
   1437 
   1438 /* Update the timestamp of the symbol map of an archive.  */
   1439 
   1440 static int
   1441 ranlib_touch (const char *archname)
   1442 {
   1443 #ifdef __GO32__
   1444   /* I don't think updating works on go32.  */
   1445   ranlib_only (archname);
   1446 #else
   1447   int f;
   1448   bfd *arch;
   1449   char **matching;
   1450 
   1451   if (get_file_size (archname) < 1)
   1452     return 1;
   1453   f = open (archname, O_RDWR | O_BINARY, 0);
   1454   if (f < 0)
   1455     {
   1456       bfd_set_error (bfd_error_system_call);
   1457       bfd_fatal (archname);
   1458     }
   1459 
   1460   arch = bfd_fdopenr (archname, (const char *) NULL, f);
   1461   if (arch == NULL)
   1462     bfd_fatal (archname);
   1463   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
   1464     {
   1465       bfd_nonfatal (archname);
   1466       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
   1467 	{
   1468 	  list_matching_formats (matching);
   1469 	  free (matching);
   1470 	}
   1471       xexit (1);
   1472     }
   1473 
   1474   if (! bfd_has_map (arch))
   1475     /* xgettext:c-format */
   1476     fatal (_("%s: no archive map to update"), archname);
   1477 
   1478   if (deterministic)
   1479     arch->flags |= BFD_DETERMINISTIC_OUTPUT;
   1480 
   1481   bfd_update_armap_timestamp (arch);
   1482 
   1483   if (! bfd_close (arch))
   1484     bfd_fatal (archname);
   1485 #endif
   1486   return 0;
   1487 }
   1488 
   1489 /* Things which are interesting to map over all or some of the files: */
   1490 
   1491 static void
   1492 print_descr (bfd *abfd)
   1493 {
   1494   print_arelt_descr (stdout, abfd, verbose);
   1495 }
   1496