OSDN Git Service

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