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