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