file zh_CN.gmo was initially added on branch binutils-2_17-branch.
[binutils.git] / binutils / ar.c
blobfe1c6402222d4166f373de729a0abb3d2d55b281
1 /* ar.c - Archive modify and extract.
2 Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3 2001, 2002, 2003, 2004, 2005
4 Free Software Foundation, Inc.
6 This file is part of GNU Binutils.
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
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
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.
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
20 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
23 Bugs: should use getopt the way tar does (complete w/optional -) and
24 should have long options too. GNU ar used to check file against filesystem
25 in quick_update and replace operations (would check mtime). Doesn't warn
26 when name truncated. No way to specify pos_end. Error messages should be
27 more consistent. */
29 #include "bfd.h"
30 #include "libiberty.h"
31 #include "progress.h"
32 #include "bucomm.h"
33 #include "aout/ar.h"
34 #include "libbfd.h"
35 #include "arsup.h"
36 #include "filenames.h"
37 #include "binemul.h"
38 #include <sys/stat.h>
40 #ifdef __GO32___
41 #define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
42 #else
43 #define EXT_NAME_LEN 6 /* ditto for *NIX */
44 #endif
46 /* We need to open files in binary modes on system where that makes a
47 difference. */
48 #ifndef O_BINARY
49 #define O_BINARY 0
50 #endif
52 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */
54 struct ar_hdr *
55 bfd_special_undocumented_glue (bfd * abfd, const char *filename);
57 /* Static declarations */
59 static void mri_emul (void);
60 static const char *normalize (const char *, bfd *);
61 static void remove_output (void);
62 static void map_over_members (bfd *, void (*)(bfd *), char **, int);
63 static void print_contents (bfd * member);
64 static void delete_members (bfd *, char **files_to_delete);
66 static void move_members (bfd *, char **files_to_move);
67 static void replace_members
68 (bfd *, char **files_to_replace, bfd_boolean quick);
69 static void print_descr (bfd * abfd);
70 static void write_archive (bfd *);
71 static void ranlib_only (const char *archname);
72 static void ranlib_touch (const char *archname);
73 static void usage (int);
75 /** Globals and flags */
77 static int mri_mode;
79 /* This flag distinguishes between ar and ranlib:
80 1 means this is 'ranlib'; 0 means this is 'ar'.
81 -1 means if we should use argv[0] to decide. */
82 extern int is_ranlib;
84 /* Nonzero means don't warn about creating the archive file if necessary. */
85 int silent_create = 0;
87 /* Nonzero means describe each action performed. */
88 int verbose = 0;
90 /* Nonzero means preserve dates of members when extracting them. */
91 int preserve_dates = 0;
93 /* Nonzero means don't replace existing members whose dates are more recent
94 than the corresponding files. */
95 int newer_only = 0;
97 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
98 member). -1 means we've been explicitly asked to not write a symbol table;
99 +1 means we've been explicitly asked to write it;
100 0 is the default.
101 Traditionally, the default in BSD has been to not write the table.
102 However, for POSIX.2 compliance the default is now to write a symbol table
103 if any of the members are object files. */
104 int write_armap = 0;
106 /* Nonzero means it's the name of an existing member; position new or moved
107 files with respect to this one. */
108 char *posname = NULL;
110 /* Sez how to use `posname': pos_before means position before that member.
111 pos_after means position after that member. pos_end means always at end.
112 pos_default means default appropriately. For the latter two, `posname'
113 should also be zero. */
114 enum pos
116 pos_default, pos_before, pos_after, pos_end
117 } postype = pos_default;
119 static bfd **
120 get_pos_bfd (bfd **, enum pos, const char *);
122 /* For extract/delete only. If COUNTED_NAME_MODE is TRUE, we only
123 extract the COUNTED_NAME_COUNTER instance of that name. */
124 static bfd_boolean counted_name_mode = 0;
125 static int counted_name_counter = 0;
127 /* Whether to truncate names of files stored in the archive. */
128 static bfd_boolean ar_truncate = FALSE;
130 /* Whether to use a full file name match when searching an archive.
131 This is convenient for archives created by the Microsoft lib
132 program. */
133 static bfd_boolean full_pathname = FALSE;
135 int interactive = 0;
137 static void
138 mri_emul (void)
140 interactive = isatty (fileno (stdin));
141 yyparse ();
144 /* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero,
145 COUNT is the length of the FILES chain; FUNCTION is called on each entry
146 whose name matches one in FILES. */
148 static void
149 map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
151 bfd *head;
152 int match_count;
154 if (count == 0)
156 for (head = arch->next; head; head = head->next)
158 PROGRESS (1);
159 function (head);
161 return;
164 /* This may appear to be a baroque way of accomplishing what we want.
165 However we have to iterate over the filenames in order to notice where
166 a filename is requested but does not exist in the archive. Ditto
167 mapping over each file each time -- we want to hack multiple
168 references. */
170 for (; count > 0; files++, count--)
172 bfd_boolean found = FALSE;
174 match_count = 0;
175 for (head = arch->next; head; head = head->next)
177 PROGRESS (1);
178 if (head->filename == NULL)
180 /* Some archive formats don't get the filenames filled in
181 until the elements are opened. */
182 struct stat buf;
183 bfd_stat_arch_elt (head, &buf);
185 if ((head->filename != NULL) &&
186 (!FILENAME_CMP (normalize (*files, arch), head->filename)))
188 ++match_count;
189 if (counted_name_mode
190 && match_count != counted_name_counter)
192 /* Counting, and didn't match on count; go on to the
193 next one. */
194 continue;
197 found = TRUE;
198 function (head);
201 if (!found)
202 /* xgettext:c-format */
203 fprintf (stderr, _("no entry %s in archive\n"), *files);
207 bfd_boolean operation_alters_arch = FALSE;
209 static void
210 usage (int help)
212 FILE *s;
214 s = help ? stdout : stderr;
216 if (! is_ranlib)
218 /* xgettext:c-format */
219 fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
220 program_name);
221 /* xgettext:c-format */
222 fprintf (s, _(" %s -M [<mri-script]\n"), program_name);
223 fprintf (s, _(" commands:\n"));
224 fprintf (s, _(" d - delete file(s) from the archive\n"));
225 fprintf (s, _(" m[ab] - move file(s) in the archive\n"));
226 fprintf (s, _(" p - print file(s) found in the archive\n"));
227 fprintf (s, _(" q[f] - quick append file(s) to the archive\n"));
228 fprintf (s, _(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n"));
229 fprintf (s, _(" t - display contents of archive\n"));
230 fprintf (s, _(" x[o] - extract file(s) from the archive\n"));
231 fprintf (s, _(" command specific modifiers:\n"));
232 fprintf (s, _(" [a] - put file(s) after [member-name]\n"));
233 fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n"));
234 fprintf (s, _(" [N] - use instance [count] of name\n"));
235 fprintf (s, _(" [f] - truncate inserted file names\n"));
236 fprintf (s, _(" [P] - use full path names when matching\n"));
237 fprintf (s, _(" [o] - preserve original dates\n"));
238 fprintf (s, _(" [u] - only replace files that are newer than current archive contents\n"));
239 fprintf (s, _(" generic modifiers:\n"));
240 fprintf (s, _(" [c] - do not warn if the library had to be created\n"));
241 fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n"));
242 fprintf (s, _(" [S] - do not build a symbol table\n"));
243 fprintf (s, _(" [v] - be verbose\n"));
244 fprintf (s, _(" [V] - display the version number\n"));
245 fprintf (s, _(" @<file> - read options from <file>\n"));
247 ar_emul_usage (s);
249 else
251 /* xgettext:c-format */
252 fprintf (s, _("Usage: %s [options] archive\n"), program_name);
253 fprintf (s, _(" Generate an index to speed access to archives\n"));
254 fprintf (s, _(" The options are:\n\
255 @<file> Read options from <file>\n\
256 -h --help Print this help message\n\
257 -V --version Print version information\n"));
260 list_supported_targets (program_name, stderr);
262 if (help)
263 fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
265 xexit (help ? 0 : 1);
268 /* Normalize a file name specified on the command line into a file
269 name which we will use in an archive. */
271 static const char *
272 normalize (const char *file, bfd *abfd)
274 const char *filename;
276 if (full_pathname)
277 return file;
279 filename = strrchr (file, '/');
280 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
282 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
283 char *bslash = strrchr (file, '\\');
284 if (filename == NULL || (bslash != NULL && bslash > filename))
285 filename = bslash;
286 if (filename == NULL && file[0] != '\0' && file[1] == ':')
287 filename = file + 1;
289 #endif
290 if (filename != (char *) NULL)
291 filename++;
292 else
293 filename = file;
295 if (ar_truncate
296 && abfd != NULL
297 && strlen (filename) > abfd->xvec->ar_max_namelen)
299 char *s;
301 /* Space leak. */
302 s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
303 memcpy (s, filename, abfd->xvec->ar_max_namelen);
304 s[abfd->xvec->ar_max_namelen] = '\0';
305 filename = s;
308 return filename;
311 /* Remove any output file. This is only called via xatexit. */
313 static const char *output_filename = NULL;
314 static FILE *output_file = NULL;
315 static bfd *output_bfd = NULL;
317 static void
318 remove_output (void)
320 if (output_filename != NULL)
322 if (output_bfd != NULL)
323 bfd_cache_close (output_bfd);
324 if (output_file != NULL)
325 fclose (output_file);
326 unlink_if_ordinary (output_filename);
330 /* The option parsing should be in its own function.
331 It will be when I have getopt working. */
333 int main (int, char **);
336 main (int argc, char **argv)
338 char *arg_ptr;
339 char c;
340 enum
342 none = 0, delete, replace, print_table,
343 print_files, extract, move, quick_append
344 } operation = none;
345 int arg_index;
346 char **files;
347 int file_count;
348 char *inarch_filename;
349 int show_version;
350 int i;
351 int do_posix = 0;
353 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
354 setlocale (LC_MESSAGES, "");
355 #endif
356 #if defined (HAVE_SETLOCALE)
357 setlocale (LC_CTYPE, "");
358 #endif
359 bindtextdomain (PACKAGE, LOCALEDIR);
360 textdomain (PACKAGE);
362 program_name = argv[0];
363 xmalloc_set_program_name (program_name);
365 expandargv (&argc, &argv);
367 if (is_ranlib < 0)
369 char *temp;
371 temp = strrchr (program_name, '/');
372 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
374 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
375 char *bslash = strrchr (program_name, '\\');
376 if (temp == NULL || (bslash != NULL && bslash > temp))
377 temp = bslash;
378 if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
379 temp = program_name + 1;
381 #endif
382 if (temp == NULL)
383 temp = program_name;
384 else
385 ++temp;
386 if (strlen (temp) >= 6
387 && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
388 is_ranlib = 1;
389 else
390 is_ranlib = 0;
393 if (argc > 1 && argv[1][0] == '-')
395 if (strcmp (argv[1], "--help") == 0)
396 usage (1);
397 else if (strcmp (argv[1], "--version") == 0)
399 if (is_ranlib)
400 print_version ("ranlib");
401 else
402 print_version ("ar");
406 START_PROGRESS (program_name, 0);
408 bfd_init ();
409 set_default_bfd_target ();
411 show_version = 0;
413 xatexit (remove_output);
415 for (i = 1; i < argc; i++)
416 if (! ar_emul_parse_arg (argv[i]))
417 break;
418 argv += (i - 1);
419 argc -= (i - 1);
421 if (is_ranlib)
423 bfd_boolean touch = FALSE;
425 if (argc < 2
426 || strcmp (argv[1], "--help") == 0
427 || strcmp (argv[1], "-h") == 0
428 || strcmp (argv[1], "-H") == 0)
429 usage (0);
430 if (strcmp (argv[1], "-V") == 0
431 || strcmp (argv[1], "-v") == 0
432 || strncmp (argv[1], "--v", 3) == 0)
433 print_version ("ranlib");
434 arg_index = 1;
435 if (strcmp (argv[1], "-t") == 0)
437 ++arg_index;
438 touch = TRUE;
440 while (arg_index < argc)
442 if (! touch)
443 ranlib_only (argv[arg_index]);
444 else
445 ranlib_touch (argv[arg_index]);
446 ++arg_index;
448 xexit (0);
451 if (argc == 2 && strcmp (argv[1], "-M") == 0)
453 mri_emul ();
454 xexit (0);
457 if (argc < 2)
458 usage (0);
460 arg_index = 1;
461 arg_ptr = argv[arg_index];
463 if (*arg_ptr == '-')
465 /* When the first option starts with '-' we support POSIX-compatible
466 option parsing. */
467 do_posix = 1;
468 ++arg_ptr; /* compatibility */
473 while ((c = *arg_ptr++) != '\0')
475 switch (c)
477 case 'd':
478 case 'm':
479 case 'p':
480 case 'q':
481 case 'r':
482 case 't':
483 case 'x':
484 if (operation != none)
485 fatal (_("two different operation options specified"));
486 switch (c)
488 case 'd':
489 operation = delete;
490 operation_alters_arch = TRUE;
491 break;
492 case 'm':
493 operation = move;
494 operation_alters_arch = TRUE;
495 break;
496 case 'p':
497 operation = print_files;
498 break;
499 case 'q':
500 operation = quick_append;
501 operation_alters_arch = TRUE;
502 break;
503 case 'r':
504 operation = replace;
505 operation_alters_arch = TRUE;
506 break;
507 case 't':
508 operation = print_table;
509 break;
510 case 'x':
511 operation = extract;
512 break;
514 case 'l':
515 break;
516 case 'c':
517 silent_create = 1;
518 break;
519 case 'o':
520 preserve_dates = 1;
521 break;
522 case 'V':
523 show_version = TRUE;
524 break;
525 case 's':
526 write_armap = 1;
527 break;
528 case 'S':
529 write_armap = -1;
530 break;
531 case 'u':
532 newer_only = 1;
533 break;
534 case 'v':
535 verbose = 1;
536 break;
537 case 'a':
538 postype = pos_after;
539 break;
540 case 'b':
541 postype = pos_before;
542 break;
543 case 'i':
544 postype = pos_before;
545 break;
546 case 'M':
547 mri_mode = 1;
548 break;
549 case 'N':
550 counted_name_mode = TRUE;
551 break;
552 case 'f':
553 ar_truncate = TRUE;
554 break;
555 case 'P':
556 full_pathname = TRUE;
557 break;
558 default:
559 /* xgettext:c-format */
560 non_fatal (_("illegal option -- %c"), c);
561 usage (0);
565 /* With POSIX-compatible option parsing continue with the next
566 argument if it starts with '-'. */
567 if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
568 arg_ptr = argv[++arg_index] + 1;
569 else
570 do_posix = 0;
572 while (do_posix);
574 if (show_version)
575 print_version ("ar");
577 ++arg_index;
578 if (arg_index >= argc)
579 usage (0);
581 if (mri_mode)
583 mri_emul ();
585 else
587 bfd *arch;
589 /* We don't use do_quick_append any more. Too many systems
590 expect ar to always rebuild the symbol table even when q is
591 used. */
593 /* We can't write an armap when using ar q, so just do ar r
594 instead. */
595 if (operation == quick_append && write_armap)
596 operation = replace;
598 if ((operation == none || operation == print_table)
599 && write_armap == 1)
601 ranlib_only (argv[arg_index]);
602 xexit (0);
605 if (operation == none)
606 fatal (_("no operation specified"));
608 if (newer_only && operation != replace)
609 fatal (_("`u' is only meaningful with the `r' option."));
611 if (postype != pos_default)
612 posname = argv[arg_index++];
614 if (counted_name_mode)
616 if (operation != extract && operation != delete)
617 fatal (_("`N' is only meaningful with the `x' and `d' options."));
618 counted_name_counter = atoi (argv[arg_index++]);
619 if (counted_name_counter <= 0)
620 fatal (_("Value for `N' must be positive."));
623 inarch_filename = argv[arg_index++];
625 files = arg_index < argc ? argv + arg_index : NULL;
626 file_count = argc - arg_index;
628 arch = open_inarch (inarch_filename,
629 files == NULL ? (char *) NULL : files[0]);
631 switch (operation)
633 case print_table:
634 map_over_members (arch, print_descr, files, file_count);
635 break;
637 case print_files:
638 map_over_members (arch, print_contents, files, file_count);
639 break;
641 case extract:
642 map_over_members (arch, extract_file, files, file_count);
643 break;
645 case delete:
646 if (files != NULL)
647 delete_members (arch, files);
648 else
649 output_filename = NULL;
650 break;
652 case move:
653 if (files != NULL)
654 move_members (arch, files);
655 else
656 output_filename = NULL;
657 break;
659 case replace:
660 case quick_append:
661 if (files != NULL || write_armap > 0)
662 replace_members (arch, files, operation == quick_append);
663 else
664 output_filename = NULL;
665 break;
667 /* Shouldn't happen! */
668 default:
669 /* xgettext:c-format */
670 fatal (_("internal error -- this option not implemented"));
674 END_PROGRESS (program_name);
676 xexit (0);
677 return 0;
680 bfd *
681 open_inarch (const char *archive_filename, const char *file)
683 const char *target;
684 bfd **last_one;
685 bfd *next_one;
686 struct stat sbuf;
687 bfd *arch;
688 char **matching;
690 bfd_set_error (bfd_error_no_error);
692 target = NULL;
694 if (stat (archive_filename, &sbuf) != 0)
696 #if !defined(__GO32__) || defined(__DJGPP__)
698 /* FIXME: I don't understand why this fragment was ifndef'ed
699 away for __GO32__; perhaps it was in the days of DJGPP v1.x.
700 stat() works just fine in v2.x, so I think this should be
701 removed. For now, I enable it for DJGPP v2. -- EZ. */
703 /* KLUDGE ALERT! Temporary fix until I figger why
704 stat() is wrong ... think it's buried in GO32's IDT - Jax */
705 if (errno != ENOENT)
706 bfd_fatal (archive_filename);
707 #endif
709 if (!operation_alters_arch)
711 fprintf (stderr, "%s: ", program_name);
712 perror (archive_filename);
713 maybequit ();
714 return NULL;
717 /* Try to figure out the target to use for the archive from the
718 first object on the list. */
719 if (file != NULL)
721 bfd *obj;
723 obj = bfd_openr (file, NULL);
724 if (obj != NULL)
726 if (bfd_check_format (obj, bfd_object))
727 target = bfd_get_target (obj);
728 (void) bfd_close (obj);
732 /* Create an empty archive. */
733 arch = bfd_openw (archive_filename, target);
734 if (arch == NULL
735 || ! bfd_set_format (arch, bfd_archive)
736 || ! bfd_close (arch))
737 bfd_fatal (archive_filename);
738 else if (!silent_create)
739 non_fatal (_("creating %s"), archive_filename);
741 /* If we die creating a new archive, don't leave it around. */
742 output_filename = archive_filename;
745 arch = bfd_openr (archive_filename, target);
746 if (arch == NULL)
748 bloser:
749 bfd_fatal (archive_filename);
752 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
754 bfd_nonfatal (archive_filename);
755 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
757 list_matching_formats (matching);
758 free (matching);
760 xexit (1);
763 last_one = &(arch->next);
764 /* Read all the contents right away, regardless. */
765 for (next_one = bfd_openr_next_archived_file (arch, NULL);
766 next_one;
767 next_one = bfd_openr_next_archived_file (arch, next_one))
769 PROGRESS (1);
770 *last_one = next_one;
771 last_one = &next_one->next;
773 *last_one = (bfd *) NULL;
774 if (bfd_get_error () != bfd_error_no_more_archived_files)
775 goto bloser;
776 return arch;
779 static void
780 print_contents (bfd *abfd)
782 int ncopied = 0;
783 char *cbuf = xmalloc (BUFSIZE);
784 struct stat buf;
785 long size;
786 if (bfd_stat_arch_elt (abfd, &buf) != 0)
787 /* xgettext:c-format */
788 fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
790 if (verbose)
791 /* xgettext:c-format */
792 printf (_("\n<%s>\n\n"), bfd_get_filename (abfd));
794 bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
796 size = buf.st_size;
797 while (ncopied < size)
800 int nread;
801 int tocopy = size - ncopied;
802 if (tocopy > BUFSIZE)
803 tocopy = BUFSIZE;
805 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
806 if (nread != tocopy)
807 /* xgettext:c-format */
808 fatal (_("%s is not a valid archive"),
809 bfd_get_filename (bfd_my_archive (abfd)));
810 fwrite (cbuf, 1, nread, stdout);
811 ncopied += tocopy;
813 free (cbuf);
816 /* Extract a member of the archive into its own file.
818 We defer opening the new file until after we have read a BUFSIZ chunk of the
819 old one, since we know we have just read the archive header for the old
820 one. Since most members are shorter than BUFSIZ, this means we will read
821 the old header, read the old data, write a new inode for the new file, and
822 write the new data, and be done. This 'optimization' is what comes from
823 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
824 Gilmore */
826 void
827 extract_file (bfd *abfd)
829 FILE *ostream;
830 char *cbuf = xmalloc (BUFSIZE);
831 int nread, tocopy;
832 long ncopied = 0;
833 long size;
834 struct stat buf;
836 if (bfd_stat_arch_elt (abfd, &buf) != 0)
837 /* xgettext:c-format */
838 fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
839 size = buf.st_size;
841 if (size < 0)
842 /* xgettext:c-format */
843 fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
845 if (verbose)
846 printf ("x - %s\n", bfd_get_filename (abfd));
848 bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
850 ostream = NULL;
851 if (size == 0)
853 /* Seems like an abstraction violation, eh? Well it's OK! */
854 output_filename = bfd_get_filename (abfd);
856 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
857 if (ostream == NULL)
859 perror (bfd_get_filename (abfd));
860 xexit (1);
863 output_file = ostream;
865 else
866 while (ncopied < size)
868 tocopy = size - ncopied;
869 if (tocopy > BUFSIZE)
870 tocopy = BUFSIZE;
872 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
873 if (nread != tocopy)
874 /* xgettext:c-format */
875 fatal (_("%s is not a valid archive"),
876 bfd_get_filename (bfd_my_archive (abfd)));
878 /* See comment above; this saves disk arm motion */
879 if (ostream == NULL)
881 /* Seems like an abstraction violation, eh? Well it's OK! */
882 output_filename = bfd_get_filename (abfd);
884 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
885 if (ostream == NULL)
887 perror (bfd_get_filename (abfd));
888 xexit (1);
891 output_file = ostream;
893 fwrite (cbuf, 1, nread, ostream);
894 ncopied += tocopy;
897 if (ostream != NULL)
898 fclose (ostream);
900 output_file = NULL;
901 output_filename = NULL;
903 chmod (bfd_get_filename (abfd), buf.st_mode);
905 if (preserve_dates)
907 /* Set access time to modification time. Only st_mtime is
908 initialized by bfd_stat_arch_elt. */
909 buf.st_atime = buf.st_mtime;
910 set_times (bfd_get_filename (abfd), &buf);
913 free (cbuf);
916 static void
917 write_archive (bfd *iarch)
919 bfd *obfd;
920 char *old_name, *new_name;
921 bfd *contents_head = iarch->next;
923 old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
924 strcpy (old_name, bfd_get_filename (iarch));
925 new_name = make_tempname (old_name);
927 output_filename = new_name;
929 obfd = bfd_openw (new_name, bfd_get_target (iarch));
931 if (obfd == NULL)
932 bfd_fatal (old_name);
934 output_bfd = obfd;
936 bfd_set_format (obfd, bfd_archive);
938 /* Request writing the archive symbol table unless we've
939 been explicitly requested not to. */
940 obfd->has_armap = write_armap >= 0;
942 if (ar_truncate)
944 /* This should really use bfd_set_file_flags, but that rejects
945 archives. */
946 obfd->flags |= BFD_TRADITIONAL_FORMAT;
949 if (!bfd_set_archive_head (obfd, contents_head))
950 bfd_fatal (old_name);
952 if (!bfd_close (obfd))
953 bfd_fatal (old_name);
955 output_bfd = NULL;
956 output_filename = NULL;
958 /* We don't care if this fails; we might be creating the archive. */
959 bfd_close (iarch);
961 if (smart_rename (new_name, old_name, 0) != 0)
962 xexit (1);
965 /* Return a pointer to the pointer to the entry which should be rplacd'd
966 into when altering. DEFAULT_POS should be how to interpret pos_default,
967 and should be a pos value. */
969 static bfd **
970 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
972 bfd **after_bfd = contents;
973 enum pos realpos;
974 const char *realposname;
976 if (postype == pos_default)
978 realpos = default_pos;
979 realposname = default_posname;
981 else
983 realpos = postype;
984 realposname = posname;
987 if (realpos == pos_end)
989 while (*after_bfd)
990 after_bfd = &((*after_bfd)->next);
992 else
994 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
995 if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
997 if (realpos == pos_after)
998 after_bfd = &(*after_bfd)->next;
999 break;
1002 return after_bfd;
1005 static void
1006 delete_members (bfd *arch, char **files_to_delete)
1008 bfd **current_ptr_ptr;
1009 bfd_boolean found;
1010 bfd_boolean something_changed = FALSE;
1011 int match_count;
1013 for (; *files_to_delete != NULL; ++files_to_delete)
1015 /* In a.out systems, the armap is optional. It's also called
1016 __.SYMDEF. So if the user asked to delete it, we should remember
1017 that fact. This isn't quite right for COFF systems (where
1018 __.SYMDEF might be regular member), but it's very unlikely
1019 to be a problem. FIXME */
1021 if (!strcmp (*files_to_delete, "__.SYMDEF"))
1023 arch->has_armap = FALSE;
1024 write_armap = -1;
1025 continue;
1028 found = FALSE;
1029 match_count = 0;
1030 current_ptr_ptr = &(arch->next);
1031 while (*current_ptr_ptr)
1033 if (FILENAME_CMP (normalize (*files_to_delete, arch),
1034 (*current_ptr_ptr)->filename) == 0)
1036 ++match_count;
1037 if (counted_name_mode
1038 && match_count != counted_name_counter)
1040 /* Counting, and didn't match on count; go on to the
1041 next one. */
1043 else
1045 found = TRUE;
1046 something_changed = TRUE;
1047 if (verbose)
1048 printf ("d - %s\n",
1049 *files_to_delete);
1050 *current_ptr_ptr = ((*current_ptr_ptr)->next);
1051 goto next_file;
1055 current_ptr_ptr = &((*current_ptr_ptr)->next);
1058 if (verbose && !found)
1060 /* xgettext:c-format */
1061 printf (_("No member named `%s'\n"), *files_to_delete);
1063 next_file:
1067 if (something_changed)
1068 write_archive (arch);
1069 else
1070 output_filename = NULL;
1074 /* Reposition existing members within an archive */
1076 static void
1077 move_members (bfd *arch, char **files_to_move)
1079 bfd **after_bfd; /* New entries go after this one */
1080 bfd **current_ptr_ptr; /* cdr pointer into contents */
1082 for (; *files_to_move; ++files_to_move)
1084 current_ptr_ptr = &(arch->next);
1085 while (*current_ptr_ptr)
1087 bfd *current_ptr = *current_ptr_ptr;
1088 if (FILENAME_CMP (normalize (*files_to_move, arch),
1089 current_ptr->filename) == 0)
1091 /* Move this file to the end of the list - first cut from
1092 where it is. */
1093 bfd *link;
1094 *current_ptr_ptr = current_ptr->next;
1096 /* Now glue to end */
1097 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1098 link = *after_bfd;
1099 *after_bfd = current_ptr;
1100 current_ptr->next = link;
1102 if (verbose)
1103 printf ("m - %s\n", *files_to_move);
1105 goto next_file;
1108 current_ptr_ptr = &((*current_ptr_ptr)->next);
1110 /* xgettext:c-format */
1111 fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1113 next_file:;
1116 write_archive (arch);
1119 /* Ought to default to replacing in place, but this is existing practice! */
1121 static void
1122 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1124 bfd_boolean changed = FALSE;
1125 bfd **after_bfd; /* New entries go after this one. */
1126 bfd *current;
1127 bfd **current_ptr;
1129 while (files_to_move && *files_to_move)
1131 if (! quick)
1133 current_ptr = &arch->next;
1134 while (*current_ptr)
1136 current = *current_ptr;
1138 /* For compatibility with existing ar programs, we
1139 permit the same file to be added multiple times. */
1140 if (FILENAME_CMP (normalize (*files_to_move, arch),
1141 normalize (current->filename, arch)) == 0
1142 && current->arelt_data != NULL)
1144 if (newer_only)
1146 struct stat fsbuf, asbuf;
1148 if (stat (*files_to_move, &fsbuf) != 0)
1150 if (errno != ENOENT)
1151 bfd_fatal (*files_to_move);
1152 goto next_file;
1154 if (bfd_stat_arch_elt (current, &asbuf) != 0)
1155 /* xgettext:c-format */
1156 fatal (_("internal stat error on %s"),
1157 current->filename);
1159 if (fsbuf.st_mtime <= asbuf.st_mtime)
1160 goto next_file;
1163 after_bfd = get_pos_bfd (&arch->next, pos_after,
1164 current->filename);
1165 if (ar_emul_replace (after_bfd, *files_to_move,
1166 verbose))
1168 /* Snip out this entry from the chain. */
1169 *current_ptr = (*current_ptr)->next;
1170 changed = TRUE;
1173 goto next_file;
1175 current_ptr = &(current->next);
1179 /* Add to the end of the archive. */
1180 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1182 if (ar_emul_append (after_bfd, *files_to_move, verbose))
1183 changed = TRUE;
1185 next_file:;
1187 files_to_move++;
1190 if (changed)
1191 write_archive (arch);
1192 else
1193 output_filename = NULL;
1196 static void
1197 ranlib_only (const char *archname)
1199 bfd *arch;
1201 if (get_file_size (archname) < 1)
1202 return;
1203 write_armap = 1;
1204 arch = open_inarch (archname, (char *) NULL);
1205 if (arch == NULL)
1206 xexit (1);
1207 write_archive (arch);
1210 /* Update the timestamp of the symbol map of an archive. */
1212 static void
1213 ranlib_touch (const char *archname)
1215 #ifdef __GO32__
1216 /* I don't think updating works on go32. */
1217 ranlib_only (archname);
1218 #else
1219 int f;
1220 bfd *arch;
1221 char **matching;
1223 if (get_file_size (archname) < 1)
1224 return;
1225 f = open (archname, O_RDWR | O_BINARY, 0);
1226 if (f < 0)
1228 bfd_set_error (bfd_error_system_call);
1229 bfd_fatal (archname);
1232 arch = bfd_fdopenr (archname, (const char *) NULL, f);
1233 if (arch == NULL)
1234 bfd_fatal (archname);
1235 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1237 bfd_nonfatal (archname);
1238 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1240 list_matching_formats (matching);
1241 free (matching);
1243 xexit (1);
1246 if (! bfd_has_map (arch))
1247 /* xgettext:c-format */
1248 fatal (_("%s: no archive map to update"), archname);
1250 bfd_update_armap_timestamp (arch);
1252 if (! bfd_close (arch))
1253 bfd_fatal (archname);
1254 #endif
1257 /* Things which are interesting to map over all or some of the files: */
1259 static void
1260 print_descr (bfd *abfd)
1262 print_arelt_descr (stdout, abfd, verbose);