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