1999-09-12 Donn Terry <donn@interix.com>
[binutils.git] / binutils / ar.c
blob3e9dcefd92d25002a68821b0ee490b1673c210af
1 /* ar.c - Archive modify and extract.
2 Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 1999
3 Free Software Foundation, Inc.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22 Bugs: should use getopt the way tar does (complete w/optional -) and
23 should have long options too. GNU ar used to check file against filesystem
24 in quick_update and replace operations (would check mtime). Doesn't warn
25 when name truncated. No way to specify pos_end. Error messages should be
26 more consistant.
28 #include "bfd.h"
29 #include "libiberty.h"
30 #include "progress.h"
31 #include "bucomm.h"
32 #include "aout/ar.h"
33 #include "libbfd.h"
34 #include "arsup.h"
35 #include <sys/stat.h>
37 #ifdef __GO32___
38 #define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
39 #else
40 #define EXT_NAME_LEN 6 /* ditto for *NIX */
41 #endif
43 /* We need to open files in binary modes on system where that makes a
44 difference. */
45 #ifndef O_BINARY
46 #define O_BINARY 0
47 #endif
49 #define BUFSIZE 8192
51 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */
53 struct ar_hdr *
54 bfd_special_undocumented_glue PARAMS ((bfd * abfd, const char *filename));
56 /* Static declarations */
58 static void
59 mri_emul PARAMS ((void));
61 static const char *
62 normalize PARAMS ((const char *, bfd *));
64 static void
65 remove_output PARAMS ((void));
67 static void
68 map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int));
70 static void
71 print_contents PARAMS ((bfd * member));
73 static void
74 delete_members PARAMS ((bfd *, char **files_to_delete));
76 #if 0
77 static void
78 do_quick_append PARAMS ((const char *archive_filename,
79 char **files_to_append));
80 #endif
82 static void
83 move_members PARAMS ((bfd *, char **files_to_move));
85 static void
86 replace_members PARAMS ((bfd *, char **files_to_replace, boolean quick));
88 static void
89 print_descr PARAMS ((bfd * abfd));
91 static void
92 write_archive PARAMS ((bfd *));
94 static void
95 ranlib_only PARAMS ((const char *archname));
97 static void
98 ranlib_touch PARAMS ((const char *archname));
100 static void
101 usage PARAMS ((int));
103 /** Globals and flags */
105 int mri_mode;
107 /* This flag distinguishes between ar and ranlib:
108 1 means this is 'ranlib'; 0 means this is 'ar'.
109 -1 means if we should use argv[0] to decide. */
110 extern int is_ranlib;
112 /* Nonzero means don't warn about creating the archive file if necessary. */
113 int silent_create = 0;
115 /* Nonzero means describe each action performed. */
116 int verbose = 0;
118 /* Nonzero means preserve dates of members when extracting them. */
119 int preserve_dates = 0;
121 /* Nonzero means don't replace existing members whose dates are more recent
122 than the corresponding files. */
123 int newer_only = 0;
125 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
126 member). -1 means we've been explicitly asked to not write a symbol table;
127 +1 means we've been explictly asked to write it;
128 0 is the default.
129 Traditionally, the default in BSD has been to not write the table.
130 However, for POSIX.2 compliance the default is now to write a symbol table
131 if any of the members are object files. */
132 int write_armap = 0;
134 /* Nonzero means it's the name of an existing member; position new or moved
135 files with respect to this one. */
136 char *posname = NULL;
138 /* Sez how to use `posname': pos_before means position before that member.
139 pos_after means position after that member. pos_end means always at end.
140 pos_default means default appropriately. For the latter two, `posname'
141 should also be zero. */
142 enum pos
144 pos_default, pos_before, pos_after, pos_end
145 } postype = pos_default;
147 static bfd **
148 get_pos_bfd PARAMS ((bfd **, enum pos, const char *));
150 /* Whether to truncate names of files stored in the archive. */
151 static boolean ar_truncate = false;
153 int interactive = 0;
155 static void
156 mri_emul ()
158 interactive = isatty (fileno (stdin));
159 yyparse ();
162 /* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero,
163 COUNT is the length of the FILES chain; FUNCTION is called on each entry
164 whose name matches one in FILES. */
166 static void
167 map_over_members (arch, function, files, count)
168 bfd *arch;
169 void (*function) PARAMS ((bfd *));
170 char **files;
171 int count;
173 bfd *head;
175 if (count == 0)
177 for (head = arch->next; head; head = head->next)
179 PROGRESS (1);
180 function (head);
182 return;
184 /* This may appear to be a baroque way of accomplishing what we want.
185 However we have to iterate over the filenames in order to notice where
186 a filename is requested but does not exist in the archive. Ditto
187 mapping over each file each time -- we want to hack multiple
188 references. */
190 for (; count > 0; files++, count--)
192 boolean found = false;
194 for (head = arch->next; head; head = head->next)
196 PROGRESS (1);
197 if (head->filename == NULL)
199 /* Some archive formats don't get the filenames filled in
200 until the elements are opened. */
201 struct stat buf;
202 bfd_stat_arch_elt (head, &buf);
204 if ((head->filename != NULL) &&
205 (!strcmp (*files, head->filename)))
207 found = true;
208 function (head);
211 if (!found)
212 /* xgettext:c-format */
213 fprintf (stderr, _("no entry %s in archive\n"), *files);
217 boolean operation_alters_arch = false;
219 static void
220 usage (help)
221 int help;
223 FILE *s;
225 s = help ? stdout : stderr;
227 if (! is_ranlib)
229 /* xgettext:c-format */
230 fprintf (s, _("Usage: %s [-]{dmpqrstx}[abcilosSuvV] [member-name] archive-file file...\n"), program_name);
231 /* xgettext:c-format */
232 fprintf (s, _(" %s -M [<mri-script]\n"), program_name);
233 fprintf (s, _(" commands:\n"));
234 fprintf (s, _(" d - delete file(s) from the archive\n"));
235 fprintf (s, _(" m[ab] - move file(s) in the archive\n"));
236 fprintf (s, _(" p - print file(s) found in the archive\n"));
237 fprintf (s, _(" q[f] - quick append file(s) to the archive\n"));
238 fprintf (s, _(" r[ab][f][u] - replace existing or insert new file(s) into the archive\n"));
239 fprintf (s, _(" t - display contents of archive\n"));
240 fprintf (s, _(" x[o] - extract file(s) from the archive\n"));
241 fprintf (s, _(" command specific modifiers:\n"));
242 fprintf (s, _(" [a] - put file(s) after [member-name]\n"));
243 fprintf (s, _(" [b] - put file(s) before [member-name] (same as [i])\n"));
244 fprintf (s, _(" [f] - truncate inserted file names\n"));
245 fprintf (s, _(" [o] - preserve original dates\n"));
246 fprintf (s, _(" [u] - only replace files that are newer than current archive contents\n"));
247 fprintf (s, _(" generic modifiers:\n"));
248 fprintf (s, _(" [c] - do not warn if the library had to be created\n"));
249 fprintf (s, _(" [s] - create an archive index (cf. ranlib)\n"));
250 fprintf (s, _(" [S] - do not build a symbol table\n"));
251 fprintf (s, _(" [v] - be verbose\n"));
252 fprintf (s, _(" [V] - display the version number\n"));
254 else
255 /* xgettext:c-format */
256 fprintf (s, _("Usage: %s [-vV] archive\n"), program_name);
258 list_supported_targets (program_name, stderr);
260 if (help)
261 fprintf (s, _("Report bugs to bug-gnu-utils@gnu.org\n"));
263 xexit (help ? 0 : 1);
266 /* Normalize a file name specified on the command line into a file
267 name which we will use in an archive. */
269 static const char *
270 normalize (file, abfd)
271 const char *file;
272 bfd *abfd;
274 const char *filename;
276 filename = strrchr (file, '/');
277 if (filename != (char *) NULL)
278 filename++;
279 else
280 filename = file;
282 if (ar_truncate
283 && abfd != NULL
284 && strlen (filename) > abfd->xvec->ar_max_namelen)
286 char *s;
288 /* Space leak. */
289 s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
290 memcpy (s, filename, abfd->xvec->ar_max_namelen);
291 s[abfd->xvec->ar_max_namelen] = '\0';
292 filename = s;
295 return filename;
298 /* Remove any output file. This is only called via xatexit. */
300 static char *output_filename = NULL;
301 static FILE *output_file = NULL;
302 static bfd *output_bfd = NULL;
304 static void
305 remove_output ()
307 if (output_filename != NULL)
309 if (output_bfd != NULL && output_bfd->iostream != NULL)
310 fclose ((FILE *) (output_bfd->iostream));
311 if (output_file != NULL)
312 fclose (output_file);
313 unlink (output_filename);
317 /* The option parsing should be in its own function.
318 It will be when I have getopt working. */
321 main (argc, argv)
322 int argc;
323 char **argv;
325 char *arg_ptr;
326 char c;
327 enum
329 none = 0, delete, replace, print_table,
330 print_files, extract, move, quick_append
331 } operation = none;
332 int arg_index;
333 char **files;
334 char *inarch_filename;
335 int show_version;
337 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
338 setlocale (LC_MESSAGES, "");
339 #endif
340 bindtextdomain (PACKAGE, LOCALEDIR);
341 textdomain (PACKAGE);
343 program_name = argv[0];
344 xmalloc_set_program_name (program_name);
346 if (is_ranlib < 0)
348 char *temp;
350 temp = strrchr (program_name, '/');
351 if (temp == NULL)
352 temp = program_name;
353 else
354 ++temp;
355 if (strlen (temp) >= 6
356 && strcmp (temp + strlen (temp) - 6, "ranlib") == 0)
357 is_ranlib = 1;
358 else
359 is_ranlib = 0;
362 if (argc > 1 && argv[1][0] == '-')
364 if (strcmp (argv[1], "--help") == 0)
365 usage (1);
366 else if (strcmp (argv[1], "--version") == 0)
368 if (is_ranlib)
369 print_version ("ranlib");
370 else
371 print_version ("ar");
375 START_PROGRESS (program_name, 0);
377 bfd_init ();
378 set_default_bfd_target ();
380 show_version = 0;
382 xatexit (remove_output);
384 if (is_ranlib)
386 boolean touch = false;
388 if (argc < 2 || strcmp (argv[1], "--help") == 0)
389 usage (0);
390 if (strcmp (argv[1], "-V") == 0
391 || strcmp (argv[1], "-v") == 0
392 || strncmp (argv[1], "--v", 3) == 0)
393 print_version ("ranlib");
394 arg_index = 1;
395 if (strcmp (argv[1], "-t") == 0)
397 ++arg_index;
398 touch = true;
400 while (arg_index < argc)
402 if (! touch)
403 ranlib_only (argv[arg_index]);
404 else
405 ranlib_touch (argv[arg_index]);
406 ++arg_index;
408 xexit (0);
411 if (argc == 2 && strcmp (argv[1], "-M") == 0)
413 mri_emul ();
414 xexit (0);
417 if (argc < 2)
418 usage (0);
420 arg_ptr = argv[1];
422 if (*arg_ptr == '-')
423 ++arg_ptr; /* compatibility */
425 while ((c = *arg_ptr++) != '\0')
427 switch (c)
429 case 'd':
430 case 'm':
431 case 'p':
432 case 'q':
433 case 'r':
434 case 't':
435 case 'x':
436 if (operation != none)
437 fatal (_("two different operation options specified"));
438 switch (c)
440 case 'd':
441 operation = delete;
442 operation_alters_arch = true;
443 break;
444 case 'm':
445 operation = move;
446 operation_alters_arch = true;
447 break;
448 case 'p':
449 operation = print_files;
450 break;
451 case 'q':
452 operation = quick_append;
453 operation_alters_arch = true;
454 break;
455 case 'r':
456 operation = replace;
457 operation_alters_arch = true;
458 break;
459 case 't':
460 operation = print_table;
461 break;
462 case 'x':
463 operation = extract;
464 break;
466 case 'l':
467 break;
468 case 'c':
469 silent_create = 1;
470 break;
471 case 'o':
472 preserve_dates = 1;
473 break;
474 case 'V':
475 show_version = true;
476 break;
477 case 's':
478 write_armap = 1;
479 break;
480 case 'S':
481 write_armap = -1;
482 break;
483 case 'u':
484 newer_only = 1;
485 break;
486 case 'v':
487 verbose = 1;
488 break;
489 case 'a':
490 postype = pos_after;
491 break;
492 case 'b':
493 postype = pos_before;
494 break;
495 case 'i':
496 postype = pos_before;
497 break;
498 case 'M':
499 mri_mode = 1;
500 break;
501 case 'f':
502 ar_truncate = true;
503 break;
504 default:
505 /* xgettext:c-format */
506 fprintf (stderr, _("%s: illegal option -- %c\n"), program_name, c);
507 usage (0);
511 if (show_version)
512 print_version ("ar");
514 if (argc < 3)
515 usage (0);
517 if (mri_mode)
519 mri_emul ();
521 else
523 bfd *arch;
525 /* We can't write an armap when using ar q, so just do ar r
526 instead. */
527 if (operation == quick_append && write_armap)
528 operation = replace;
530 if ((operation == none || operation == print_table)
531 && write_armap == 1)
533 ranlib_only (argv[2]);
534 xexit (0);
537 if (operation == none)
538 fatal (_("no operation specified"));
540 if (newer_only && operation != replace)
541 fatal (_("`u' is only meaningful with the `r' option."));
543 arg_index = 2;
545 if (postype != pos_default)
546 posname = argv[arg_index++];
548 inarch_filename = argv[arg_index++];
550 files = arg_index < argc ? argv + arg_index : NULL;
552 #if 0
553 /* We don't use do_quick_append any more. Too many systems
554 expect ar to always rebuild the symbol table even when q is
555 used. */
557 /* We can't do a quick append if we need to construct an
558 extended name table, because do_quick_append won't be able to
559 rebuild the name table. Unfortunately, at this point we
560 don't actually know the maximum name length permitted by this
561 object file format. So, we guess. FIXME. */
562 if (operation == quick_append && ! ar_truncate)
564 char **chk;
566 for (chk = files; chk != NULL && *chk != '\0'; chk++)
568 if (strlen (normalize (*chk, (bfd *) NULL)) > 14)
570 operation = replace;
571 break;
576 if (operation == quick_append)
578 /* Note that quick appending to a non-existent archive creates it,
579 even if there are no files to append. */
580 do_quick_append (inarch_filename, files);
581 xexit (0);
583 #endif
585 arch = open_inarch (inarch_filename,
586 files == NULL ? (char *) NULL : files[0]);
588 switch (operation)
590 case print_table:
591 map_over_members (arch, print_descr, files, argc - 3);
592 break;
594 case print_files:
595 map_over_members (arch, print_contents, files, argc - 3);
596 break;
598 case extract:
599 map_over_members (arch, extract_file, files, argc - 3);
600 break;
602 case delete:
603 if (files != NULL)
604 delete_members (arch, files);
605 break;
607 case move:
608 if (files != NULL)
609 move_members (arch, files);
610 break;
612 case replace:
613 case quick_append:
614 if (files != NULL || write_armap > 0)
615 replace_members (arch, files, operation == quick_append);
616 break;
618 /* Shouldn't happen! */
619 default:
620 /* xgettext:c-format */
621 fprintf (stderr, _("%s: internal error -- this option not implemented\n"),
622 program_name);
623 xexit (1);
627 END_PROGRESS (program_name);
629 xexit (0);
630 return 0;
633 bfd *
634 open_inarch (archive_filename, file)
635 const char *archive_filename;
636 const char *file;
638 const char *target;
639 bfd **last_one;
640 bfd *next_one;
641 struct stat sbuf;
642 bfd *arch;
643 char **matching;
645 bfd_set_error (bfd_error_no_error);
647 target = NULL;
649 if (stat (archive_filename, &sbuf) != 0)
651 #ifndef __GO32__
653 /* KLUDGE ALERT! Temporary fix until I figger why
654 * stat() is wrong ... think it's buried in GO32's IDT
655 * - Jax
657 if (errno != ENOENT)
658 bfd_fatal (archive_filename);
659 #endif
661 if (!operation_alters_arch)
663 fprintf (stderr, "%s: ", program_name);
664 perror (archive_filename);
665 maybequit ();
666 return NULL;
669 /* Try to figure out the target to use for the archive from the
670 first object on the list. */
671 if (file != NULL)
673 bfd *obj;
675 obj = bfd_openr (file, NULL);
676 if (obj != NULL)
678 if (bfd_check_format (obj, bfd_object))
679 target = bfd_get_target (obj);
680 (void) bfd_close (obj);
684 /* Create an empty archive. */
685 arch = bfd_openw (archive_filename, target);
686 if (arch == NULL
687 || ! bfd_set_format (arch, bfd_archive)
688 || ! bfd_close (arch))
689 bfd_fatal (archive_filename);
692 arch = bfd_openr (archive_filename, target);
693 if (arch == NULL)
695 bloser:
696 bfd_fatal (archive_filename);
699 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
701 bfd_nonfatal (archive_filename);
702 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
704 list_matching_formats (matching);
705 free (matching);
707 xexit (1);
710 last_one = &(arch->next);
711 /* Read all the contents right away, regardless. */
712 for (next_one = bfd_openr_next_archived_file (arch, NULL);
713 next_one;
714 next_one = bfd_openr_next_archived_file (arch, next_one))
716 PROGRESS (1);
717 *last_one = next_one;
718 last_one = &next_one->next;
720 *last_one = (bfd *) NULL;
721 if (bfd_get_error () != bfd_error_no_more_archived_files)
722 goto bloser;
723 return arch;
726 static void
727 print_contents (abfd)
728 bfd *abfd;
730 int ncopied = 0;
731 char *cbuf = xmalloc (BUFSIZE);
732 struct stat buf;
733 long size;
734 if (bfd_stat_arch_elt (abfd, &buf) != 0)
735 /* xgettext:c-format */
736 fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
738 if (verbose)
739 /* xgettext:c-format */
740 printf (_("\n<member %s>\n\n"), bfd_get_filename (abfd));
742 bfd_seek (abfd, 0, SEEK_SET);
744 size = buf.st_size;
745 while (ncopied < size)
748 int nread;
749 int tocopy = size - ncopied;
750 if (tocopy > BUFSIZE)
751 tocopy = BUFSIZE;
753 nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
754 abstraction! */
755 if (nread != tocopy)
756 /* xgettext:c-format */
757 fatal (_("%s is not a valid archive"),
758 bfd_get_filename (bfd_my_archive (abfd)));
759 fwrite (cbuf, 1, nread, stdout);
760 ncopied += tocopy;
762 free (cbuf);
765 /* Extract a member of the archive into its own file.
767 We defer opening the new file until after we have read a BUFSIZ chunk of the
768 old one, since we know we have just read the archive header for the old
769 one. Since most members are shorter than BUFSIZ, this means we will read
770 the old header, read the old data, write a new inode for the new file, and
771 write the new data, and be done. This 'optimization' is what comes from
772 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
773 Gilmore */
775 void
776 extract_file (abfd)
777 bfd *abfd;
779 FILE *ostream;
780 char *cbuf = xmalloc (BUFSIZE);
781 int nread, tocopy;
782 long ncopied = 0;
783 long size;
784 struct stat buf;
786 if (bfd_stat_arch_elt (abfd, &buf) != 0)
787 /* xgettext:c-format */
788 fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
789 size = buf.st_size;
791 if (size < 0)
792 /* xgettext:c-format */
793 fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
795 if (verbose)
796 printf ("x - %s\n", bfd_get_filename (abfd));
798 bfd_seek (abfd, 0, SEEK_SET);
800 ostream = NULL;
801 if (size == 0)
803 /* Seems like an abstraction violation, eh? Well it's OK! */
804 output_filename = bfd_get_filename (abfd);
806 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
807 if (ostream == NULL)
809 perror (bfd_get_filename (abfd));
810 xexit (1);
813 output_file = ostream;
815 else
816 while (ncopied < size)
818 tocopy = size - ncopied;
819 if (tocopy > BUFSIZE)
820 tocopy = BUFSIZE;
822 nread = bfd_read (cbuf, 1, tocopy, abfd);
823 if (nread != tocopy)
824 /* xgettext:c-format */
825 fatal (_("%s is not a valid archive"),
826 bfd_get_filename (bfd_my_archive (abfd)));
828 /* See comment above; this saves disk arm motion */
829 if (ostream == NULL)
831 /* Seems like an abstraction violation, eh? Well it's OK! */
832 output_filename = bfd_get_filename (abfd);
834 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
835 if (ostream == NULL)
837 perror (bfd_get_filename (abfd));
838 xexit (1);
841 output_file = ostream;
843 fwrite (cbuf, 1, nread, ostream);
844 ncopied += tocopy;
847 if (ostream != NULL)
848 fclose (ostream);
850 output_file = NULL;
851 output_filename = NULL;
853 chmod (bfd_get_filename (abfd), buf.st_mode);
855 if (preserve_dates)
856 set_times (bfd_get_filename (abfd), &buf);
858 free (cbuf);
861 #if 0
863 /* We don't use this anymore. Too many systems expect ar to rebuild
864 the symbol table even when q is used. */
866 /* Just do it quickly; don't worry about dups, armap, or anything like that */
868 static void
869 do_quick_append (archive_filename, files_to_append)
870 const char *archive_filename;
871 char **files_to_append;
873 FILE *ofile, *ifile;
874 char *buf = xmalloc (BUFSIZE);
875 long tocopy, thistime;
876 bfd *temp;
877 struct stat sbuf;
878 boolean newfile = false;
879 bfd_set_error (bfd_error_no_error);
881 if (stat (archive_filename, &sbuf) != 0)
884 #ifndef __GO32__
886 /* KLUDGE ALERT! Temporary fix until I figger why
887 * stat() is wrong ... think it's buried in GO32's IDT
888 * - Jax
891 if (errno != ENOENT)
892 bfd_fatal (archive_filename);
893 #endif
895 newfile = true;
898 ofile = fopen (archive_filename, FOPEN_AUB);
899 if (ofile == NULL)
901 perror (program_name);
902 xexit (1);
905 temp = bfd_openr (archive_filename, NULL);
906 if (temp == NULL)
908 bfd_fatal (archive_filename);
910 if (newfile == false)
912 if (bfd_check_format (temp, bfd_archive) != true)
913 /* xgettext:c-format */
914 fatal (_("%s is not an archive"), archive_filename);
916 else
918 fwrite (ARMAG, 1, SARMAG, ofile);
919 if (!silent_create)
920 /* xgettext:c-format */
921 fprintf (stderr, _("%s: creating %s\n"),
922 program_name, archive_filename);
925 if (ar_truncate)
926 temp->flags |= BFD_TRADITIONAL_FORMAT;
928 /* assume it's an achive, go straight to the end, sans $200 */
929 fseek (ofile, 0, 2);
931 for (; files_to_append && *files_to_append; ++files_to_append)
933 struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
934 if (hdr == NULL)
936 bfd_fatal (*files_to_append);
939 BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
941 ifile = fopen (*files_to_append, FOPEN_RB);
942 if (ifile == NULL)
944 bfd_nonfatal (*files_to_append);
947 if (stat (*files_to_append, &sbuf) != 0)
949 bfd_nonfatal (*files_to_append);
952 tocopy = sbuf.st_size;
954 /* XXX should do error-checking! */
955 fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
957 while (tocopy > 0)
959 thistime = tocopy;
960 if (thistime > BUFSIZE)
961 thistime = BUFSIZE;
962 fread (buf, 1, thistime, ifile);
963 fwrite (buf, 1, thistime, ofile);
964 tocopy -= thistime;
966 fclose (ifile);
967 if ((sbuf.st_size % 2) == 1)
968 putc ('\012', ofile);
970 fclose (ofile);
971 bfd_close (temp);
972 free (buf);
975 #endif /* 0 */
977 static void
978 write_archive (iarch)
979 bfd *iarch;
981 bfd *obfd;
982 char *old_name, *new_name;
983 bfd *contents_head = iarch->next;
985 old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
986 strcpy (old_name, bfd_get_filename (iarch));
987 new_name = make_tempname (old_name);
989 output_filename = new_name;
991 obfd = bfd_openw (new_name, bfd_get_target (iarch));
993 if (obfd == NULL)
994 bfd_fatal (old_name);
996 output_bfd = obfd;
998 bfd_set_format (obfd, bfd_archive);
1000 /* Request writing the archive symbol table unless we've
1001 been explicitly requested not to. */
1002 obfd->has_armap = write_armap >= 0;
1004 if (ar_truncate)
1006 /* This should really use bfd_set_file_flags, but that rejects
1007 archives. */
1008 obfd->flags |= BFD_TRADITIONAL_FORMAT;
1011 if (bfd_set_archive_head (obfd, contents_head) != true)
1012 bfd_fatal (old_name);
1014 if (!bfd_close (obfd))
1015 bfd_fatal (old_name);
1017 output_bfd = NULL;
1018 output_filename = NULL;
1020 /* We don't care if this fails; we might be creating the archive. */
1021 bfd_close (iarch);
1023 if (smart_rename (new_name, old_name, 0) != 0)
1024 xexit (1);
1027 /* Return a pointer to the pointer to the entry which should be rplacd'd
1028 into when altering. DEFAULT_POS should be how to interpret pos_default,
1029 and should be a pos value. */
1031 static bfd **
1032 get_pos_bfd (contents, default_pos, default_posname)
1033 bfd **contents;
1034 enum pos default_pos;
1035 const char *default_posname;
1037 bfd **after_bfd = contents;
1038 enum pos realpos;
1039 const char *realposname;
1041 if (postype == pos_default)
1043 realpos = default_pos;
1044 realposname = default_posname;
1046 else
1048 realpos = postype;
1049 realposname = posname;
1052 if (realpos == pos_end)
1054 while (*after_bfd)
1055 after_bfd = &((*after_bfd)->next);
1057 else
1059 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
1060 if (strcmp ((*after_bfd)->filename, realposname) == 0)
1062 if (realpos == pos_after)
1063 after_bfd = &(*after_bfd)->next;
1064 break;
1067 return after_bfd;
1070 static void
1071 delete_members (arch, files_to_delete)
1072 bfd *arch;
1073 char **files_to_delete;
1075 bfd **current_ptr_ptr;
1076 boolean found;
1077 boolean something_changed = false;
1078 for (; *files_to_delete != NULL; ++files_to_delete)
1080 /* In a.out systems, the armap is optional. It's also called
1081 __.SYMDEF. So if the user asked to delete it, we should remember
1082 that fact. This isn't quite right for COFF systems (where
1083 __.SYMDEF might be regular member), but it's very unlikely
1084 to be a problem. FIXME */
1086 if (!strcmp (*files_to_delete, "__.SYMDEF"))
1088 arch->has_armap = false;
1089 write_armap = -1;
1090 continue;
1093 found = false;
1094 current_ptr_ptr = &(arch->next);
1095 while (*current_ptr_ptr)
1097 if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
1099 found = true;
1100 something_changed = true;
1101 if (verbose)
1102 printf ("d - %s\n",
1103 *files_to_delete);
1104 *current_ptr_ptr = ((*current_ptr_ptr)->next);
1105 goto next_file;
1107 else
1109 current_ptr_ptr = &((*current_ptr_ptr)->next);
1113 if (verbose && found == false)
1115 /* xgettext:c-format */
1116 printf (_("No member named `%s'\n"), *files_to_delete);
1118 next_file:
1122 if (something_changed == true)
1124 write_archive (arch);
1129 /* Reposition existing members within an archive */
1131 static void
1132 move_members (arch, files_to_move)
1133 bfd *arch;
1134 char **files_to_move;
1136 bfd **after_bfd; /* New entries go after this one */
1137 bfd **current_ptr_ptr; /* cdr pointer into contents */
1139 for (; *files_to_move; ++files_to_move)
1141 current_ptr_ptr = &(arch->next);
1142 while (*current_ptr_ptr)
1144 bfd *current_ptr = *current_ptr_ptr;
1145 if (strcmp (normalize (*files_to_move, arch),
1146 current_ptr->filename) == 0)
1148 /* Move this file to the end of the list - first cut from
1149 where it is. */
1150 bfd *link;
1151 *current_ptr_ptr = current_ptr->next;
1153 /* Now glue to end */
1154 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1155 link = *after_bfd;
1156 *after_bfd = current_ptr;
1157 current_ptr->next = link;
1159 if (verbose)
1160 printf ("m - %s\n", *files_to_move);
1162 goto next_file;
1165 current_ptr_ptr = &((*current_ptr_ptr)->next);
1167 /* xgettext:c-format */
1168 fprintf (stderr, _("%s: no entry %s in archive %s!\n"),
1169 program_name, *files_to_move, arch->filename);
1170 xexit (1);
1171 next_file:;
1174 write_archive (arch);
1177 /* Ought to default to replacing in place, but this is existing practice! */
1179 static void
1180 replace_members (arch, files_to_move, quick)
1181 bfd *arch;
1182 char **files_to_move;
1183 boolean quick;
1185 boolean changed = false;
1186 bfd **after_bfd; /* New entries go after this one */
1187 bfd *current;
1188 bfd **current_ptr;
1189 bfd *temp;
1191 while (files_to_move && *files_to_move)
1193 if (! quick)
1195 current_ptr = &arch->next;
1196 while (*current_ptr)
1198 current = *current_ptr;
1200 /* For compatibility with existing ar programs, we
1201 permit the same file to be added multiple times. */
1202 if (strcmp (normalize (*files_to_move, arch),
1203 normalize (current->filename, arch)) == 0
1204 && current->arelt_data != NULL)
1206 if (newer_only)
1208 struct stat fsbuf, asbuf;
1210 if (stat (*files_to_move, &fsbuf) != 0)
1212 if (errno != ENOENT)
1213 bfd_fatal (*files_to_move);
1214 goto next_file;
1216 if (bfd_stat_arch_elt (current, &asbuf) != 0)
1217 /* xgettext:c-format */
1218 fatal (_("internal stat error on %s"), current->filename);
1220 if (fsbuf.st_mtime <= asbuf.st_mtime)
1221 goto next_file;
1224 after_bfd = get_pos_bfd (&arch->next, pos_after,
1225 current->filename);
1226 temp = *after_bfd;
1228 *after_bfd = bfd_openr (*files_to_move, NULL);
1229 if (*after_bfd == (bfd *) NULL)
1231 bfd_fatal (*files_to_move);
1233 (*after_bfd)->next = temp;
1235 /* snip out this entry from the chain */
1236 *current_ptr = (*current_ptr)->next;
1238 if (verbose)
1240 printf ("r - %s\n", *files_to_move);
1243 changed = true;
1245 goto next_file;
1247 current_ptr = &(current->next);
1251 /* Add to the end of the archive. */
1253 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1254 temp = *after_bfd;
1255 *after_bfd = bfd_openr (*files_to_move, NULL);
1256 if (*after_bfd == (bfd *) NULL)
1258 bfd_fatal (*files_to_move);
1260 if (verbose)
1262 printf ("a - %s\n", *files_to_move);
1265 (*after_bfd)->next = temp;
1267 changed = true;
1269 next_file:;
1271 files_to_move++;
1274 if (changed)
1275 write_archive (arch);
1278 static void
1279 ranlib_only (archname)
1280 const char *archname;
1282 bfd *arch;
1284 write_armap = 1;
1285 arch = open_inarch (archname, (char *) NULL);
1286 if (arch == NULL)
1287 xexit (1);
1288 write_archive (arch);
1291 /* Update the timestamp of the symbol map of an archive. */
1293 static void
1294 ranlib_touch (archname)
1295 const char *archname;
1297 #ifdef __GO32__
1298 /* I don't think updating works on go32. */
1299 ranlib_only (archname);
1300 #else
1301 int f;
1302 bfd *arch;
1303 char **matching;
1305 f = open (archname, O_RDWR | O_BINARY, 0);
1306 if (f < 0)
1308 bfd_set_error (bfd_error_system_call);
1309 bfd_fatal (archname);
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))
1317 bfd_nonfatal (archname);
1318 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1320 list_matching_formats (matching);
1321 free (matching);
1323 xexit (1);
1326 if (! bfd_has_map (arch))
1327 /* xgettext:c-format */
1328 fatal (_("%s: no archive map to update"), archname);
1330 bfd_update_armap_timestamp (arch);
1332 if (! bfd_close (arch))
1333 bfd_fatal (archname);
1334 #endif
1337 /* Things which are interesting to map over all or some of the files: */
1339 static void
1340 print_descr (abfd)
1341 bfd *abfd;
1343 print_arelt_descr (stdout, abfd, verbose);