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