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