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