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