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