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