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