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