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