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