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