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