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