12a6b7db3Sskrll /* ar.c - Archive modify and extract.
2*e072ec67Schristos Copyright (C) 1991-2022 Free Software Foundation, Inc.
32a6b7db3Sskrll
42a6b7db3Sskrll This file is part of GNU Binutils.
52a6b7db3Sskrll
62a6b7db3Sskrll This program is free software; you can redistribute it and/or modify
72a6b7db3Sskrll it under the terms of the GNU General Public License as published by
82a6b7db3Sskrll the Free Software Foundation; either version 3 of the License, or
92a6b7db3Sskrll (at your option) any later version.
102a6b7db3Sskrll
112a6b7db3Sskrll This program is distributed in the hope that it will be useful,
122a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
132a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
142a6b7db3Sskrll GNU General Public License for more details.
152a6b7db3Sskrll
162a6b7db3Sskrll You should have received a copy of the GNU General Public License
172a6b7db3Sskrll along with this program; if not, write to the Free Software
182a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
192a6b7db3Sskrll MA 02110-1301, USA. */
202a6b7db3Sskrll
212a6b7db3Sskrll /*
224c43201bSchristos Bugs: GNU ar used to check file against filesystem in quick_update and
234c43201bSchristos replace operations (would check mtime). Doesn't warn when name truncated.
244c43201bSchristos No way to specify pos_end. Error messages should be more consistent. */
252a6b7db3Sskrll
262a6b7db3Sskrll #include "sysdep.h"
272a6b7db3Sskrll #include "bfd.h"
282a6b7db3Sskrll #include "libiberty.h"
292a6b7db3Sskrll #include "progress.h"
304c43201bSchristos #include "getopt.h"
312a6b7db3Sskrll #include "aout/ar.h"
322a6b7db3Sskrll #include "bucomm.h"
332a6b7db3Sskrll #include "arsup.h"
342a6b7db3Sskrll #include "filenames.h"
352a6b7db3Sskrll #include "binemul.h"
36aa4b58b1Schristos #include "plugin-api.h"
378443c5fcSchristos #include "plugin.h"
38c21fdd85Schristos #include "ansidecl.h"
392a6b7db3Sskrll
402a6b7db3Sskrll #ifdef __GO32___
412a6b7db3Sskrll #define EXT_NAME_LEN 3 /* Bufflen of addition to name if it's MS-DOS. */
422a6b7db3Sskrll #else
432a6b7db3Sskrll #define EXT_NAME_LEN 6 /* Ditto for *NIX. */
442a6b7db3Sskrll #endif
452a6b7db3Sskrll
462a6b7db3Sskrll /* Static declarations. */
472a6b7db3Sskrll
482a6b7db3Sskrll static void mri_emul (void);
492a6b7db3Sskrll static const char *normalize (const char *, bfd *);
502a6b7db3Sskrll static void remove_output (void);
512a6b7db3Sskrll static void map_over_members (bfd *, void (*)(bfd *), char **, int);
522a6b7db3Sskrll static void print_contents (bfd * member);
532a6b7db3Sskrll static void delete_members (bfd *, char **files_to_delete);
542a6b7db3Sskrll
552a6b7db3Sskrll static void move_members (bfd *, char **files_to_move);
562a6b7db3Sskrll static void replace_members
57*e072ec67Schristos (bfd *, char **files_to_replace, bool quick);
582a6b7db3Sskrll static void print_descr (bfd * abfd);
592a6b7db3Sskrll static void write_archive (bfd *);
602a6b7db3Sskrll static int ranlib_only (const char *archname);
612a6b7db3Sskrll static int ranlib_touch (const char *archname);
622a6b7db3Sskrll static void usage (int);
632a6b7db3Sskrll
642a6b7db3Sskrll /** Globals and flags. */
652a6b7db3Sskrll
662a6b7db3Sskrll static int mri_mode;
672a6b7db3Sskrll
682a6b7db3Sskrll /* This flag distinguishes between ar and ranlib:
692a6b7db3Sskrll 1 means this is 'ranlib'; 0 means this is 'ar'.
702a6b7db3Sskrll -1 means if we should use argv[0] to decide. */
712a6b7db3Sskrll extern int is_ranlib;
722a6b7db3Sskrll
732a6b7db3Sskrll /* Nonzero means don't warn about creating the archive file if necessary. */
742a6b7db3Sskrll int silent_create = 0;
752a6b7db3Sskrll
762a6b7db3Sskrll /* Nonzero means describe each action performed. */
772a6b7db3Sskrll int verbose = 0;
782a6b7db3Sskrll
79916041edSchristos /* Nonzero means display offsets of files in the archive. */
80916041edSchristos int display_offsets = 0;
81916041edSchristos
822a6b7db3Sskrll /* Nonzero means preserve dates of members when extracting them. */
832a6b7db3Sskrll int preserve_dates = 0;
842a6b7db3Sskrll
852a6b7db3Sskrll /* Nonzero means don't replace existing members whose dates are more recent
862a6b7db3Sskrll than the corresponding files. */
872a6b7db3Sskrll int newer_only = 0;
882a6b7db3Sskrll
892a6b7db3Sskrll /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
902a6b7db3Sskrll member). -1 means we've been explicitly asked to not write a symbol table;
912a6b7db3Sskrll +1 means we've been explicitly asked to write it;
922a6b7db3Sskrll 0 is the default.
932a6b7db3Sskrll Traditionally, the default in BSD has been to not write the table.
942a6b7db3Sskrll However, for POSIX.2 compliance the default is now to write a symbol table
952a6b7db3Sskrll if any of the members are object files. */
962a6b7db3Sskrll int write_armap = 0;
972a6b7db3Sskrll
98abf07352Sskrll /* Operate in deterministic mode: write zero for timestamps, uids,
99abf07352Sskrll and gids for archive members and the archive symbol table, and write
100abf07352Sskrll consistent file modes. */
1014c43201bSchristos int deterministic = -1; /* Determinism indeterminate. */
102abf07352Sskrll
1032a6b7db3Sskrll /* Nonzero means it's the name of an existing member; position new or moved
1042a6b7db3Sskrll files with respect to this one. */
1052a6b7db3Sskrll char *posname = NULL;
1062a6b7db3Sskrll
1072a6b7db3Sskrll /* Sez how to use `posname': pos_before means position before that member.
1082a6b7db3Sskrll pos_after means position after that member. pos_end means always at end.
1092a6b7db3Sskrll pos_default means default appropriately. For the latter two, `posname'
1102a6b7db3Sskrll should also be zero. */
1112a6b7db3Sskrll enum pos
1122a6b7db3Sskrll {
1132a6b7db3Sskrll pos_default, pos_before, pos_after, pos_end
1142a6b7db3Sskrll } postype = pos_default;
1152a6b7db3Sskrll
1164c43201bSchristos enum operations
1174c43201bSchristos {
1184c43201bSchristos none = 0, del, replace, print_table,
1194c43201bSchristos print_files, extract, move, quick_append
1204c43201bSchristos } operation = none;
1214c43201bSchristos
1222a6b7db3Sskrll static bfd **
1232a6b7db3Sskrll get_pos_bfd (bfd **, enum pos, const char *);
1242a6b7db3Sskrll
1252a6b7db3Sskrll /* For extract/delete only. If COUNTED_NAME_MODE is TRUE, we only
1262a6b7db3Sskrll extract the COUNTED_NAME_COUNTER instance of that name. */
127*e072ec67Schristos static bool counted_name_mode = 0;
1282a6b7db3Sskrll static int counted_name_counter = 0;
1292a6b7db3Sskrll
1302a6b7db3Sskrll /* Whether to truncate names of files stored in the archive. */
131*e072ec67Schristos static bool ar_truncate = false;
1322a6b7db3Sskrll
1332a6b7db3Sskrll /* Whether to use a full file name match when searching an archive.
1342a6b7db3Sskrll This is convenient for archives created by the Microsoft lib
1352a6b7db3Sskrll program. */
136*e072ec67Schristos static bool full_pathname = false;
1372a6b7db3Sskrll
1382a6b7db3Sskrll /* Whether to create a "thin" archive (symbol index only -- no files). */
139*e072ec67Schristos static bool make_thin_archive = false;
140*e072ec67Schristos
141*e072ec67Schristos #define LIBDEPS "__.LIBDEP"
142*e072ec67Schristos /* Text to store in the __.LIBDEP archive element for the linker to use. */
143*e072ec67Schristos static char * libdeps = NULL;
144*e072ec67Schristos static bfd * libdeps_bfd = NULL;
1452a6b7db3Sskrll
1464c43201bSchristos static int show_version = 0;
1474c43201bSchristos
1484c43201bSchristos static int show_help = 0;
1494c43201bSchristos
150438aacb6Schristos #if BFD_SUPPORTS_PLUGINS
151438aacb6Schristos static const char *plugin_target = "plugin";
152438aacb6Schristos #else
1538443c5fcSchristos static const char *plugin_target = NULL;
154438aacb6Schristos #endif
1558443c5fcSchristos
1564c43201bSchristos static const char *target = NULL;
1574c43201bSchristos
158c21fdd85Schristos enum long_option_numbers
159c21fdd85Schristos {
160c21fdd85Schristos OPTION_PLUGIN = 201,
161c21fdd85Schristos OPTION_TARGET,
162c21fdd85Schristos OPTION_OUTPUT
163c21fdd85Schristos };
164c21fdd85Schristos
165c21fdd85Schristos static const char * output_dir = NULL;
1664c43201bSchristos
1674c43201bSchristos static struct option long_options[] =
1684c43201bSchristos {
1694c43201bSchristos {"help", no_argument, &show_help, 1},
1704c43201bSchristos {"plugin", required_argument, NULL, OPTION_PLUGIN},
1714c43201bSchristos {"target", required_argument, NULL, OPTION_TARGET},
1724c43201bSchristos {"version", no_argument, &show_version, 1},
173c21fdd85Schristos {"output", required_argument, NULL, OPTION_OUTPUT},
174*e072ec67Schristos {"record-libdeps", required_argument, NULL, 'l'},
175*e072ec67Schristos {"thin", no_argument, NULL, 'T'},
1764c43201bSchristos {NULL, no_argument, NULL, 0}
1774c43201bSchristos };
1784c43201bSchristos
1792a6b7db3Sskrll int interactive = 0;
1802a6b7db3Sskrll
1812a6b7db3Sskrll static void
mri_emul(void)1822a6b7db3Sskrll mri_emul (void)
1832a6b7db3Sskrll {
1842a6b7db3Sskrll interactive = isatty (fileno (stdin));
1852a6b7db3Sskrll yyparse ();
1862a6b7db3Sskrll }
1872a6b7db3Sskrll
1882a6b7db3Sskrll /* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero,
1892a6b7db3Sskrll COUNT is the length of the FILES chain; FUNCTION is called on each entry
1902a6b7db3Sskrll whose name matches one in FILES. */
1912a6b7db3Sskrll
1922a6b7db3Sskrll static void
map_over_members(bfd * arch,void (* function)(bfd *),char ** files,int count)1932a6b7db3Sskrll map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
1942a6b7db3Sskrll {
1952a6b7db3Sskrll bfd *head;
1962a6b7db3Sskrll int match_count;
1972a6b7db3Sskrll
1982a6b7db3Sskrll if (count == 0)
1992a6b7db3Sskrll {
2002a6b7db3Sskrll for (head = arch->archive_next; head; head = head->archive_next)
2012a6b7db3Sskrll {
2022a6b7db3Sskrll PROGRESS (1);
2032a6b7db3Sskrll function (head);
2042a6b7db3Sskrll }
2052a6b7db3Sskrll return;
2062a6b7db3Sskrll }
2072a6b7db3Sskrll
2082a6b7db3Sskrll /* This may appear to be a baroque way of accomplishing what we want.
2092a6b7db3Sskrll However we have to iterate over the filenames in order to notice where
2102a6b7db3Sskrll a filename is requested but does not exist in the archive. Ditto
2112a6b7db3Sskrll mapping over each file each time -- we want to hack multiple
2122a6b7db3Sskrll references. */
2132a6b7db3Sskrll
214438aacb6Schristos for (head = arch->archive_next; head; head = head->archive_next)
215438aacb6Schristos head->archive_pass = 0;
216438aacb6Schristos
2172a6b7db3Sskrll for (; count > 0; files++, count--)
2182a6b7db3Sskrll {
219*e072ec67Schristos bool found = false;
2202a6b7db3Sskrll
2212a6b7db3Sskrll match_count = 0;
2222a6b7db3Sskrll for (head = arch->archive_next; head; head = head->archive_next)
2232a6b7db3Sskrll {
2242a6b7db3Sskrll const char * filename;
2252a6b7db3Sskrll
2262a6b7db3Sskrll PROGRESS (1);
227438aacb6Schristos /* PR binutils/15796: Once an archive element has been matched
228438aacb6Schristos do not match it again. If the user provides multiple same-named
229438aacb6Schristos parameters on the command line their intent is to match multiple
230438aacb6Schristos same-named entries in the archive, not the same entry multiple
231438aacb6Schristos times. */
232438aacb6Schristos if (head->archive_pass)
233438aacb6Schristos continue;
234438aacb6Schristos
235*e072ec67Schristos filename = bfd_get_filename (head);
2362a6b7db3Sskrll if (filename == NULL)
2372a6b7db3Sskrll {
2382a6b7db3Sskrll /* Some archive formats don't get the filenames filled in
2392a6b7db3Sskrll until the elements are opened. */
2402a6b7db3Sskrll struct stat buf;
2412a6b7db3Sskrll bfd_stat_arch_elt (head, &buf);
2422a6b7db3Sskrll }
2432a6b7db3Sskrll else if (bfd_is_thin_archive (arch))
2442a6b7db3Sskrll {
2452a6b7db3Sskrll /* Thin archives store full pathnames. Need to normalize. */
2462a6b7db3Sskrll filename = normalize (filename, arch);
2472a6b7db3Sskrll }
2482a6b7db3Sskrll
2494c43201bSchristos if (filename != NULL
2504c43201bSchristos && !FILENAME_CMP (normalize (*files, arch), filename))
2512a6b7db3Sskrll {
2522a6b7db3Sskrll ++match_count;
2532a6b7db3Sskrll if (counted_name_mode
2542a6b7db3Sskrll && match_count != counted_name_counter)
2552a6b7db3Sskrll {
2562a6b7db3Sskrll /* Counting, and didn't match on count; go on to the
2572a6b7db3Sskrll next one. */
2582a6b7db3Sskrll continue;
2592a6b7db3Sskrll }
2602a6b7db3Sskrll
261*e072ec67Schristos found = true;
2622a6b7db3Sskrll function (head);
263438aacb6Schristos head->archive_pass = 1;
264438aacb6Schristos /* PR binutils/15796: Once a file has been matched, do not
265438aacb6Schristos match any more same-named files in the archive. If the
266438aacb6Schristos user does want to match multiple same-name files in an
267438aacb6Schristos archive they should provide multiple same-name parameters
268438aacb6Schristos to the ar command. */
269438aacb6Schristos break;
2702a6b7db3Sskrll }
2712a6b7db3Sskrll }
2722a6b7db3Sskrll
2732a6b7db3Sskrll if (!found)
2742a6b7db3Sskrll /* xgettext:c-format */
2752a6b7db3Sskrll fprintf (stderr, _("no entry %s in archive\n"), *files);
2762a6b7db3Sskrll }
2772a6b7db3Sskrll }
2782a6b7db3Sskrll
279*e072ec67Schristos bool operation_alters_arch = false;
2802a6b7db3Sskrll
2812a6b7db3Sskrll static void
usage(int help)2822a6b7db3Sskrll usage (int help)
2832a6b7db3Sskrll {
2842a6b7db3Sskrll FILE *s;
2852a6b7db3Sskrll
2868443c5fcSchristos #if BFD_SUPPORTS_PLUGINS
2874c43201bSchristos /* xgettext:c-format */
2884c43201bSchristos const char *command_line
289916041edSchristos = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilMNoOPsSTuvV]"
2904c43201bSchristos " [--plugin <name>] [member-name] [count] archive-file file...\n");
2914c43201bSchristos
2928443c5fcSchristos #else
2934c43201bSchristos /* xgettext:c-format */
2944c43201bSchristos const char *command_line
295916041edSchristos = _("Usage: %s [emulation options] [-]{dmpqrstx}[abcDfilMNoOPsSTuvV]"
2964c43201bSchristos " [member-name] [count] archive-file file...\n");
2978443c5fcSchristos #endif
298438aacb6Schristos s = help ? stdout : stderr;
299438aacb6Schristos
3008443c5fcSchristos fprintf (s, command_line, program_name);
3018443c5fcSchristos
3022a6b7db3Sskrll /* xgettext:c-format */
3032a6b7db3Sskrll fprintf (s, _(" %s -M [<mri-script]\n"), program_name);
3042a6b7db3Sskrll fprintf (s, _(" commands:\n"));
3052a6b7db3Sskrll fprintf (s, _(" d - delete file(s) from the archive\n"));
3062a6b7db3Sskrll fprintf (s, _(" m[ab] - move file(s) in the archive\n"));
3072a6b7db3Sskrll fprintf (s, _(" p - print file(s) found in the archive\n"));
3082a6b7db3Sskrll fprintf (s, _(" q[f] - quick append file(s) to the archive\n"));
3092a6b7db3Sskrll fprintf (s, _(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n"));
3108443c5fcSchristos fprintf (s, _(" s - act as ranlib\n"));
311916041edSchristos fprintf (s, _(" t[O][v] - display contents of the archive\n"));
3122a6b7db3Sskrll fprintf (s, _(" x[o] - extract file(s) from the archive\n"));
3132a6b7db3Sskrll fprintf (s, _(" command specific modifiers:\n"));
3142a6b7db3Sskrll fprintf (s, _(" [a] - put file(s) after [member-name]\n"));
3152a6b7db3Sskrll fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n"));
3164c43201bSchristos if (DEFAULT_AR_DETERMINISTIC)
3174c43201bSchristos {
3184c43201bSchristos fprintf (s, _("\
3194c43201bSchristos [D] - use zero for timestamps and uids/gids (default)\n"));
3204c43201bSchristos fprintf (s, _("\
3214c43201bSchristos [U] - use actual timestamps and uids/gids\n"));
3224c43201bSchristos }
3234c43201bSchristos else
3244c43201bSchristos {
3254c43201bSchristos fprintf (s, _("\
3264c43201bSchristos [D] - use zero for timestamps and uids/gids\n"));
3274c43201bSchristos fprintf (s, _("\
3284c43201bSchristos [U] - use actual timestamps and uids/gids (default)\n"));
3294c43201bSchristos }
3302a6b7db3Sskrll fprintf (s, _(" [N] - use instance [count] of name\n"));
3312a6b7db3Sskrll fprintf (s, _(" [f] - truncate inserted file names\n"));
3322a6b7db3Sskrll fprintf (s, _(" [P] - use full path names when matching\n"));
3332a6b7db3Sskrll fprintf (s, _(" [o] - preserve original dates\n"));
334916041edSchristos fprintf (s, _(" [O] - display offsets of files in the archive\n"));
3352a6b7db3Sskrll fprintf (s, _(" [u] - only replace files that are newer than current archive contents\n"));
3362a6b7db3Sskrll fprintf (s, _(" generic modifiers:\n"));
3372a6b7db3Sskrll fprintf (s, _(" [c] - do not warn if the library had to be created\n"));
3382a6b7db3Sskrll fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n"));
339*e072ec67Schristos fprintf (s, _(" [l <text> ] - specify the dependencies of this library\n"));
3402a6b7db3Sskrll fprintf (s, _(" [S] - do not build a symbol table\n"));
341*e072ec67Schristos fprintf (s, _(" [T] - deprecated, use --thin instead\n"));
3422a6b7db3Sskrll fprintf (s, _(" [v] - be verbose\n"));
3432a6b7db3Sskrll fprintf (s, _(" [V] - display the version number\n"));
3442a6b7db3Sskrll fprintf (s, _(" @<file> - read options from <file>\n"));
3454c43201bSchristos fprintf (s, _(" --target=BFDNAME - specify the target object format as BFDNAME\n"));
346c21fdd85Schristos fprintf (s, _(" --output=DIRNAME - specify the output directory for extraction operations\n"));
347*e072ec67Schristos fprintf (s, _(" --record-libdeps=<text> - specify the dependencies of this library\n"));
348*e072ec67Schristos fprintf (s, _(" --thin - make a thin archive\n"));
3498443c5fcSchristos #if BFD_SUPPORTS_PLUGINS
3508443c5fcSchristos fprintf (s, _(" optional:\n"));
3518443c5fcSchristos fprintf (s, _(" --plugin <p> - load the specified plugin\n"));
3528443c5fcSchristos #endif
3534c43201bSchristos
3542a6b7db3Sskrll ar_emul_usage (s);
3554c43201bSchristos
3564c43201bSchristos list_supported_targets (program_name, s);
3574c43201bSchristos
3584c43201bSchristos if (REPORT_BUGS_TO[0] && help)
3594c43201bSchristos fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
3604c43201bSchristos
3614c43201bSchristos xexit (help ? 0 : 1);
3622a6b7db3Sskrll }
3634c43201bSchristos
3644c43201bSchristos static void
ranlib_usage(int help)3654c43201bSchristos ranlib_usage (int help)
3662a6b7db3Sskrll {
3674c43201bSchristos FILE *s;
3684c43201bSchristos
3694c43201bSchristos s = help ? stdout : stderr;
3704c43201bSchristos
3712a6b7db3Sskrll /* xgettext:c-format */
3722a6b7db3Sskrll fprintf (s, _("Usage: %s [options] archive\n"), program_name);
3732a6b7db3Sskrll fprintf (s, _(" Generate an index to speed access to archives\n"));
3742a6b7db3Sskrll fprintf (s, _(" The options are:\n\
3758443c5fcSchristos @<file> Read options from <file>\n"));
3768443c5fcSchristos #if BFD_SUPPORTS_PLUGINS
3778443c5fcSchristos fprintf (s, _("\
3788443c5fcSchristos --plugin <name> Load the specified plugin\n"));
3798443c5fcSchristos #endif
3804c43201bSchristos if (DEFAULT_AR_DETERMINISTIC)
3814c43201bSchristos fprintf (s, _("\
3824c43201bSchristos -D Use zero for symbol map timestamp (default)\n\
3834c43201bSchristos -U Use an actual symbol map timestamp\n"));
3844c43201bSchristos else
3854c43201bSchristos fprintf (s, _("\
3864c43201bSchristos -D Use zero for symbol map timestamp\n\
3874c43201bSchristos -U Use actual symbol map timestamp (default)\n"));
3888443c5fcSchristos fprintf (s, _("\
3892a6b7db3Sskrll -t Update the archive's symbol map timestamp\n\
3902a6b7db3Sskrll -h --help Print this help message\n\
3912a6b7db3Sskrll -v --version Print version information\n"));
3922a6b7db3Sskrll
3932a6b7db3Sskrll list_supported_targets (program_name, s);
3942a6b7db3Sskrll
3952a6b7db3Sskrll if (REPORT_BUGS_TO[0] && help)
3962a6b7db3Sskrll fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
3972a6b7db3Sskrll
3982a6b7db3Sskrll xexit (help ? 0 : 1);
3992a6b7db3Sskrll }
4002a6b7db3Sskrll
4012a6b7db3Sskrll /* Normalize a file name specified on the command line into a file
4022a6b7db3Sskrll name which we will use in an archive. */
4032a6b7db3Sskrll
4042a6b7db3Sskrll static const char *
normalize(const char * file,bfd * abfd)4052a6b7db3Sskrll normalize (const char *file, bfd *abfd)
4062a6b7db3Sskrll {
4072a6b7db3Sskrll const char *filename;
4082a6b7db3Sskrll
4092a6b7db3Sskrll if (full_pathname)
4102a6b7db3Sskrll return file;
4112a6b7db3Sskrll
4128443c5fcSchristos filename = lbasename (file);
4132a6b7db3Sskrll
4142a6b7db3Sskrll if (ar_truncate
4152a6b7db3Sskrll && abfd != NULL
4162a6b7db3Sskrll && strlen (filename) > abfd->xvec->ar_max_namelen)
4172a6b7db3Sskrll {
4182a6b7db3Sskrll char *s;
4192a6b7db3Sskrll
4202a6b7db3Sskrll /* Space leak. */
4218443c5fcSchristos s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
4222a6b7db3Sskrll memcpy (s, filename, abfd->xvec->ar_max_namelen);
4232a6b7db3Sskrll s[abfd->xvec->ar_max_namelen] = '\0';
4242a6b7db3Sskrll filename = s;
4252a6b7db3Sskrll }
4262a6b7db3Sskrll
4272a6b7db3Sskrll return filename;
4282a6b7db3Sskrll }
4292a6b7db3Sskrll
4302a6b7db3Sskrll /* Remove any output file. This is only called via xatexit. */
4312a6b7db3Sskrll
4322a6b7db3Sskrll static const char *output_filename = NULL;
4332a6b7db3Sskrll static FILE *output_file = NULL;
4342a6b7db3Sskrll static bfd *output_bfd = NULL;
4352a6b7db3Sskrll
4362a6b7db3Sskrll static void
remove_output(void)4372a6b7db3Sskrll remove_output (void)
4382a6b7db3Sskrll {
4392a6b7db3Sskrll if (output_filename != NULL)
4402a6b7db3Sskrll {
4412a6b7db3Sskrll if (output_bfd != NULL)
4422a6b7db3Sskrll bfd_cache_close (output_bfd);
4432a6b7db3Sskrll if (output_file != NULL)
4442a6b7db3Sskrll fclose (output_file);
4452a6b7db3Sskrll unlink_if_ordinary (output_filename);
4462a6b7db3Sskrll }
4472a6b7db3Sskrll }
4482a6b7db3Sskrll
4494c43201bSchristos static char **
decode_options(int argc,char ** argv)4504c43201bSchristos decode_options (int argc, char **argv)
4512a6b7db3Sskrll {
4524c43201bSchristos int c;
4534c43201bSchristos
454c21fdd85Schristos /* Convert old-style ar call by exploding option element and rearranging
4554c43201bSchristos options accordingly. */
4564c43201bSchristos
457c21fdd85Schristos restart:
4584c43201bSchristos if (argc > 1 && argv[1][0] != '-')
4592a6b7db3Sskrll {
4604c43201bSchristos int new_argc; /* argc value for rearranged arguments */
4614c43201bSchristos char **new_argv; /* argv value for rearranged arguments */
4624c43201bSchristos char *const *in; /* cursor into original argv */
4634c43201bSchristos char **out; /* cursor into rearranged argv */
4644c43201bSchristos const char *letter; /* cursor into old option letters */
4654c43201bSchristos char buffer[3]; /* constructed option buffer */
4662a6b7db3Sskrll
4674c43201bSchristos /* Initialize a constructed option. */
4682a6b7db3Sskrll
4694c43201bSchristos buffer[0] = '-';
4704c43201bSchristos buffer[2] = '\0';
4712a6b7db3Sskrll
4724c43201bSchristos /* Allocate a new argument array, and copy program name in it. */
4732a6b7db3Sskrll
4744c43201bSchristos new_argc = argc - 1 + strlen (argv[1]);
4754c43201bSchristos new_argv = xmalloc ((new_argc + 1) * sizeof (*argv));
4764c43201bSchristos in = argv;
4774c43201bSchristos out = new_argv;
4784c43201bSchristos *out++ = *in++;
4794c43201bSchristos
4804c43201bSchristos /* Copy each old letter option as a separate option. */
4814c43201bSchristos
4824c43201bSchristos for (letter = *in++; *letter; letter++)
4832a6b7db3Sskrll {
4844c43201bSchristos buffer[1] = *letter;
4854c43201bSchristos *out++ = xstrdup (buffer);
4862a6b7db3Sskrll }
4872a6b7db3Sskrll
4884c43201bSchristos /* Copy all remaining options. */
4894c43201bSchristos
4904c43201bSchristos while (in < argv + argc)
4914c43201bSchristos *out++ = *in++;
4924c43201bSchristos *out = NULL;
4934c43201bSchristos
4944c43201bSchristos /* Replace the old option list by the new one. */
4954c43201bSchristos
4964c43201bSchristos argc = new_argc;
4974c43201bSchristos argv = new_argv;
4982a6b7db3Sskrll }
4992a6b7db3Sskrll
500*e072ec67Schristos while ((c = getopt_long (argc, argv, "hdmpqrtxl:coOVsSuvabiMNfPTDU",
5014c43201bSchristos long_options, NULL)) != EOF)
5022a6b7db3Sskrll {
5032a6b7db3Sskrll switch (c)
5042a6b7db3Sskrll {
5052a6b7db3Sskrll case 'd':
5062a6b7db3Sskrll case 'm':
5072a6b7db3Sskrll case 'p':
5082a6b7db3Sskrll case 'q':
5092a6b7db3Sskrll case 'r':
5102a6b7db3Sskrll case 't':
5112a6b7db3Sskrll case 'x':
5122a6b7db3Sskrll if (operation != none)
5132a6b7db3Sskrll fatal (_("two different operation options specified"));
5144c43201bSchristos break;
5154c43201bSchristos }
5164c43201bSchristos
5172a6b7db3Sskrll switch (c)
5182a6b7db3Sskrll {
5194c43201bSchristos case 'h':
5204c43201bSchristos show_help = 1;
5214c43201bSchristos break;
5222a6b7db3Sskrll case 'd':
5238443c5fcSchristos operation = del;
524*e072ec67Schristos operation_alters_arch = true;
5252a6b7db3Sskrll break;
5262a6b7db3Sskrll case 'm':
5272a6b7db3Sskrll operation = move;
528*e072ec67Schristos operation_alters_arch = true;
5292a6b7db3Sskrll break;
5302a6b7db3Sskrll case 'p':
5312a6b7db3Sskrll operation = print_files;
5322a6b7db3Sskrll break;
5332a6b7db3Sskrll case 'q':
5342a6b7db3Sskrll operation = quick_append;
535*e072ec67Schristos operation_alters_arch = true;
5362a6b7db3Sskrll break;
5372a6b7db3Sskrll case 'r':
5382a6b7db3Sskrll operation = replace;
539*e072ec67Schristos operation_alters_arch = true;
5402a6b7db3Sskrll break;
5412a6b7db3Sskrll case 't':
5422a6b7db3Sskrll operation = print_table;
5432a6b7db3Sskrll break;
5442a6b7db3Sskrll case 'x':
5452a6b7db3Sskrll operation = extract;
5462a6b7db3Sskrll break;
5472a6b7db3Sskrll case 'l':
548*e072ec67Schristos if (libdeps != NULL)
549*e072ec67Schristos fatal (_("libdeps specified more than once"));
550*e072ec67Schristos libdeps = optarg;
5512a6b7db3Sskrll break;
5522a6b7db3Sskrll case 'c':
5532a6b7db3Sskrll silent_create = 1;
5542a6b7db3Sskrll break;
5552a6b7db3Sskrll case 'o':
5562a6b7db3Sskrll preserve_dates = 1;
5572a6b7db3Sskrll break;
558916041edSchristos case 'O':
559916041edSchristos display_offsets = 1;
560916041edSchristos break;
5612a6b7db3Sskrll case 'V':
562*e072ec67Schristos show_version = true;
5632a6b7db3Sskrll break;
5642a6b7db3Sskrll case 's':
5652a6b7db3Sskrll write_armap = 1;
5662a6b7db3Sskrll break;
5672a6b7db3Sskrll case 'S':
5682a6b7db3Sskrll write_armap = -1;
5692a6b7db3Sskrll break;
5702a6b7db3Sskrll case 'u':
5712a6b7db3Sskrll newer_only = 1;
5722a6b7db3Sskrll break;
5732a6b7db3Sskrll case 'v':
5742a6b7db3Sskrll verbose = 1;
5752a6b7db3Sskrll break;
5762a6b7db3Sskrll case 'a':
5772a6b7db3Sskrll postype = pos_after;
5782a6b7db3Sskrll break;
5792a6b7db3Sskrll case 'b':
5802a6b7db3Sskrll postype = pos_before;
5812a6b7db3Sskrll break;
5822a6b7db3Sskrll case 'i':
5832a6b7db3Sskrll postype = pos_before;
5842a6b7db3Sskrll break;
5852a6b7db3Sskrll case 'M':
5862a6b7db3Sskrll mri_mode = 1;
5872a6b7db3Sskrll break;
5882a6b7db3Sskrll case 'N':
589*e072ec67Schristos counted_name_mode = true;
5902a6b7db3Sskrll break;
5912a6b7db3Sskrll case 'f':
592*e072ec67Schristos ar_truncate = true;
5932a6b7db3Sskrll break;
5942a6b7db3Sskrll case 'P':
595*e072ec67Schristos full_pathname = true;
5962a6b7db3Sskrll break;
5972a6b7db3Sskrll case 'T':
598*e072ec67Schristos make_thin_archive = true;
5992a6b7db3Sskrll break;
6008443c5fcSchristos case 'D':
601*e072ec67Schristos deterministic = true;
6028443c5fcSchristos break;
6034c43201bSchristos case 'U':
604*e072ec67Schristos deterministic = false;
6054c43201bSchristos break;
6064c43201bSchristos case OPTION_PLUGIN:
6074c43201bSchristos #if BFD_SUPPORTS_PLUGINS
6084c43201bSchristos bfd_plugin_set_plugin (optarg);
6094c43201bSchristos #else
6104c43201bSchristos fprintf (stderr, _("sorry - this program has been built without plugin support\n"));
6114c43201bSchristos xexit (1);
6124c43201bSchristos #endif
6134c43201bSchristos break;
6144c43201bSchristos case OPTION_TARGET:
6154c43201bSchristos target = optarg;
6164c43201bSchristos break;
617c21fdd85Schristos case OPTION_OUTPUT:
618c21fdd85Schristos output_dir = optarg;
619c21fdd85Schristos break;
6204c43201bSchristos case 0: /* A long option that just sets a flag. */
6214c43201bSchristos break;
6222a6b7db3Sskrll default:
6232a6b7db3Sskrll usage (0);
6242a6b7db3Sskrll }
6252a6b7db3Sskrll }
6262a6b7db3Sskrll
627c21fdd85Schristos /* PR 13256: Allow for the possibility that the first command line option
628c21fdd85Schristos started with a dash (eg --plugin) but then the following option(s) are
629c21fdd85Schristos old style, non-dash-prefixed versions. */
630c21fdd85Schristos if (operation == none && write_armap != 1 && !mri_mode
631c21fdd85Schristos && optind > 0 && optind < argc)
632c21fdd85Schristos {
633c21fdd85Schristos argv += (optind - 1);
634c21fdd85Schristos argc -= (optind - 1);
635c21fdd85Schristos optind = 0;
636c21fdd85Schristos goto restart;
637c21fdd85Schristos }
638c21fdd85Schristos
6394c43201bSchristos return &argv[optind];
6402a6b7db3Sskrll }
6414c43201bSchristos
6424c43201bSchristos /* If neither -D nor -U was specified explicitly,
6434c43201bSchristos then use the configured default. */
6444c43201bSchristos static void
default_deterministic(void)6454c43201bSchristos default_deterministic (void)
6464c43201bSchristos {
6474c43201bSchristos if (deterministic < 0)
6484c43201bSchristos deterministic = DEFAULT_AR_DETERMINISTIC;
6494c43201bSchristos }
6504c43201bSchristos
6514c43201bSchristos static void
ranlib_main(int argc,char ** argv)6524c43201bSchristos ranlib_main (int argc, char **argv)
6534c43201bSchristos {
6544c43201bSchristos int arg_index, status = 0;
655*e072ec67Schristos bool touch = false;
6564c43201bSchristos int c;
6574c43201bSchristos
6584c43201bSchristos while ((c = getopt_long (argc, argv, "DhHUvVt", long_options, NULL)) != EOF)
6594c43201bSchristos {
6604c43201bSchristos switch (c)
6614c43201bSchristos {
6624c43201bSchristos case 'D':
663*e072ec67Schristos deterministic = true;
6644c43201bSchristos break;
6654c43201bSchristos case 'U':
666*e072ec67Schristos deterministic = false;
6674c43201bSchristos break;
6684c43201bSchristos case 'h':
6694c43201bSchristos case 'H':
6704c43201bSchristos show_help = 1;
6714c43201bSchristos break;
6724c43201bSchristos case 't':
673*e072ec67Schristos touch = true;
6744c43201bSchristos break;
6754c43201bSchristos case 'v':
6764c43201bSchristos case 'V':
6774c43201bSchristos show_version = 1;
6784c43201bSchristos break;
6794c43201bSchristos
6804c43201bSchristos /* PR binutils/13493: Support plugins. */
6814c43201bSchristos case OPTION_PLUGIN:
6824c43201bSchristos #if BFD_SUPPORTS_PLUGINS
6834c43201bSchristos bfd_plugin_set_plugin (optarg);
6844c43201bSchristos #else
6854c43201bSchristos fprintf (stderr, _("sorry - this program has been built without plugin support\n"));
6864c43201bSchristos xexit (1);
6874c43201bSchristos #endif
6884c43201bSchristos break;
6894c43201bSchristos }
6904c43201bSchristos }
6914c43201bSchristos
6924c43201bSchristos if (argc < 2)
6934c43201bSchristos ranlib_usage (0);
6944c43201bSchristos
6954c43201bSchristos if (show_help)
6964c43201bSchristos ranlib_usage (1);
6974c43201bSchristos
6984c43201bSchristos if (show_version)
6994c43201bSchristos print_version ("ranlib");
7004c43201bSchristos
7014c43201bSchristos default_deterministic ();
7024c43201bSchristos
7034c43201bSchristos arg_index = optind;
7044c43201bSchristos
7054c43201bSchristos while (arg_index < argc)
7064c43201bSchristos {
7074c43201bSchristos if (! touch)
7084c43201bSchristos status |= ranlib_only (argv[arg_index]);
7094c43201bSchristos else
7104c43201bSchristos status |= ranlib_touch (argv[arg_index]);
7114c43201bSchristos ++arg_index;
7124c43201bSchristos }
7134c43201bSchristos
7144c43201bSchristos xexit (status);
7154c43201bSchristos }
7164c43201bSchristos
7174c43201bSchristos int main (int, char **);
7184c43201bSchristos
7194c43201bSchristos int
main(int argc,char ** argv)7204c43201bSchristos main (int argc, char **argv)
7214c43201bSchristos {
7224c43201bSchristos int arg_index;
7234c43201bSchristos char **files;
7244c43201bSchristos int file_count;
7254c43201bSchristos char *inarch_filename;
7264c43201bSchristos int i;
7274c43201bSchristos
728*e072ec67Schristos #ifdef HAVE_LC_MESSAGES
7294c43201bSchristos setlocale (LC_MESSAGES, "");
7304c43201bSchristos #endif
7314c43201bSchristos setlocale (LC_CTYPE, "");
7324c43201bSchristos bindtextdomain (PACKAGE, LOCALEDIR);
7334c43201bSchristos textdomain (PACKAGE);
7344c43201bSchristos
7354c43201bSchristos program_name = argv[0];
7364c43201bSchristos xmalloc_set_program_name (program_name);
737438aacb6Schristos bfd_set_error_program_name (program_name);
7384c43201bSchristos #if BFD_SUPPORTS_PLUGINS
7394c43201bSchristos bfd_plugin_set_program_name (program_name);
7404c43201bSchristos #endif
7414c43201bSchristos
7424c43201bSchristos expandargv (&argc, &argv);
7434c43201bSchristos
7444c43201bSchristos if (is_ranlib < 0)
7454c43201bSchristos {
7464c43201bSchristos const char *temp = lbasename (program_name);
7474c43201bSchristos
7484c43201bSchristos if (strlen (temp) >= 6
7494c43201bSchristos && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
7504c43201bSchristos is_ranlib = 1;
7514c43201bSchristos else
7524c43201bSchristos is_ranlib = 0;
7534c43201bSchristos }
7544c43201bSchristos
7554c43201bSchristos START_PROGRESS (program_name, 0);
7564c43201bSchristos
757c21fdd85Schristos if (bfd_init () != BFD_INIT_MAGIC)
758c21fdd85Schristos fatal (_("fatal error: libbfd ABI mismatch"));
7594c43201bSchristos set_default_bfd_target ();
7604c43201bSchristos
7614c43201bSchristos xatexit (remove_output);
7624c43201bSchristos
7634c43201bSchristos for (i = 1; i < argc; i++)
7644c43201bSchristos if (! ar_emul_parse_arg (argv[i]))
7654c43201bSchristos break;
7664c43201bSchristos argv += (i - 1);
7674c43201bSchristos argc -= (i - 1);
7684c43201bSchristos
7694c43201bSchristos if (is_ranlib)
7704c43201bSchristos ranlib_main (argc, argv);
7714c43201bSchristos
7724c43201bSchristos if (argc < 2)
7734c43201bSchristos usage (0);
7744c43201bSchristos
7754c43201bSchristos argv = decode_options (argc, argv);
7764c43201bSchristos
7774c43201bSchristos if (show_help)
7784c43201bSchristos usage (1);
7792a6b7db3Sskrll
7802a6b7db3Sskrll if (show_version)
7812a6b7db3Sskrll print_version ("ar");
7822a6b7db3Sskrll
7834c43201bSchristos arg_index = 0;
7842a6b7db3Sskrll
7852a6b7db3Sskrll if (mri_mode)
7862a6b7db3Sskrll {
787438aacb6Schristos default_deterministic ();
7882a6b7db3Sskrll mri_emul ();
7892a6b7db3Sskrll }
7902a6b7db3Sskrll else
7912a6b7db3Sskrll {
7922a6b7db3Sskrll bfd *arch;
7932a6b7db3Sskrll
794aa4b58b1Schristos /* Fail if no files are specified on the command line.
795aa4b58b1Schristos (But not for MRI mode which allows for reading arguments
796aa4b58b1Schristos and filenames from stdin). */
797aa4b58b1Schristos if (argv[arg_index] == NULL)
798aa4b58b1Schristos usage (0);
799aa4b58b1Schristos
8002a6b7db3Sskrll /* We don't use do_quick_append any more. Too many systems
8012a6b7db3Sskrll expect ar to always rebuild the symbol table even when q is
8022a6b7db3Sskrll used. */
8032a6b7db3Sskrll
8042a6b7db3Sskrll /* We can't write an armap when using ar q, so just do ar r
8052a6b7db3Sskrll instead. */
8062a6b7db3Sskrll if (operation == quick_append && write_armap)
8072a6b7db3Sskrll operation = replace;
8082a6b7db3Sskrll
8092a6b7db3Sskrll if ((operation == none || operation == print_table)
8102a6b7db3Sskrll && write_armap == 1)
8112a6b7db3Sskrll xexit (ranlib_only (argv[arg_index]));
8122a6b7db3Sskrll
8132a6b7db3Sskrll if (operation == none)
8142a6b7db3Sskrll fatal (_("no operation specified"));
8152a6b7db3Sskrll
8162a6b7db3Sskrll if (newer_only && operation != replace)
8172a6b7db3Sskrll fatal (_("`u' is only meaningful with the `r' option."));
8182a6b7db3Sskrll
8194c43201bSchristos if (newer_only && deterministic > 0)
820abf07352Sskrll fatal (_("`u' is not meaningful with the `D' option."));
821abf07352Sskrll
8224c43201bSchristos if (newer_only && deterministic < 0 && DEFAULT_AR_DETERMINISTIC)
8234c43201bSchristos non_fatal (_("\
8244c43201bSchristos `u' modifier ignored since `D' is the default (see `U')"));
8254c43201bSchristos
8264c43201bSchristos default_deterministic ();
8274c43201bSchristos
8282a6b7db3Sskrll if (postype != pos_default)
829aa4b58b1Schristos {
8302a6b7db3Sskrll posname = argv[arg_index++];
831aa4b58b1Schristos if (posname == NULL)
832aa4b58b1Schristos fatal (_("missing position arg."));
833aa4b58b1Schristos }
8342a6b7db3Sskrll
8352a6b7db3Sskrll if (counted_name_mode)
8362a6b7db3Sskrll {
8378443c5fcSchristos if (operation != extract && operation != del)
8382a6b7db3Sskrll fatal (_("`N' is only meaningful with the `x' and `d' options."));
839aa4b58b1Schristos if (argv[arg_index] == NULL)
840aa4b58b1Schristos fatal (_("`N' missing value."));
8412a6b7db3Sskrll counted_name_counter = atoi (argv[arg_index++]);
8422a6b7db3Sskrll if (counted_name_counter <= 0)
8432a6b7db3Sskrll fatal (_("Value for `N' must be positive."));
8442a6b7db3Sskrll }
8452a6b7db3Sskrll
8462a6b7db3Sskrll inarch_filename = argv[arg_index++];
847aa4b58b1Schristos if (inarch_filename == NULL)
848aa4b58b1Schristos usage (0);
8492a6b7db3Sskrll
8504c43201bSchristos for (file_count = 0; argv[arg_index + file_count] != NULL; file_count++)
8514c43201bSchristos continue;
8524c43201bSchristos
8534c43201bSchristos files = (file_count > 0) ? argv + arg_index : NULL;
8542a6b7db3Sskrll
8552a6b7db3Sskrll arch = open_inarch (inarch_filename,
8562a6b7db3Sskrll files == NULL ? (char *) NULL : files[0]);
8572a6b7db3Sskrll
8582a6b7db3Sskrll if (operation == extract && bfd_is_thin_archive (arch))
8592a6b7db3Sskrll fatal (_("`x' cannot be used on thin archives."));
8602a6b7db3Sskrll
861*e072ec67Schristos if (libdeps != NULL)
862*e072ec67Schristos {
863*e072ec67Schristos char **new_files;
864*e072ec67Schristos bfd_size_type reclen = strlen (libdeps) + 1;
865*e072ec67Schristos
866*e072ec67Schristos /* Create a bfd to contain the dependencies.
867*e072ec67Schristos It inherits its type from arch, but we must set the type to
868*e072ec67Schristos "binary" otherwise bfd_bwrite() will fail. After writing, we
869*e072ec67Schristos must set the type back to default otherwise adding it to the
870*e072ec67Schristos archive will fail. */
871*e072ec67Schristos libdeps_bfd = bfd_create (LIBDEPS, arch);
872*e072ec67Schristos if (libdeps_bfd == NULL)
873*e072ec67Schristos fatal (_("Cannot create libdeps record."));
874*e072ec67Schristos
875*e072ec67Schristos if (bfd_find_target ("binary", libdeps_bfd) == NULL)
876*e072ec67Schristos fatal (_("Cannot set libdeps record type to binary."));
877*e072ec67Schristos
878*e072ec67Schristos if (! bfd_set_format (libdeps_bfd, bfd_object))
879*e072ec67Schristos fatal (_("Cannot set libdeps object format."));
880*e072ec67Schristos
881*e072ec67Schristos if (! bfd_make_writable (libdeps_bfd))
882*e072ec67Schristos fatal (_("Cannot make libdeps object writable."));
883*e072ec67Schristos
884*e072ec67Schristos if (bfd_bwrite (libdeps, reclen, libdeps_bfd) != reclen)
885*e072ec67Schristos fatal (_("Cannot write libdeps record."));
886*e072ec67Schristos
887*e072ec67Schristos if (! bfd_make_readable (libdeps_bfd))
888*e072ec67Schristos fatal (_("Cannot make libdeps object readable."));
889*e072ec67Schristos
890*e072ec67Schristos if (bfd_find_target (plugin_target, libdeps_bfd) == NULL)
891*e072ec67Schristos fatal (_("Cannot reset libdeps record type."));
892*e072ec67Schristos
893*e072ec67Schristos /* Insert our libdeps record in 2nd slot of the list of files
894*e072ec67Schristos being operated on. We shouldn't use 1st slot, but we want
895*e072ec67Schristos to avoid having to search all the way to the end of an
896*e072ec67Schristos archive with a large number of members at link time. */
897*e072ec67Schristos new_files = xmalloc ((file_count + 2) * sizeof (*new_files));
898*e072ec67Schristos if (file_count)
899*e072ec67Schristos {
900*e072ec67Schristos new_files[0] = files[0];
901*e072ec67Schristos memcpy (new_files + 1, files, file_count * sizeof (*files));
902*e072ec67Schristos }
903*e072ec67Schristos new_files[file_count != 0] = LIBDEPS;
904*e072ec67Schristos file_count++;
905*e072ec67Schristos new_files[file_count] = NULL;
906*e072ec67Schristos files = new_files;
907*e072ec67Schristos }
908*e072ec67Schristos
9092a6b7db3Sskrll switch (operation)
9102a6b7db3Sskrll {
9112a6b7db3Sskrll case print_table:
9122a6b7db3Sskrll map_over_members (arch, print_descr, files, file_count);
9132a6b7db3Sskrll break;
9142a6b7db3Sskrll
9152a6b7db3Sskrll case print_files:
9162a6b7db3Sskrll map_over_members (arch, print_contents, files, file_count);
9172a6b7db3Sskrll break;
9182a6b7db3Sskrll
9192a6b7db3Sskrll case extract:
9202a6b7db3Sskrll map_over_members (arch, extract_file, files, file_count);
9212a6b7db3Sskrll break;
9222a6b7db3Sskrll
9238443c5fcSchristos case del:
9242a6b7db3Sskrll if (files != NULL)
9252a6b7db3Sskrll delete_members (arch, files);
9262a6b7db3Sskrll else
9272a6b7db3Sskrll output_filename = NULL;
9282a6b7db3Sskrll break;
9292a6b7db3Sskrll
9302a6b7db3Sskrll case move:
9314c43201bSchristos /* PR 12558: Creating and moving at the same time does
9324c43201bSchristos not make sense. Just create the archive instead. */
9334c43201bSchristos if (! silent_create)
9344c43201bSchristos {
9352a6b7db3Sskrll if (files != NULL)
9362a6b7db3Sskrll move_members (arch, files);
9372a6b7db3Sskrll else
9382a6b7db3Sskrll output_filename = NULL;
9392a6b7db3Sskrll break;
9404c43201bSchristos }
9414c43201bSchristos /* Fall through. */
9422a6b7db3Sskrll
9432a6b7db3Sskrll case replace:
9442a6b7db3Sskrll case quick_append:
9452a6b7db3Sskrll if (files != NULL || write_armap > 0)
9462a6b7db3Sskrll replace_members (arch, files, operation == quick_append);
9472a6b7db3Sskrll else
9482a6b7db3Sskrll output_filename = NULL;
9492a6b7db3Sskrll break;
9502a6b7db3Sskrll
9512a6b7db3Sskrll /* Shouldn't happen! */
9522a6b7db3Sskrll default:
9532a6b7db3Sskrll /* xgettext:c-format */
9542a6b7db3Sskrll fatal (_("internal error -- this option not implemented"));
9552a6b7db3Sskrll }
9562a6b7db3Sskrll }
9572a6b7db3Sskrll
9582a6b7db3Sskrll END_PROGRESS (program_name);
9592a6b7db3Sskrll
9602a6b7db3Sskrll xexit (0);
9612a6b7db3Sskrll return 0;
9622a6b7db3Sskrll }
9632a6b7db3Sskrll
9642a6b7db3Sskrll bfd *
open_inarch(const char * archive_filename,const char * file)9652a6b7db3Sskrll open_inarch (const char *archive_filename, const char *file)
9662a6b7db3Sskrll {
9672a6b7db3Sskrll bfd **last_one;
9682a6b7db3Sskrll bfd *next_one;
9692a6b7db3Sskrll struct stat sbuf;
9702a6b7db3Sskrll bfd *arch;
9712a6b7db3Sskrll char **matching;
9722a6b7db3Sskrll
9732a6b7db3Sskrll bfd_set_error (bfd_error_no_error);
9742a6b7db3Sskrll
9754c43201bSchristos if (target == NULL)
9768443c5fcSchristos target = plugin_target;
9772a6b7db3Sskrll
9782a6b7db3Sskrll if (stat (archive_filename, &sbuf) != 0)
9792a6b7db3Sskrll {
9802a6b7db3Sskrll #if !defined(__GO32__) || defined(__DJGPP__)
9812a6b7db3Sskrll
9822a6b7db3Sskrll /* FIXME: I don't understand why this fragment was ifndef'ed
9832a6b7db3Sskrll away for __GO32__; perhaps it was in the days of DJGPP v1.x.
9842a6b7db3Sskrll stat() works just fine in v2.x, so I think this should be
9852a6b7db3Sskrll removed. For now, I enable it for DJGPP v2. -- EZ. */
9862a6b7db3Sskrll
9872a6b7db3Sskrll /* KLUDGE ALERT! Temporary fix until I figger why
9882a6b7db3Sskrll stat() is wrong ... think it's buried in GO32's IDT - Jax */
9892a6b7db3Sskrll if (errno != ENOENT)
9902a6b7db3Sskrll bfd_fatal (archive_filename);
9912a6b7db3Sskrll #endif
9922a6b7db3Sskrll
9932a6b7db3Sskrll if (!operation_alters_arch)
9942a6b7db3Sskrll {
9952a6b7db3Sskrll fprintf (stderr, "%s: ", program_name);
9962a6b7db3Sskrll perror (archive_filename);
9972a6b7db3Sskrll maybequit ();
9982a6b7db3Sskrll return NULL;
9992a6b7db3Sskrll }
10002a6b7db3Sskrll
10014c43201bSchristos /* If the target isn't set, try to figure out the target to use
10024c43201bSchristos for the archive from the first object on the list. */
10034c43201bSchristos if (target == NULL && file != NULL)
10042a6b7db3Sskrll {
10052a6b7db3Sskrll bfd *obj;
10062a6b7db3Sskrll
10078443c5fcSchristos obj = bfd_openr (file, target);
10082a6b7db3Sskrll if (obj != NULL)
10092a6b7db3Sskrll {
10102a6b7db3Sskrll if (bfd_check_format (obj, bfd_object))
10112a6b7db3Sskrll target = bfd_get_target (obj);
10122a6b7db3Sskrll (void) bfd_close (obj);
10132a6b7db3Sskrll }
10142a6b7db3Sskrll }
10152a6b7db3Sskrll
10162a6b7db3Sskrll /* Create an empty archive. */
10172a6b7db3Sskrll arch = bfd_openw (archive_filename, target);
10182a6b7db3Sskrll if (arch == NULL
10192a6b7db3Sskrll || ! bfd_set_format (arch, bfd_archive)
10202a6b7db3Sskrll || ! bfd_close (arch))
10212a6b7db3Sskrll bfd_fatal (archive_filename);
10222a6b7db3Sskrll else if (!silent_create)
10232a6b7db3Sskrll non_fatal (_("creating %s"), archive_filename);
10242a6b7db3Sskrll
10252a6b7db3Sskrll /* If we die creating a new archive, don't leave it around. */
10262a6b7db3Sskrll output_filename = archive_filename;
10272a6b7db3Sskrll }
10282a6b7db3Sskrll
10292a6b7db3Sskrll arch = bfd_openr (archive_filename, target);
10302a6b7db3Sskrll if (arch == NULL)
10312a6b7db3Sskrll {
10322a6b7db3Sskrll bloser:
10332a6b7db3Sskrll bfd_fatal (archive_filename);
10342a6b7db3Sskrll }
10352a6b7db3Sskrll
10362a6b7db3Sskrll if (! bfd_check_format_matches (arch, bfd_archive, &matching))
10372a6b7db3Sskrll {
10382a6b7db3Sskrll bfd_nonfatal (archive_filename);
10392a6b7db3Sskrll if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
10402a6b7db3Sskrll list_matching_formats (matching);
10412a6b7db3Sskrll xexit (1);
10422a6b7db3Sskrll }
10432a6b7db3Sskrll
1044438aacb6Schristos if ((operation == replace || operation == quick_append)
1045438aacb6Schristos && bfd_openr_next_archived_file (arch, NULL) != NULL)
1046438aacb6Schristos {
1047438aacb6Schristos /* PR 15140: Catch attempts to convert a normal
1048438aacb6Schristos archive into a thin archive or vice versa. */
1049438aacb6Schristos if (make_thin_archive && ! bfd_is_thin_archive (arch))
1050438aacb6Schristos {
1051438aacb6Schristos fatal (_("Cannot convert existing library %s to thin format"),
1052438aacb6Schristos bfd_get_filename (arch));
1053438aacb6Schristos goto bloser;
1054438aacb6Schristos }
1055438aacb6Schristos else if (! make_thin_archive && bfd_is_thin_archive (arch))
1056438aacb6Schristos {
1057438aacb6Schristos fatal (_("Cannot convert existing thin library %s to normal format"),
1058438aacb6Schristos bfd_get_filename (arch));
1059438aacb6Schristos goto bloser;
1060438aacb6Schristos }
1061438aacb6Schristos }
1062438aacb6Schristos
10632a6b7db3Sskrll last_one = &(arch->archive_next);
10642a6b7db3Sskrll /* Read all the contents right away, regardless. */
10652a6b7db3Sskrll for (next_one = bfd_openr_next_archived_file (arch, NULL);
10662a6b7db3Sskrll next_one;
10672a6b7db3Sskrll next_one = bfd_openr_next_archived_file (arch, next_one))
10682a6b7db3Sskrll {
10692a6b7db3Sskrll PROGRESS (1);
10702a6b7db3Sskrll *last_one = next_one;
10712a6b7db3Sskrll last_one = &next_one->archive_next;
10722a6b7db3Sskrll }
10732a6b7db3Sskrll *last_one = (bfd *) NULL;
10742a6b7db3Sskrll if (bfd_get_error () != bfd_error_no_more_archived_files)
10752a6b7db3Sskrll goto bloser;
10762a6b7db3Sskrll return arch;
10772a6b7db3Sskrll }
10782a6b7db3Sskrll
10792a6b7db3Sskrll static void
print_contents(bfd * abfd)10802a6b7db3Sskrll print_contents (bfd *abfd)
10812a6b7db3Sskrll {
10824c43201bSchristos bfd_size_type ncopied = 0;
10834c43201bSchristos bfd_size_type size;
10848443c5fcSchristos char *cbuf = (char *) xmalloc (BUFSIZE);
10852a6b7db3Sskrll struct stat buf;
10864c43201bSchristos
10872a6b7db3Sskrll if (bfd_stat_arch_elt (abfd, &buf) != 0)
10882a6b7db3Sskrll /* xgettext:c-format */
10892a6b7db3Sskrll fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
10902a6b7db3Sskrll
10912a6b7db3Sskrll if (verbose)
10928443c5fcSchristos printf ("\n<%s>\n\n", bfd_get_filename (abfd));
10932a6b7db3Sskrll
10942a6b7db3Sskrll bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
10952a6b7db3Sskrll
10962a6b7db3Sskrll size = buf.st_size;
10972a6b7db3Sskrll while (ncopied < size)
10982a6b7db3Sskrll {
10994c43201bSchristos bfd_size_type nread;
11004c43201bSchristos bfd_size_type tocopy = size - ncopied;
11012a6b7db3Sskrll
11022a6b7db3Sskrll if (tocopy > BUFSIZE)
11032a6b7db3Sskrll tocopy = BUFSIZE;
11042a6b7db3Sskrll
11054c43201bSchristos nread = bfd_bread (cbuf, tocopy, abfd);
11062a6b7db3Sskrll if (nread != tocopy)
11072a6b7db3Sskrll /* xgettext:c-format */
11082a6b7db3Sskrll fatal (_("%s is not a valid archive"),
1109ad93aa80Schristos bfd_get_filename (abfd->my_archive));
11102a6b7db3Sskrll
11114c43201bSchristos /* fwrite in mingw32 may return int instead of bfd_size_type. Cast the
11124c43201bSchristos return value to bfd_size_type to avoid comparison between signed and
11132a6b7db3Sskrll unsigned values. */
11144c43201bSchristos if ((bfd_size_type) fwrite (cbuf, 1, nread, stdout) != nread)
11152a6b7db3Sskrll fatal ("stdout: %s", strerror (errno));
11162a6b7db3Sskrll ncopied += tocopy;
11172a6b7db3Sskrll }
11182a6b7db3Sskrll free (cbuf);
11192a6b7db3Sskrll }
11202a6b7db3Sskrll
1121c21fdd85Schristos
1122c21fdd85Schristos static FILE * open_output_file (bfd *) ATTRIBUTE_RETURNS_NONNULL;
1123c21fdd85Schristos
1124c21fdd85Schristos static FILE *
open_output_file(bfd * abfd)1125c21fdd85Schristos open_output_file (bfd * abfd)
1126c21fdd85Schristos {
1127c21fdd85Schristos output_filename = bfd_get_filename (abfd);
1128c21fdd85Schristos
1129c21fdd85Schristos /* PR binutils/17533: Do not allow directory traversal
1130c21fdd85Schristos outside of the current directory tree - unless the
1131c21fdd85Schristos user has explicitly specified an output directory. */
1132c21fdd85Schristos if (! is_valid_archive_path (output_filename))
1133c21fdd85Schristos {
1134c21fdd85Schristos char * base = (char *) lbasename (output_filename);
1135c21fdd85Schristos
1136c21fdd85Schristos non_fatal (_("illegal output pathname for archive member: %s, using '%s' instead"),
1137c21fdd85Schristos output_filename, base);
1138c21fdd85Schristos output_filename = base;
1139c21fdd85Schristos }
1140c21fdd85Schristos
1141c21fdd85Schristos if (output_dir)
1142c21fdd85Schristos {
1143c21fdd85Schristos size_t len = strlen (output_dir);
1144c21fdd85Schristos
1145c21fdd85Schristos if (len > 0)
1146c21fdd85Schristos {
1147c21fdd85Schristos /* FIXME: There is a memory leak here, but it is not serious. */
1148c21fdd85Schristos if (IS_DIR_SEPARATOR (output_dir [len - 1]))
1149c21fdd85Schristos output_filename = concat (output_dir, output_filename, NULL);
1150c21fdd85Schristos else
1151c21fdd85Schristos output_filename = concat (output_dir, "/", output_filename, NULL);
1152c21fdd85Schristos }
1153c21fdd85Schristos }
1154c21fdd85Schristos
1155c21fdd85Schristos if (verbose)
1156c21fdd85Schristos printf ("x - %s\n", output_filename);
1157c21fdd85Schristos
1158c21fdd85Schristos FILE * ostream = fopen (output_filename, FOPEN_WB);
1159c21fdd85Schristos if (ostream == NULL)
1160c21fdd85Schristos {
1161c21fdd85Schristos perror (output_filename);
1162c21fdd85Schristos xexit (1);
1163c21fdd85Schristos }
1164c21fdd85Schristos
1165c21fdd85Schristos return ostream;
1166c21fdd85Schristos }
1167c21fdd85Schristos
11682a6b7db3Sskrll /* Extract a member of the archive into its own file.
11692a6b7db3Sskrll
11702a6b7db3Sskrll We defer opening the new file until after we have read a BUFSIZ chunk of the
11712a6b7db3Sskrll old one, since we know we have just read the archive header for the old
11722a6b7db3Sskrll one. Since most members are shorter than BUFSIZ, this means we will read
11732a6b7db3Sskrll the old header, read the old data, write a new inode for the new file, and
11742a6b7db3Sskrll write the new data, and be done. This 'optimization' is what comes from
11752a6b7db3Sskrll sitting next to a bare disk and hearing it every time it seeks. -- Gnu
11762a6b7db3Sskrll Gilmore */
11772a6b7db3Sskrll
11782a6b7db3Sskrll void
extract_file(bfd * abfd)11792a6b7db3Sskrll extract_file (bfd *abfd)
11802a6b7db3Sskrll {
11814c43201bSchristos bfd_size_type size;
11822a6b7db3Sskrll struct stat buf;
11832a6b7db3Sskrll
1184*e072ec67Schristos if (preserve_dates)
1185*e072ec67Schristos memset (&buf, 0, sizeof (buf));
1186*e072ec67Schristos
11872a6b7db3Sskrll if (bfd_stat_arch_elt (abfd, &buf) != 0)
11882a6b7db3Sskrll /* xgettext:c-format */
11892a6b7db3Sskrll fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
11902a6b7db3Sskrll size = buf.st_size;
11912a6b7db3Sskrll
11922a6b7db3Sskrll bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
11932a6b7db3Sskrll
1194c21fdd85Schristos output_file = NULL;
11952a6b7db3Sskrll if (size == 0)
11962a6b7db3Sskrll {
1197c21fdd85Schristos output_file = open_output_file (abfd);
11982a6b7db3Sskrll }
11992a6b7db3Sskrll else
1200c21fdd85Schristos {
1201c21fdd85Schristos bfd_size_type ncopied = 0;
1202c21fdd85Schristos char *cbuf = (char *) xmalloc (BUFSIZE);
1203c21fdd85Schristos
12042a6b7db3Sskrll while (ncopied < size)
12052a6b7db3Sskrll {
1206c21fdd85Schristos bfd_size_type nread, tocopy;
1207c21fdd85Schristos
12082a6b7db3Sskrll tocopy = size - ncopied;
12092a6b7db3Sskrll if (tocopy > BUFSIZE)
12102a6b7db3Sskrll tocopy = BUFSIZE;
12112a6b7db3Sskrll
12124c43201bSchristos nread = bfd_bread (cbuf, tocopy, abfd);
12132a6b7db3Sskrll if (nread != tocopy)
12142a6b7db3Sskrll /* xgettext:c-format */
12152a6b7db3Sskrll fatal (_("%s is not a valid archive"),
1216ad93aa80Schristos bfd_get_filename (abfd->my_archive));
12172a6b7db3Sskrll
1218c21fdd85Schristos /* See comment above; this saves disk arm motion. */
1219c21fdd85Schristos if (output_file == NULL)
1220c21fdd85Schristos output_file = open_output_file (abfd);
12212a6b7db3Sskrll
12224c43201bSchristos /* fwrite in mingw32 may return int instead of bfd_size_type. Cast
12234c43201bSchristos the return value to bfd_size_type to avoid comparison between
12242a6b7db3Sskrll signed and unsigned values. */
1225c21fdd85Schristos if ((bfd_size_type) fwrite (cbuf, 1, nread, output_file) != nread)
12262a6b7db3Sskrll fatal ("%s: %s", output_filename, strerror (errno));
1227c21fdd85Schristos
12282a6b7db3Sskrll ncopied += tocopy;
12292a6b7db3Sskrll }
12302a6b7db3Sskrll
1231c21fdd85Schristos free (cbuf);
1232c21fdd85Schristos }
1233c21fdd85Schristos
1234c21fdd85Schristos fclose (output_file);
12352a6b7db3Sskrll
12362a6b7db3Sskrll output_file = NULL;
12372a6b7db3Sskrll
1238c21fdd85Schristos chmod (output_filename, buf.st_mode);
12392a6b7db3Sskrll
12402a6b7db3Sskrll if (preserve_dates)
12412a6b7db3Sskrll {
12422a6b7db3Sskrll /* Set access time to modification time. Only st_mtime is
12432a6b7db3Sskrll initialized by bfd_stat_arch_elt. */
12442a6b7db3Sskrll buf.st_atime = buf.st_mtime;
1245c21fdd85Schristos set_times (output_filename, &buf);
12462a6b7db3Sskrll }
12472a6b7db3Sskrll
1248c21fdd85Schristos output_filename = NULL;
12492a6b7db3Sskrll }
12502a6b7db3Sskrll
12512a6b7db3Sskrll static void
write_archive(bfd * iarch)12522a6b7db3Sskrll write_archive (bfd *iarch)
12532a6b7db3Sskrll {
12542a6b7db3Sskrll bfd *obfd;
12552a6b7db3Sskrll char *old_name, *new_name;
12562a6b7db3Sskrll bfd *contents_head = iarch->archive_next;
1257*e072ec67Schristos int tmpfd = -1;
12582a6b7db3Sskrll
1259*e072ec67Schristos old_name = xstrdup (bfd_get_filename (iarch));
1260*e072ec67Schristos new_name = make_tempname (old_name, &tmpfd);
12612a6b7db3Sskrll
12622a6b7db3Sskrll if (new_name == NULL)
12634c43201bSchristos bfd_fatal (_("could not create temporary file whilst writing archive"));
12642a6b7db3Sskrll
12652a6b7db3Sskrll output_filename = new_name;
12662a6b7db3Sskrll
1267*e072ec67Schristos obfd = bfd_fdopenw (new_name, bfd_get_target (iarch), tmpfd);
12682a6b7db3Sskrll
12692a6b7db3Sskrll if (obfd == NULL)
1270*e072ec67Schristos {
1271*e072ec67Schristos close (tmpfd);
12722a6b7db3Sskrll bfd_fatal (old_name);
1273*e072ec67Schristos }
12742a6b7db3Sskrll
12752a6b7db3Sskrll output_bfd = obfd;
12762a6b7db3Sskrll
12772a6b7db3Sskrll bfd_set_format (obfd, bfd_archive);
12782a6b7db3Sskrll
12792a6b7db3Sskrll /* Request writing the archive symbol table unless we've
12802a6b7db3Sskrll been explicitly requested not to. */
12812a6b7db3Sskrll obfd->has_armap = write_armap >= 0;
12822a6b7db3Sskrll
12832a6b7db3Sskrll if (ar_truncate)
12842a6b7db3Sskrll {
12852a6b7db3Sskrll /* This should really use bfd_set_file_flags, but that rejects
12862a6b7db3Sskrll archives. */
12872a6b7db3Sskrll obfd->flags |= BFD_TRADITIONAL_FORMAT;
12882a6b7db3Sskrll }
12892a6b7db3Sskrll
1290abf07352Sskrll if (deterministic)
1291abf07352Sskrll obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
1292abf07352Sskrll
1293c21fdd85Schristos if (full_pathname)
1294c21fdd85Schristos obfd->flags |= BFD_ARCHIVE_FULL_PATH;
1295c21fdd85Schristos
12962a6b7db3Sskrll if (make_thin_archive || bfd_is_thin_archive (iarch))
1297*e072ec67Schristos bfd_set_thin_archive (obfd, true);
12982a6b7db3Sskrll
12992a6b7db3Sskrll if (!bfd_set_archive_head (obfd, contents_head))
13002a6b7db3Sskrll bfd_fatal (old_name);
13012a6b7db3Sskrll
1302*e072ec67Schristos tmpfd = dup (tmpfd);
13032a6b7db3Sskrll if (!bfd_close (obfd))
13042a6b7db3Sskrll bfd_fatal (old_name);
13052a6b7db3Sskrll
13062a6b7db3Sskrll output_bfd = NULL;
13072a6b7db3Sskrll output_filename = NULL;
13082a6b7db3Sskrll
13092a6b7db3Sskrll /* We don't care if this fails; we might be creating the archive. */
13102a6b7db3Sskrll bfd_close (iarch);
13112a6b7db3Sskrll
1312*e072ec67Schristos if (smart_rename (new_name, old_name, tmpfd, NULL, false) != 0)
13132a6b7db3Sskrll xexit (1);
13144c43201bSchristos free (old_name);
1315aa4b58b1Schristos free (new_name);
13162a6b7db3Sskrll }
13172a6b7db3Sskrll
13182a6b7db3Sskrll /* Return a pointer to the pointer to the entry which should be rplacd'd
13192a6b7db3Sskrll into when altering. DEFAULT_POS should be how to interpret pos_default,
13202a6b7db3Sskrll and should be a pos value. */
13212a6b7db3Sskrll
13222a6b7db3Sskrll static bfd **
get_pos_bfd(bfd ** contents,enum pos default_pos,const char * default_posname)13232a6b7db3Sskrll get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
13242a6b7db3Sskrll {
13252a6b7db3Sskrll bfd **after_bfd = contents;
13262a6b7db3Sskrll enum pos realpos;
13272a6b7db3Sskrll const char *realposname;
13282a6b7db3Sskrll
13292a6b7db3Sskrll if (postype == pos_default)
13302a6b7db3Sskrll {
13312a6b7db3Sskrll realpos = default_pos;
13322a6b7db3Sskrll realposname = default_posname;
13332a6b7db3Sskrll }
13342a6b7db3Sskrll else
13352a6b7db3Sskrll {
13362a6b7db3Sskrll realpos = postype;
13372a6b7db3Sskrll realposname = posname;
13382a6b7db3Sskrll }
13392a6b7db3Sskrll
13402a6b7db3Sskrll if (realpos == pos_end)
13412a6b7db3Sskrll {
13422a6b7db3Sskrll while (*after_bfd)
13432a6b7db3Sskrll after_bfd = &((*after_bfd)->archive_next);
13442a6b7db3Sskrll }
13452a6b7db3Sskrll else
13462a6b7db3Sskrll {
13472a6b7db3Sskrll for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
1348*e072ec67Schristos if (FILENAME_CMP (bfd_get_filename (*after_bfd), realposname) == 0)
13492a6b7db3Sskrll {
13502a6b7db3Sskrll if (realpos == pos_after)
13512a6b7db3Sskrll after_bfd = &(*after_bfd)->archive_next;
13522a6b7db3Sskrll break;
13532a6b7db3Sskrll }
13542a6b7db3Sskrll }
13552a6b7db3Sskrll return after_bfd;
13562a6b7db3Sskrll }
13572a6b7db3Sskrll
13582a6b7db3Sskrll static void
delete_members(bfd * arch,char ** files_to_delete)13592a6b7db3Sskrll delete_members (bfd *arch, char **files_to_delete)
13602a6b7db3Sskrll {
13612a6b7db3Sskrll bfd **current_ptr_ptr;
1362*e072ec67Schristos bool found;
1363*e072ec67Schristos bool something_changed = false;
13642a6b7db3Sskrll int match_count;
13652a6b7db3Sskrll
13662a6b7db3Sskrll for (; *files_to_delete != NULL; ++files_to_delete)
13672a6b7db3Sskrll {
13682a6b7db3Sskrll /* In a.out systems, the armap is optional. It's also called
13692a6b7db3Sskrll __.SYMDEF. So if the user asked to delete it, we should remember
13702a6b7db3Sskrll that fact. This isn't quite right for COFF systems (where
13712a6b7db3Sskrll __.SYMDEF might be regular member), but it's very unlikely
13722a6b7db3Sskrll to be a problem. FIXME */
13732a6b7db3Sskrll
13742a6b7db3Sskrll if (!strcmp (*files_to_delete, "__.SYMDEF"))
13752a6b7db3Sskrll {
1376*e072ec67Schristos arch->has_armap = false;
13772a6b7db3Sskrll write_armap = -1;
13782a6b7db3Sskrll continue;
13792a6b7db3Sskrll }
13802a6b7db3Sskrll
1381*e072ec67Schristos found = false;
13822a6b7db3Sskrll match_count = 0;
13832a6b7db3Sskrll current_ptr_ptr = &(arch->archive_next);
13842a6b7db3Sskrll while (*current_ptr_ptr)
13852a6b7db3Sskrll {
13862a6b7db3Sskrll if (FILENAME_CMP (normalize (*files_to_delete, arch),
1387*e072ec67Schristos bfd_get_filename (*current_ptr_ptr)) == 0)
13882a6b7db3Sskrll {
13892a6b7db3Sskrll ++match_count;
13902a6b7db3Sskrll if (counted_name_mode
13912a6b7db3Sskrll && match_count != counted_name_counter)
13922a6b7db3Sskrll {
13932a6b7db3Sskrll /* Counting, and didn't match on count; go on to the
13942a6b7db3Sskrll next one. */
13952a6b7db3Sskrll }
13962a6b7db3Sskrll else
13972a6b7db3Sskrll {
1398*e072ec67Schristos found = true;
1399*e072ec67Schristos something_changed = true;
14002a6b7db3Sskrll if (verbose)
14012a6b7db3Sskrll printf ("d - %s\n",
14022a6b7db3Sskrll *files_to_delete);
14032a6b7db3Sskrll *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
14042a6b7db3Sskrll goto next_file;
14052a6b7db3Sskrll }
14062a6b7db3Sskrll }
14072a6b7db3Sskrll
14082a6b7db3Sskrll current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
14092a6b7db3Sskrll }
14102a6b7db3Sskrll
14112a6b7db3Sskrll if (verbose && !found)
14122a6b7db3Sskrll {
14132a6b7db3Sskrll /* xgettext:c-format */
14142a6b7db3Sskrll printf (_("No member named `%s'\n"), *files_to_delete);
14152a6b7db3Sskrll }
14162a6b7db3Sskrll next_file:
14172a6b7db3Sskrll ;
14182a6b7db3Sskrll }
14192a6b7db3Sskrll
14202a6b7db3Sskrll if (something_changed)
14212a6b7db3Sskrll write_archive (arch);
14222a6b7db3Sskrll else
14232a6b7db3Sskrll output_filename = NULL;
14242a6b7db3Sskrll }
14252a6b7db3Sskrll
14262a6b7db3Sskrll
14272a6b7db3Sskrll /* Reposition existing members within an archive */
14282a6b7db3Sskrll
14292a6b7db3Sskrll static void
move_members(bfd * arch,char ** files_to_move)14302a6b7db3Sskrll move_members (bfd *arch, char **files_to_move)
14312a6b7db3Sskrll {
14322a6b7db3Sskrll bfd **after_bfd; /* New entries go after this one */
14332a6b7db3Sskrll bfd **current_ptr_ptr; /* cdr pointer into contents */
14342a6b7db3Sskrll
14352a6b7db3Sskrll for (; *files_to_move; ++files_to_move)
14362a6b7db3Sskrll {
14372a6b7db3Sskrll current_ptr_ptr = &(arch->archive_next);
14382a6b7db3Sskrll while (*current_ptr_ptr)
14392a6b7db3Sskrll {
14402a6b7db3Sskrll bfd *current_ptr = *current_ptr_ptr;
14412a6b7db3Sskrll if (FILENAME_CMP (normalize (*files_to_move, arch),
1442*e072ec67Schristos bfd_get_filename (current_ptr)) == 0)
14432a6b7db3Sskrll {
14442a6b7db3Sskrll /* Move this file to the end of the list - first cut from
14452a6b7db3Sskrll where it is. */
14468443c5fcSchristos bfd *link_bfd;
14472a6b7db3Sskrll *current_ptr_ptr = current_ptr->archive_next;
14482a6b7db3Sskrll
14492a6b7db3Sskrll /* Now glue to end */
14502a6b7db3Sskrll after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
14518443c5fcSchristos link_bfd = *after_bfd;
14522a6b7db3Sskrll *after_bfd = current_ptr;
14538443c5fcSchristos current_ptr->archive_next = link_bfd;
14542a6b7db3Sskrll
14552a6b7db3Sskrll if (verbose)
14562a6b7db3Sskrll printf ("m - %s\n", *files_to_move);
14572a6b7db3Sskrll
14582a6b7db3Sskrll goto next_file;
14592a6b7db3Sskrll }
14602a6b7db3Sskrll
14612a6b7db3Sskrll current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
14622a6b7db3Sskrll }
14632a6b7db3Sskrll /* xgettext:c-format */
1464*e072ec67Schristos fatal (_("no entry %s in archive %s!"), *files_to_move,
1465*e072ec67Schristos bfd_get_filename (arch));
14662a6b7db3Sskrll
14672a6b7db3Sskrll next_file:;
14682a6b7db3Sskrll }
14692a6b7db3Sskrll
14702a6b7db3Sskrll write_archive (arch);
14712a6b7db3Sskrll }
14722a6b7db3Sskrll
14732a6b7db3Sskrll /* Ought to default to replacing in place, but this is existing practice! */
14742a6b7db3Sskrll
14752a6b7db3Sskrll static void
replace_members(bfd * arch,char ** files_to_move,bool quick)1476*e072ec67Schristos replace_members (bfd *arch, char **files_to_move, bool quick)
14772a6b7db3Sskrll {
1478*e072ec67Schristos bool changed = false;
14792a6b7db3Sskrll bfd **after_bfd; /* New entries go after this one. */
14802a6b7db3Sskrll bfd *current;
14812a6b7db3Sskrll bfd **current_ptr;
14822a6b7db3Sskrll
14832a6b7db3Sskrll while (files_to_move && *files_to_move)
14842a6b7db3Sskrll {
14852a6b7db3Sskrll if (! quick)
14862a6b7db3Sskrll {
14872a6b7db3Sskrll current_ptr = &arch->archive_next;
14882a6b7db3Sskrll while (*current_ptr)
14892a6b7db3Sskrll {
14902a6b7db3Sskrll current = *current_ptr;
14912a6b7db3Sskrll
14922a6b7db3Sskrll /* For compatibility with existing ar programs, we
14932a6b7db3Sskrll permit the same file to be added multiple times. */
14942a6b7db3Sskrll if (FILENAME_CMP (normalize (*files_to_move, arch),
1495*e072ec67Schristos normalize (bfd_get_filename (current), arch)) == 0
14962a6b7db3Sskrll && current->arelt_data != NULL)
14972a6b7db3Sskrll {
1498*e072ec67Schristos bool replaced;
14992a6b7db3Sskrll if (newer_only)
15002a6b7db3Sskrll {
15012a6b7db3Sskrll struct stat fsbuf, asbuf;
15022a6b7db3Sskrll
15032a6b7db3Sskrll if (stat (*files_to_move, &fsbuf) != 0)
15042a6b7db3Sskrll {
15052a6b7db3Sskrll if (errno != ENOENT)
15062a6b7db3Sskrll bfd_fatal (*files_to_move);
15072a6b7db3Sskrll goto next_file;
15082a6b7db3Sskrll }
15092a6b7db3Sskrll if (bfd_stat_arch_elt (current, &asbuf) != 0)
15102a6b7db3Sskrll /* xgettext:c-format */
15112a6b7db3Sskrll fatal (_("internal stat error on %s"),
1512*e072ec67Schristos bfd_get_filename (current));
15132a6b7db3Sskrll
15142a6b7db3Sskrll if (fsbuf.st_mtime <= asbuf.st_mtime)
15152a6b7db3Sskrll goto next_file;
15162a6b7db3Sskrll }
15172a6b7db3Sskrll
15182a6b7db3Sskrll after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
1519*e072ec67Schristos bfd_get_filename (current));
1520*e072ec67Schristos if (libdeps_bfd != NULL
1521*e072ec67Schristos && FILENAME_CMP (normalize (*files_to_move, arch),
1522*e072ec67Schristos LIBDEPS) == 0)
1523*e072ec67Schristos {
1524*e072ec67Schristos replaced = ar_emul_replace_bfd (after_bfd, libdeps_bfd,
1525*e072ec67Schristos verbose);
1526*e072ec67Schristos }
1527*e072ec67Schristos else
1528*e072ec67Schristos {
1529*e072ec67Schristos replaced = ar_emul_replace (after_bfd, *files_to_move,
1530*e072ec67Schristos target, verbose);
1531*e072ec67Schristos }
1532*e072ec67Schristos if (replaced)
15332a6b7db3Sskrll {
15342a6b7db3Sskrll /* Snip out this entry from the chain. */
15352a6b7db3Sskrll *current_ptr = (*current_ptr)->archive_next;
1536*e072ec67Schristos changed = true;
15372a6b7db3Sskrll }
15382a6b7db3Sskrll
15392a6b7db3Sskrll goto next_file;
15402a6b7db3Sskrll }
15412a6b7db3Sskrll current_ptr = &(current->archive_next);
15422a6b7db3Sskrll }
15432a6b7db3Sskrll }
15442a6b7db3Sskrll
15452a6b7db3Sskrll /* Add to the end of the archive. */
15462a6b7db3Sskrll after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
15472a6b7db3Sskrll
1548*e072ec67Schristos if (libdeps_bfd != NULL
1549*e072ec67Schristos && FILENAME_CMP (normalize (*files_to_move, arch), LIBDEPS) == 0)
1550*e072ec67Schristos {
1551*e072ec67Schristos changed |= ar_emul_append_bfd (after_bfd, libdeps_bfd,
1552*e072ec67Schristos verbose, make_thin_archive);
1553*e072ec67Schristos }
1554*e072ec67Schristos else
1555*e072ec67Schristos {
1556*e072ec67Schristos changed |= ar_emul_append (after_bfd, *files_to_move, target,
1557*e072ec67Schristos verbose, make_thin_archive);
1558*e072ec67Schristos }
15592a6b7db3Sskrll
15602a6b7db3Sskrll next_file:;
15612a6b7db3Sskrll
15622a6b7db3Sskrll files_to_move++;
15632a6b7db3Sskrll }
15642a6b7db3Sskrll
15652a6b7db3Sskrll if (changed)
15662a6b7db3Sskrll write_archive (arch);
15672a6b7db3Sskrll else
15682a6b7db3Sskrll output_filename = NULL;
15692a6b7db3Sskrll }
15702a6b7db3Sskrll
15712a6b7db3Sskrll static int
ranlib_only(const char * archname)15722a6b7db3Sskrll ranlib_only (const char *archname)
15732a6b7db3Sskrll {
15742a6b7db3Sskrll bfd *arch;
15752a6b7db3Sskrll
15762a6b7db3Sskrll if (get_file_size (archname) < 1)
15772a6b7db3Sskrll return 1;
15782a6b7db3Sskrll write_armap = 1;
15792a6b7db3Sskrll arch = open_inarch (archname, (char *) NULL);
15802a6b7db3Sskrll if (arch == NULL)
15812a6b7db3Sskrll xexit (1);
15822a6b7db3Sskrll write_archive (arch);
15832a6b7db3Sskrll return 0;
15842a6b7db3Sskrll }
15852a6b7db3Sskrll
15862a6b7db3Sskrll /* Update the timestamp of the symbol map of an archive. */
15872a6b7db3Sskrll
15882a6b7db3Sskrll static int
ranlib_touch(const char * archname)15892a6b7db3Sskrll ranlib_touch (const char *archname)
15902a6b7db3Sskrll {
15912a6b7db3Sskrll #ifdef __GO32__
15922a6b7db3Sskrll /* I don't think updating works on go32. */
15932a6b7db3Sskrll ranlib_only (archname);
15942a6b7db3Sskrll #else
15952a6b7db3Sskrll int f;
15962a6b7db3Sskrll bfd *arch;
15972a6b7db3Sskrll char **matching;
15982a6b7db3Sskrll
15992a6b7db3Sskrll if (get_file_size (archname) < 1)
16002a6b7db3Sskrll return 1;
16012a6b7db3Sskrll f = open (archname, O_RDWR | O_BINARY, 0);
16022a6b7db3Sskrll if (f < 0)
16032a6b7db3Sskrll {
16042a6b7db3Sskrll bfd_set_error (bfd_error_system_call);
16052a6b7db3Sskrll bfd_fatal (archname);
16062a6b7db3Sskrll }
16072a6b7db3Sskrll
16082a6b7db3Sskrll arch = bfd_fdopenr (archname, (const char *) NULL, f);
16092a6b7db3Sskrll if (arch == NULL)
16102a6b7db3Sskrll bfd_fatal (archname);
16112a6b7db3Sskrll if (! bfd_check_format_matches (arch, bfd_archive, &matching))
16122a6b7db3Sskrll {
16132a6b7db3Sskrll bfd_nonfatal (archname);
16142a6b7db3Sskrll if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
16152a6b7db3Sskrll list_matching_formats (matching);
16162a6b7db3Sskrll xexit (1);
16172a6b7db3Sskrll }
16182a6b7db3Sskrll
16192a6b7db3Sskrll if (! bfd_has_map (arch))
16202a6b7db3Sskrll /* xgettext:c-format */
16212a6b7db3Sskrll fatal (_("%s: no archive map to update"), archname);
16222a6b7db3Sskrll
16234c43201bSchristos if (deterministic)
16244c43201bSchristos arch->flags |= BFD_DETERMINISTIC_OUTPUT;
16254c43201bSchristos
16262a6b7db3Sskrll bfd_update_armap_timestamp (arch);
16272a6b7db3Sskrll
16282a6b7db3Sskrll if (! bfd_close (arch))
16292a6b7db3Sskrll bfd_fatal (archname);
16302a6b7db3Sskrll #endif
16312a6b7db3Sskrll return 0;
16322a6b7db3Sskrll }
16332a6b7db3Sskrll
16342a6b7db3Sskrll /* Things which are interesting to map over all or some of the files: */
16352a6b7db3Sskrll
16362a6b7db3Sskrll static void
print_descr(bfd * abfd)16372a6b7db3Sskrll print_descr (bfd *abfd)
16382a6b7db3Sskrll {
1639916041edSchristos print_arelt_descr (stdout, abfd, verbose, display_offsets);
16402a6b7db3Sskrll }
1641