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