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