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