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