1999-09-12 Donn Terry <donn@interix.com>
[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 const 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       /* If we die creating a new archive, don't leave it around.  */
704       output_filename = archive_filename;
705     }
706
707   arch = bfd_openr (archive_filename, target);
708   if (arch == NULL)
709     {
710     bloser:
711       bfd_fatal (archive_filename);
712     }
713
714   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
715     {
716       bfd_nonfatal (archive_filename);
717       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
718         {
719           list_matching_formats (matching);
720           free (matching);
721         }
722       xexit (1);
723     }
724
725   last_one = &(arch->next);
726   /* Read all the contents right away, regardless.  */
727   for (next_one = bfd_openr_next_archived_file (arch, NULL);
728        next_one;
729        next_one = bfd_openr_next_archived_file (arch, next_one))
730     {
731       PROGRESS (1);
732       *last_one = next_one;
733       last_one = &next_one->next;
734     }
735   *last_one = (bfd *) NULL;
736   if (bfd_get_error () != bfd_error_no_more_archived_files)
737     goto bloser;
738   return arch;
739 }
740
741 static void
742 print_contents (abfd)
743      bfd *abfd;
744 {
745   int ncopied = 0;
746   char *cbuf = xmalloc (BUFSIZE);
747   struct stat buf;
748   long size;
749   if (bfd_stat_arch_elt (abfd, &buf) != 0)
750     /* xgettext:c-format */
751     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
752
753   if (verbose)
754     /* xgettext:c-format */
755     printf (_("\n<member %s>\n\n"), bfd_get_filename (abfd));
756
757   bfd_seek (abfd, 0, SEEK_SET);
758
759   size = buf.st_size;
760   while (ncopied < size)
761     {
762
763       int nread;
764       int tocopy = size - ncopied;
765       if (tocopy > BUFSIZE)
766         tocopy = BUFSIZE;
767
768       nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
769                                                            abstraction!  */
770       if (nread != tocopy)
771         /* xgettext:c-format */
772         fatal (_("%s is not a valid archive"),
773                bfd_get_filename (bfd_my_archive (abfd)));
774       fwrite (cbuf, 1, nread, stdout);
775       ncopied += tocopy;
776     }
777   free (cbuf);
778 }
779
780 /* Extract a member of the archive into its own file.
781
782    We defer opening the new file until after we have read a BUFSIZ chunk of the
783    old one, since we know we have just read the archive header for the old
784    one.  Since most members are shorter than BUFSIZ, this means we will read
785    the old header, read the old data, write a new inode for the new file, and
786    write the new data, and be done. This 'optimization' is what comes from
787    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
788    Gilmore  */
789
790 void
791 extract_file (abfd)
792      bfd *abfd;
793 {
794   FILE *ostream;
795   char *cbuf = xmalloc (BUFSIZE);
796   int nread, tocopy;
797   long ncopied = 0;
798   long size;
799   struct stat buf;
800   
801   if (bfd_stat_arch_elt (abfd, &buf) != 0)
802     /* xgettext:c-format */
803     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
804   size = buf.st_size;
805
806   if (size < 0)
807     /* xgettext:c-format */
808     fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
809   
810   if (verbose)
811     printf ("x - %s\n", bfd_get_filename (abfd));
812
813   bfd_seek (abfd, 0, SEEK_SET);
814
815   ostream = NULL;
816   if (size == 0)
817     {
818       /* Seems like an abstraction violation, eh?  Well it's OK! */
819       output_filename = bfd_get_filename (abfd);
820
821       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
822       if (ostream == NULL)
823         {
824           perror (bfd_get_filename (abfd));
825           xexit (1);
826         }
827
828       output_file = ostream;
829     }
830   else
831     while (ncopied < size)
832       {
833         tocopy = size - ncopied;
834         if (tocopy > BUFSIZE)
835           tocopy = BUFSIZE;
836
837         nread = bfd_read (cbuf, 1, tocopy, abfd);
838         if (nread != tocopy)
839           /* xgettext:c-format */
840           fatal (_("%s is not a valid archive"),
841                  bfd_get_filename (bfd_my_archive (abfd)));
842
843         /* See comment above; this saves disk arm motion */
844         if (ostream == NULL)
845           {
846             /* Seems like an abstraction violation, eh?  Well it's OK! */
847             output_filename = bfd_get_filename (abfd);
848
849             ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
850             if (ostream == NULL)
851               {
852                 perror (bfd_get_filename (abfd));
853                 xexit (1);
854               }
855
856             output_file = ostream;
857           }
858         fwrite (cbuf, 1, nread, ostream);
859         ncopied += tocopy;
860       }
861
862   if (ostream != NULL)
863     fclose (ostream);
864
865   output_file = NULL;
866   output_filename = NULL;
867
868   chmod (bfd_get_filename (abfd), buf.st_mode);
869
870   if (preserve_dates)
871     set_times (bfd_get_filename (abfd), &buf);
872
873   free (cbuf);
874 }
875
876 #if 0
877
878 /* We don't use this anymore.  Too many systems expect ar to rebuild
879    the symbol table even when q is used.  */
880
881 /* Just do it quickly; don't worry about dups, armap, or anything like that */
882
883 static void
884 do_quick_append (archive_filename, files_to_append)
885      const char *archive_filename;
886      char **files_to_append;
887 {
888   FILE *ofile, *ifile;
889   char *buf = xmalloc (BUFSIZE);
890   long tocopy, thistime;
891   bfd *temp;
892   struct stat sbuf;
893   boolean newfile = false;
894   bfd_set_error (bfd_error_no_error);
895
896   if (stat (archive_filename, &sbuf) != 0)
897     {
898
899 #ifndef __GO32__
900
901 /* KLUDGE ALERT! Temporary fix until I figger why
902  * stat() is wrong ... think it's buried in GO32's IDT
903  * - Jax
904  */
905
906       if (errno != ENOENT)
907         bfd_fatal (archive_filename);
908 #endif
909
910       newfile = true;
911     }
912
913   ofile = fopen (archive_filename, FOPEN_AUB);
914   if (ofile == NULL)
915     {
916       perror (program_name);
917       xexit (1);
918     }
919
920   temp = bfd_openr (archive_filename, NULL);
921   if (temp == NULL)
922     {
923       bfd_fatal (archive_filename);
924     }
925   if (newfile == false)
926     {
927       if (bfd_check_format (temp, bfd_archive) != true)
928         /* xgettext:c-format */
929         fatal (_("%s is not an archive"), archive_filename);
930     }
931   else
932     {
933       fwrite (ARMAG, 1, SARMAG, ofile);
934       if (!silent_create)
935         /* xgettext:c-format */
936         fprintf (stderr, _("%s: creating %s\n"),
937                  program_name, archive_filename);
938     }
939
940   if (ar_truncate)
941     temp->flags |= BFD_TRADITIONAL_FORMAT;
942
943   /* assume it's an achive, go straight to the end, sans $200 */
944   fseek (ofile, 0, 2);
945
946   for (; files_to_append && *files_to_append; ++files_to_append)
947     {
948       struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
949       if (hdr == NULL)
950         {
951           bfd_fatal (*files_to_append);
952         }
953
954       BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
955
956       ifile = fopen (*files_to_append, FOPEN_RB);
957       if (ifile == NULL)
958         {
959           bfd_nonfatal (*files_to_append);
960         }
961
962       if (stat (*files_to_append, &sbuf) != 0)
963         {
964           bfd_nonfatal (*files_to_append);
965         }
966
967       tocopy = sbuf.st_size;
968
969       /* XXX should do error-checking! */
970       fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
971
972       while (tocopy > 0)
973         {
974           thistime = tocopy;
975           if (thistime > BUFSIZE)
976             thistime = BUFSIZE;
977           fread (buf, 1, thistime, ifile);
978           fwrite (buf, 1, thistime, ofile);
979           tocopy -= thistime;
980         }
981       fclose (ifile);
982       if ((sbuf.st_size % 2) == 1)
983         putc ('\012', ofile);
984     }
985   fclose (ofile);
986   bfd_close (temp);
987   free (buf);
988 }
989
990 #endif /* 0 */
991
992 static void
993 write_archive (iarch)
994      bfd *iarch;
995 {
996   bfd *obfd;
997   char *old_name, *new_name;
998   bfd *contents_head = iarch->next;
999
1000   old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
1001   strcpy (old_name, bfd_get_filename (iarch));
1002   new_name = make_tempname (old_name);
1003
1004   output_filename = new_name;
1005
1006   obfd = bfd_openw (new_name, bfd_get_target (iarch));
1007
1008   if (obfd == NULL)
1009     bfd_fatal (old_name);
1010
1011   output_bfd = obfd;
1012
1013   bfd_set_format (obfd, bfd_archive);
1014
1015   /* Request writing the archive symbol table unless we've
1016      been explicitly requested not to.  */
1017   obfd->has_armap = write_armap >= 0;
1018
1019   if (ar_truncate)
1020     {
1021       /* This should really use bfd_set_file_flags, but that rejects
1022          archives.  */
1023       obfd->flags |= BFD_TRADITIONAL_FORMAT;
1024     }
1025
1026   if (bfd_set_archive_head (obfd, contents_head) != true)
1027     bfd_fatal (old_name);
1028
1029   if (!bfd_close (obfd))
1030     bfd_fatal (old_name);
1031
1032   output_bfd = NULL;
1033   output_filename = NULL;
1034
1035   /* We don't care if this fails; we might be creating the archive.  */
1036   bfd_close (iarch);
1037
1038   if (smart_rename (new_name, old_name, 0) != 0)
1039     xexit (1);
1040 }
1041
1042 /* Return a pointer to the pointer to the entry which should be rplacd'd
1043    into when altering.  DEFAULT_POS should be how to interpret pos_default,
1044    and should be a pos value.  */
1045
1046 static bfd **
1047 get_pos_bfd (contents, default_pos, default_posname)
1048      bfd **contents;
1049      enum pos default_pos;
1050      const char *default_posname;
1051 {
1052   bfd **after_bfd = contents;
1053   enum pos realpos;
1054   const char *realposname;
1055
1056   if (postype == pos_default)
1057     {
1058       realpos = default_pos;
1059       realposname = default_posname;
1060     }
1061   else
1062     {
1063       realpos = postype;
1064       realposname = posname;
1065     }
1066
1067   if (realpos == pos_end)
1068     {
1069       while (*after_bfd)
1070         after_bfd = &((*after_bfd)->next);
1071     }
1072   else
1073     {
1074       for (; *after_bfd; after_bfd = &(*after_bfd)->next)
1075         if (strcmp ((*after_bfd)->filename, realposname) == 0)
1076           {
1077             if (realpos == pos_after)
1078               after_bfd = &(*after_bfd)->next;
1079             break;
1080           }
1081     }
1082   return after_bfd;
1083 }
1084
1085 static void
1086 delete_members (arch, files_to_delete)
1087      bfd *arch;
1088      char **files_to_delete;
1089 {
1090   bfd **current_ptr_ptr;
1091   boolean found;
1092   boolean something_changed = false;
1093   for (; *files_to_delete != NULL; ++files_to_delete)
1094     {
1095       /* In a.out systems, the armap is optional.  It's also called
1096          __.SYMDEF.  So if the user asked to delete it, we should remember
1097          that fact. This isn't quite right for COFF systems (where
1098          __.SYMDEF might be regular member), but it's very unlikely
1099          to be a problem.  FIXME */
1100
1101       if (!strcmp (*files_to_delete, "__.SYMDEF"))
1102         {
1103           arch->has_armap = false;
1104           write_armap = -1;
1105           continue;
1106         }
1107
1108       found = false;
1109       current_ptr_ptr = &(arch->next);
1110       while (*current_ptr_ptr)
1111         {
1112           if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
1113             {
1114               found = true;
1115               something_changed = true;
1116               if (verbose)
1117                 printf ("d - %s\n",
1118                         *files_to_delete);
1119               *current_ptr_ptr = ((*current_ptr_ptr)->next);
1120               goto next_file;
1121             }
1122           else
1123             {
1124               current_ptr_ptr = &((*current_ptr_ptr)->next);
1125             }
1126         }
1127
1128       if (verbose && found == false)
1129         {
1130           /* xgettext:c-format */
1131           printf (_("No member named `%s'\n"), *files_to_delete);
1132         }
1133     next_file:
1134       ;
1135     }
1136
1137   if (something_changed == true)
1138     {
1139       write_archive (arch);
1140     }
1141 }
1142
1143
1144 /* Reposition existing members within an archive */
1145
1146 static void
1147 move_members (arch, files_to_move)
1148      bfd *arch;
1149      char **files_to_move;
1150 {
1151   bfd **after_bfd;              /* New entries go after this one */
1152   bfd **current_ptr_ptr;        /* cdr pointer into contents */
1153
1154   for (; *files_to_move; ++files_to_move)
1155     {
1156       current_ptr_ptr = &(arch->next);
1157       while (*current_ptr_ptr)
1158         {
1159           bfd *current_ptr = *current_ptr_ptr;
1160           if (strcmp (normalize (*files_to_move, arch),
1161                       current_ptr->filename) == 0)
1162             {
1163               /* Move this file to the end of the list - first cut from
1164                  where it is.  */
1165               bfd *link;
1166               *current_ptr_ptr = current_ptr->next;
1167
1168               /* Now glue to end */
1169               after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1170               link = *after_bfd;
1171               *after_bfd = current_ptr;
1172               current_ptr->next = link;
1173
1174               if (verbose)
1175                 printf ("m - %s\n", *files_to_move);
1176
1177               goto next_file;
1178             }
1179
1180           current_ptr_ptr = &((*current_ptr_ptr)->next);
1181         }
1182       /* xgettext:c-format */
1183       fprintf (stderr, _("%s: no entry %s in archive %s!\n"),
1184                program_name, *files_to_move, arch->filename);
1185       xexit (1);
1186     next_file:;
1187     }
1188
1189   write_archive (arch);
1190 }
1191
1192 /* Ought to default to replacing in place, but this is existing practice!  */
1193
1194 static void
1195 replace_members (arch, files_to_move, quick)
1196      bfd *arch;
1197      char **files_to_move;
1198      boolean quick;
1199 {
1200   boolean changed = false;
1201   bfd **after_bfd;              /* New entries go after this one */
1202   bfd *current;
1203   bfd **current_ptr;
1204   bfd *temp;
1205
1206   while (files_to_move && *files_to_move)
1207     {
1208       if (! quick)
1209         {
1210           current_ptr = &arch->next;
1211           while (*current_ptr)
1212             {
1213               current = *current_ptr;
1214
1215               /* For compatibility with existing ar programs, we
1216                  permit the same file to be added multiple times.  */
1217               if (strcmp (normalize (*files_to_move, arch),
1218                           normalize (current->filename, arch)) == 0
1219                   && current->arelt_data != NULL)
1220                 {
1221                   if (newer_only)
1222                     {
1223                       struct stat fsbuf, asbuf;
1224
1225                       if (stat (*files_to_move, &fsbuf) != 0)
1226                         {
1227                           if (errno != ENOENT)
1228                             bfd_fatal (*files_to_move);
1229                           goto next_file;
1230                         }
1231                       if (bfd_stat_arch_elt (current, &asbuf) != 0)
1232                         /* xgettext:c-format */
1233                         fatal (_("internal stat error on %s"), current->filename);
1234
1235                       if (fsbuf.st_mtime <= asbuf.st_mtime)
1236                         goto next_file;
1237                     }
1238
1239                   after_bfd = get_pos_bfd (&arch->next, pos_after,
1240                                            current->filename);
1241                   temp = *after_bfd;
1242
1243                   *after_bfd = bfd_openr (*files_to_move, NULL);
1244                   if (*after_bfd == (bfd *) NULL)
1245                     {
1246                       bfd_fatal (*files_to_move);
1247                     }
1248                   (*after_bfd)->next = temp;
1249
1250                   /* snip out this entry from the chain */
1251                   *current_ptr = (*current_ptr)->next;
1252
1253                   if (verbose)
1254                     {
1255                       printf ("r - %s\n", *files_to_move);
1256                     }
1257
1258                   changed = true;
1259
1260                   goto next_file;
1261                 }
1262               current_ptr = &(current->next);
1263             }
1264         }
1265
1266       /* Add to the end of the archive.  */
1267
1268       after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1269       temp = *after_bfd;
1270       *after_bfd = bfd_openr (*files_to_move, NULL);
1271       if (*after_bfd == (bfd *) NULL)
1272         {
1273           bfd_fatal (*files_to_move);
1274         }
1275       if (verbose)
1276         {
1277           printf ("a - %s\n", *files_to_move);
1278         }
1279
1280       (*after_bfd)->next = temp;
1281
1282       changed = true;
1283
1284     next_file:;
1285
1286       files_to_move++;
1287     }
1288
1289   if (changed)
1290     write_archive (arch);
1291 }
1292
1293 static void
1294 ranlib_only (archname)
1295      const char *archname;
1296 {
1297   bfd *arch;
1298
1299   write_armap = 1;
1300   arch = open_inarch (archname, (char *) NULL);
1301   if (arch == NULL)
1302     xexit (1);
1303   write_archive (arch);
1304 }
1305
1306 /* Update the timestamp of the symbol map of an archive.  */
1307
1308 static void
1309 ranlib_touch (archname)
1310      const char *archname;
1311 {
1312 #ifdef __GO32__
1313   /* I don't think updating works on go32.  */
1314   ranlib_only (archname);
1315 #else
1316   int f;
1317   bfd *arch;
1318   char **matching;
1319
1320   f = open (archname, O_RDWR | O_BINARY, 0);
1321   if (f < 0)
1322     {
1323       bfd_set_error (bfd_error_system_call);
1324       bfd_fatal (archname);
1325     }
1326
1327   arch = bfd_fdopenr (archname, (const char *) NULL, f);
1328   if (arch == NULL)
1329     bfd_fatal (archname);
1330   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1331     {
1332       bfd_nonfatal (archname);
1333       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1334         {
1335           list_matching_formats (matching);
1336           free (matching);
1337         }
1338       xexit (1);
1339     }
1340
1341   if (! bfd_has_map (arch))
1342     /* xgettext:c-format */
1343     fatal (_("%s: no archive map to update"), archname);
1344
1345   bfd_update_armap_timestamp (arch);
1346
1347   if (! bfd_close (arch))
1348     bfd_fatal (archname);
1349 #endif
1350 }
1351
1352 /* Things which are interesting to map over all or some of the files: */
1353
1354 static void
1355 print_descr (abfd)
1356      bfd *abfd;
1357 {
1358   print_arelt_descr (stdout, abfd, verbose);
1359 }