]> Git Repo - binutils.git/blob - binutils/ar.c
syslex.l, objdump.c/config changes
[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   program_name = argv[0];
234   xmalloc_set_program_name (program_name);
235
236   bfd_init ();
237   show_version = 0;
238
239   temp = strrchr (program_name, '/');
240   if (temp == (char *) NULL)
241     temp = program_name;        /* shouldn't happen, but... */
242   else
243     ++temp;
244   if (is_ranlib > 0 || (is_ranlib < 0 && strcmp (temp, "ranlib") == 0))
245     {
246       is_ranlib = 1;
247       if (argc < 2 || argc > 3)
248         usage ();
249       arg_ptr = argv[1];
250       if (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "-v") == 0)
251         do_show_version ();
252       ranlib_only (arg_ptr);
253     }
254   else
255     is_ranlib = 0;
256
257   if (argc == 2 && strcmp (argv[1], "-M") == 0)
258     {
259       mri_emul ();
260       exit (0);
261     }
262
263   if (argc < 2)
264     usage ();
265
266   arg_ptr = argv[1];
267
268   if (*arg_ptr == '-')
269     ++arg_ptr;                  /* compatibility */
270
271   while ((c = *arg_ptr++) != '\0')
272     {
273       switch (c)
274         {
275         case 'd':
276         case 'm':
277         case 'p':
278         case 'q':
279         case 'r':
280         case 't':
281         case 'x':
282           if (operation != none)
283             fatal ("two different operation options specified");
284           switch (c)
285             {
286             case 'd':
287               operation = delete;
288               operation_alters_arch = true;
289               break;
290             case 'm':
291               operation = move;
292               operation_alters_arch = true;
293               break;
294             case 'p':
295               operation = print_files;
296               break;
297             case 'q':
298               operation = quick_append;
299               operation_alters_arch = true;
300               break;
301             case 'r':
302               operation = replace;
303               operation_alters_arch = true;
304               break;
305             case 't':
306               operation = print_table;
307               break;
308             case 'x':
309               operation = extract;
310               break;
311             }
312         case 'l':
313           break;
314         case 'c':
315           silent_create = 1;
316           break;
317         case 'o':
318           preserve_dates = 1;
319           break;
320         case 'V':
321           show_version = true;
322           break;
323         case 's':
324           write_armap = 1;
325           break;
326         case 'u':
327           newer_only = 1;
328           break;
329         case 'v':
330           verbose = 1;
331           break;
332         case 'a':
333           postype = pos_after;
334           break;
335         case 'b':
336           postype = pos_before;
337           break;
338         case 'i':
339           postype = pos_before;
340           break;
341         case 'M':
342           mri_mode = 1;
343           break;
344         default:
345           fprintf (stderr, "%s: illegal option -- %c\n", program_name, c);
346           usage ();
347         }
348     }
349
350   if (show_version)
351     do_show_version ();
352
353   if (argc < 3)
354     usage ();
355
356   if (mri_mode)
357     {
358       mri_emul ();
359     }
360   else
361     {
362       if ((operation == none || operation == print_table)
363           && write_armap == 1)
364         ranlib_only (argv[2]);
365
366       if (operation == none)
367         fatal ("no operation specified");
368
369       if (newer_only && operation != replace)
370         fatal ("`u' is only meaningful with the `r' option.");
371
372       arg_index = 2;
373
374       if (postype != pos_default)
375         posname = argv[arg_index++];
376
377       inarch_filename = argv[arg_index++];
378
379       files = arg_index < argc ? argv + arg_index : NULL;
380
381       if (operation == quick_append)
382         {
383           /* Note that quick appending to a non-existent archive creates it,
384              even if there are no files to append. */
385           do_quick_append (inarch_filename, files);
386           exit (0);
387         }
388
389       open_inarch (inarch_filename);
390
391       switch (operation)
392         {
393         case print_table:
394           map_over_members (print_descr, files, argc - 3);
395           break;
396
397         case print_files:
398           map_over_members (print_contents, files, argc - 3);
399           break;
400
401         case extract:
402           map_over_members (extract_file, files, argc - 3);
403           break;
404
405         case delete:
406           if (files != NULL)
407             delete_members (files);
408           break;
409
410         case move:
411           if (files != NULL)
412             move_members (files);
413           break;
414
415         case replace:
416           if (files != NULL || write_armap > 0)
417             replace_members (files);
418           break;
419
420           /* Shouldn't happen! */
421         default:
422           fprintf (stderr, "%s: internal error -- this option not implemented\n",
423                    program_name);
424           exit (1);
425         }
426     }
427   return 0;
428 }
429
430 static char *
431 normalize (file)
432      char *file;
433 {
434   char *filename = strrchr (file, '/');
435   if (filename != (char *) NULL)
436     {
437       filename++;
438     }
439   else
440     {
441       filename = file;
442     }
443   return filename;
444 }
445
446 int
447 open_inarch (archive_filename)
448      char *archive_filename;
449 {
450   bfd **last_one;
451   bfd *next_one;
452   struct stat sbuf;
453   bfd_set_error (bfd_error_no_error);
454
455   if (stat (archive_filename, &sbuf) != 0)
456     {
457
458 #ifndef __GO32__
459
460 /* KLUDGE ALERT! Temporary fix until I figger why
461  * stat() is wrong ... think it's buried in GO32's IDT
462  * - Jax
463  */
464       if (errno != ENOENT)
465         bfd_fatal (archive_filename);
466 #endif
467
468       if (!operation_alters_arch)
469         {
470           fprintf (stderr, "%s: ", program_name);
471           perror (archive_filename);
472           maybequit ();
473           return 0;
474         }
475
476       /* This routine is one way to forcibly create the archive. */
477
478       do_quick_append (archive_filename, 0);
479     }
480
481   inarch = bfd_openr (archive_filename, NULL);
482   if (inarch == NULL)
483     {
484     bloser:
485       bfd_fatal (archive_filename);
486     }
487
488   if (bfd_check_format (inarch, bfd_archive) != true)
489     fatal ("%s is not an archive", archive_filename);
490   last_one = &(inarch->next);
491   /* Read all the contents right away, regardless.  */
492   for (next_one = bfd_openr_next_archived_file (inarch, NULL);
493        next_one;
494        next_one = bfd_openr_next_archived_file (inarch, next_one))
495     {
496       *last_one = next_one;
497       last_one = &next_one->next;
498     }
499   *last_one = (bfd *) NULL;
500   if (bfd_get_error () != bfd_error_no_more_archived_files)
501     goto bloser;
502   return 1;
503 }
504
505 static void
506 print_contents (abfd)
507      bfd *abfd;
508 {
509   int ncopied = 0;
510   struct stat buf;
511   long size;
512   if (bfd_stat_arch_elt (abfd, &buf) != 0)
513     fatal ("internal stat error on %s", bfd_get_filename (abfd));
514
515   if (verbose)
516     printf ("\n<member %s>\n\n", bfd_get_filename (abfd));
517
518   bfd_seek (abfd, 0, SEEK_SET);
519
520   size = buf.st_size;
521   while (ncopied < size)
522     {
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       if (nread != tocopy)
532         fatal ("%s is not a valid archive",
533                bfd_get_filename (bfd_my_archive (abfd)));
534       fwrite (cbuf, 1, nread, stdout);
535       ncopied += tocopy;
536     }
537 }
538
539 /* Extract a member of the archive into its own file.
540
541    We defer opening the new file until after we have read a BUFSIZ chunk of the
542    old one, since we know we have just read the archive header for the old
543    one.  Since most members are shorter than BUFSIZ, this means we will read
544    the old header, read the old data, write a new inode for the new file, and
545    write the new data, and be done. This 'optimization' is what comes from
546    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
547    Gilmore  */
548
549 void
550 extract_file (abfd)
551      bfd *abfd;
552 {
553   FILE *ostream;
554   char cbuf[BUFSIZE];
555   int nread, tocopy;
556   int ncopied = 0;
557   long size;
558   struct stat buf;
559   if (bfd_stat_arch_elt (abfd, &buf) != 0)
560     fatal ("internal stat error on %s", bfd_get_filename (abfd));
561   size = buf.st_size;
562
563   if (verbose)
564     printf ("x - %s\n", bfd_get_filename (abfd));
565
566   bfd_seek (abfd, 0, SEEK_SET);
567
568   ostream = 0;
569   if (size == 0)
570     {
571       /* Seems like an abstraction violation, eh?  Well it's OK! */
572       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
573       if (!ostream)
574         {
575           perror (bfd_get_filename (abfd));
576           exit (1);
577         }
578     }
579   else
580     while (ncopied < size)
581       {
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 ("%s is not a valid archive",
589                  bfd_get_filename (bfd_my_archive (abfd)));
590
591         /* See comment above; this saves disk arm motion */
592         if (!ostream)
593           {
594             /* Seems like an abstraction violation, eh?  Well it's OK! */
595             ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
596             if (!ostream)
597               {
598                 perror (bfd_get_filename (abfd));
599                 exit (1);
600               }
601           }
602         fwrite (cbuf, 1, nread, ostream);
603         ncopied += tocopy;
604       }
605
606   fclose (ostream);
607   chmod (bfd_get_filename (abfd), buf.st_mode);
608
609   if (preserve_dates)
610     {
611 #ifdef POSIX_UTIME
612       struct utimbuf tb;
613       tb.actime = buf.st_mtime;
614       tb.modtime = buf.st_mtime;
615       utime (bfd_get_filename (abfd), &tb);     /* FIXME check result */
616 #else /* ! POSIX_UTIME */
617 #ifdef USE_UTIME
618       long tb[2];
619       tb[0] = buf.st_mtime;
620       tb[1] = buf.st_mtime;
621       utime (bfd_get_filename (abfd), tb);      /* FIXME check result */
622 #else /* ! USE_UTIME */
623       struct timeval tv[2];
624       tv[0].tv_sec = buf.st_mtime;
625       tv[0].tv_usec = 0;
626       tv[1].tv_sec = buf.st_mtime;
627       tv[1].tv_usec = 0;
628       utimes (bfd_get_filename (abfd), tv);     /* FIXME check result */
629 #endif /* ! USE_UTIME */
630 #endif /* ! POSIX_UTIME */
631     }
632 }
633
634 /* Just do it quickly; don't worry about dups, armap, or anything like that */
635
636 static void
637 do_quick_append (archive_filename, files_to_append)
638      char *archive_filename;
639      char **files_to_append;
640 {
641   FILE *ofile, *ifile;
642   char buf[BUFSIZE];
643   long tocopy, thistime;
644   bfd *temp;
645   struct stat sbuf;
646   boolean newfile = false;
647   bfd_set_error (bfd_error_no_error);
648
649   if (stat (archive_filename, &sbuf) != 0)
650     {
651
652 #ifndef __GO32__
653
654 /* KLUDGE ALERT! Temporary fix until I figger why
655  * stat() is wrong ... think it's buried in GO32's IDT
656  * - Jax
657  */
658
659       if (errno != ENOENT)
660         bfd_fatal (archive_filename);
661 #endif
662
663       newfile = true;
664     }
665
666   ofile = fopen (archive_filename, FOPEN_AUB);
667   if (ofile == NULL)
668     {
669       perror (program_name);
670       exit (1);
671     }
672
673   temp = bfd_openr (archive_filename, NULL);
674   if (temp == NULL)
675     {
676       bfd_fatal (archive_filename);
677     }
678   if (newfile == false)
679     {
680       if (bfd_check_format (temp, bfd_archive) != true)
681         fatal ("%s is not an archive", archive_filename);
682     }
683   else
684     {
685       fwrite (ARMAG, 1, SARMAG, ofile);
686       if (!silent_create)
687         fprintf (stderr, "%s: creating %s\n",
688                  program_name, archive_filename);
689     }
690
691   /* assume it's an achive, go straight to the end, sans $200 */
692   fseek (ofile, 0, 2);
693
694   for (; files_to_append && *files_to_append; ++files_to_append)
695     {
696       struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
697       if (hdr == NULL)
698         {
699           bfd_fatal (*files_to_append);
700         }
701
702       BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
703
704       ifile = fopen (*files_to_append, FOPEN_RB);
705       if (ifile == NULL)
706         {
707           bfd_nonfatal (*files_to_append);
708         }
709
710       if (stat (*files_to_append, &sbuf) != 0)
711         {
712           bfd_nonfatal (*files_to_append);
713         }
714
715       tocopy = sbuf.st_size;
716
717       /* XXX should do error-checking! */
718       fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
719
720       while (tocopy > 0)
721         {
722           thistime = tocopy;
723           if (thistime > BUFSIZE)
724             thistime = BUFSIZE;
725           fread (buf, 1, thistime, ifile);
726           fwrite (buf, 1, thistime, ofile);
727           tocopy -= thistime;
728         }
729       fclose (ifile);
730       if ((sbuf.st_size % 2) == 1)
731         putc ('\012', ofile);
732     }
733   fclose (ofile);
734   bfd_close (temp);
735 }
736
737
738 void
739 write_archive ()
740 {
741   bfd *obfd;
742   int namelen = strlen (inarch->filename);
743   char *new_name = xmalloc (namelen + EXT_NAME_LEN);
744   bfd *contents_head = inarch->next;
745
746   strcpy (new_name, inarch->filename);
747
748 #ifdef __GO32__                 /* avoid long .extensions for MS-DOS */
749   strcpy (new_name + namelen, "-a");
750 #else
751   strcpy (new_name + namelen, "-art");
752 #endif
753
754   obfd = bfd_openw (new_name,
755   /* FIXME: violates abstraction; need a better protocol */
756                     (inarch->xvec ? bfd_get_target (inarch) : NULL));
757
758   if (obfd == NULL)
759     bfd_fatal (inarch->filename);
760
761   bfd_set_format (obfd, bfd_archive);
762
763   /* Request writing the archive symbol table unless we've
764      been explicitly requested not to.  */
765   obfd->has_armap = write_armap >= 0;
766
767   if (bfd_set_archive_head (obfd, contents_head) != true)
768     bfd_fatal (inarch->filename);
769
770   if (!bfd_close (obfd))
771     bfd_fatal (inarch->filename);
772
773   /* We don't care if this fails; we might be creating the archive.  */
774   unlink (inarch->filename);
775
776   if (rename (new_name, inarch->filename) != 0)
777     bfd_fatal (inarch->filename);
778 }
779
780 /* Return a pointer to the pointer to the entry which should be rplacd'd
781    into when altering.  DEFAULT_POS should be how to interpret pos_default,
782    and should be a pos value.  */
783
784 bfd **
785 get_pos_bfd (contents, default_pos)
786      bfd **contents;
787      enum pos default_pos;
788 {
789   bfd **after_bfd = contents;
790   enum pos realpos = (postype == pos_default ? default_pos : postype);
791
792   if (realpos == pos_end)
793     {
794       while (*after_bfd)
795         after_bfd = &((*after_bfd)->next);
796     }
797   else
798     {
799       for (; *after_bfd; after_bfd = &(*after_bfd)->next)
800         if (!strcmp ((*after_bfd)->filename, posname))
801           {
802             if (realpos == pos_after)
803               after_bfd = &(*after_bfd)->next;
804             break;
805           }
806     }
807   return after_bfd;
808 }
809
810 static void
811 delete_members (files_to_delete)
812      char **files_to_delete;
813 {
814   bfd **current_ptr_ptr;
815   boolean found;
816   boolean something_changed = false;
817   for (; *files_to_delete != NULL; ++files_to_delete)
818     {
819       /* In a.out systems, the armap is optional.  It's also called
820          __.SYMDEF.  So if the user asked to delete it, we should remember
821          that fact. This isn't quite right for COFF systems (where
822          __.SYMDEF might be regular member), but it's very unlikely
823          to be a problem.  FIXME */
824
825       if (!strcmp (*files_to_delete, "__.SYMDEF"))
826         {
827           inarch->has_armap = false;
828           write_armap = -1;
829           continue;
830         }
831
832       found = false;
833       current_ptr_ptr = &(inarch->next);
834       while (*current_ptr_ptr)
835         {
836           if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
837             {
838               found = true;
839               something_changed = true;
840               if (verbose)
841                 printf ("d - %s\n",
842                         *files_to_delete);
843               *current_ptr_ptr = ((*current_ptr_ptr)->next);
844               goto next_file;
845             }
846           else
847             {
848               current_ptr_ptr = &((*current_ptr_ptr)->next);
849             }
850         }
851
852       if (verbose && found == false)
853         {
854           printf ("No member named `%s'\n", *files_to_delete);
855         }
856     next_file:
857       ;
858     }
859
860   if (something_changed == true)
861     {
862       write_archive ();
863     }
864 }
865
866
867 /* Reposition existing members within an archive */
868
869 static void
870 move_members (files_to_move)
871      char **files_to_move;
872 {
873   bfd **after_bfd;              /* New entries go after this one */
874   bfd **current_ptr_ptr;        /* cdr pointer into contents */
875
876   for (; *files_to_move; ++files_to_move)
877     {
878       current_ptr_ptr = &(inarch->next);
879       while (*current_ptr_ptr)
880         {
881           bfd *current_ptr = *current_ptr_ptr;
882           if (strcmp (normalize (*files_to_move), current_ptr->filename) == 0)
883             {
884               /* Move this file to the end of the list - first cut from
885                  where it is.  */
886               bfd *link;
887               *current_ptr_ptr = current_ptr->next;
888
889               /* Now glue to end */
890               after_bfd = get_pos_bfd (&inarch->next, pos_end);
891               link = *after_bfd;
892               *after_bfd = current_ptr;
893               current_ptr->next = link;
894
895               if (verbose)
896                 printf ("m - %s\n", *files_to_move);
897
898               goto next_file;
899             }
900
901           current_ptr_ptr = &((*current_ptr_ptr)->next);
902         }
903       fprintf (stderr, "%s: no entry %s in archive %s!\n",
904                program_name, *files_to_move, inarch->filename);
905       exit (1);
906     next_file:;
907     }
908
909   write_archive ();
910 }
911
912 /* Ought to default to replacing in place, but this is existing practice!  */
913
914 static void
915 replace_members (files_to_move)
916      char **files_to_move;
917 {
918   bfd **after_bfd;              /* New entries go after this one */
919   bfd *current;
920   bfd **current_ptr;
921   bfd *temp;
922
923   while (files_to_move && *files_to_move)
924     {
925       current_ptr = &inarch->next;
926       while (*current_ptr)
927         {
928           current = *current_ptr;
929
930           if (!strcmp (normalize (*files_to_move), current->filename))
931             {
932               if (newer_only)
933                 {
934                   struct stat fsbuf, asbuf;
935
936                   if (current->arelt_data == NULL)
937                     {
938                       /* This can only happen if you specify a file on the
939                          command line more than once. */
940                       fprintf (stderr,
941                                "%s: duplicate file specified: %s -- skipping\n",
942                                program_name, *files_to_move);
943                       goto next_file;
944                     }
945
946                   if (stat (*files_to_move, &fsbuf) != 0)
947                     {
948                       if (errno != ENOENT)
949                         bfd_fatal (*files_to_move);
950                       goto next_file;
951                     }
952                   if (bfd_stat_arch_elt (current, &asbuf) != 0)
953                     fatal ("internal stat error on %s", current->filename);
954
955                   if (fsbuf.st_mtime <= asbuf.st_mtime)
956                     goto next_file;
957                 }
958
959               /* snip out this entry from the chain */
960               *current_ptr = current->next;
961
962               after_bfd = get_pos_bfd (&inarch->next, pos_end);
963               temp = *after_bfd;
964               *after_bfd = bfd_openr (*files_to_move, NULL);
965               if (*after_bfd == (bfd *) NULL)
966                 {
967                   bfd_fatal (*files_to_move);
968                 }
969               (*after_bfd)->next = temp;
970
971               if (verbose)
972                 {
973                   printf ("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
974                           *files_to_move);
975                 }
976               goto next_file;
977             }
978           current_ptr = &(current->next);
979         }
980
981       /* It isn't in there, so add to end */
982
983       after_bfd = get_pos_bfd (&inarch->next, pos_end);
984       temp = *after_bfd;
985       *after_bfd = bfd_openr (*files_to_move, NULL);
986       if (*after_bfd == (bfd *) NULL)
987         {
988           bfd_fatal (*files_to_move);
989         }
990       if (verbose)
991         {
992           printf ("c - %s\n", *files_to_move);
993         }
994
995       (*after_bfd)->next = temp;
996
997     next_file:;
998
999       files_to_move++;
1000     }
1001
1002   write_archive ();
1003 }
1004
1005 static void
1006 ranlib_only (archname)
1007      char *archname;
1008 {
1009   write_armap = 1;
1010   open_inarch (archname);
1011   write_archive ();
1012   exit (0);
1013 }
1014
1015 /* Things which are interesting to map over all or some of the files: */
1016
1017 static void
1018 print_descr (abfd)
1019      bfd *abfd;
1020 {
1021   print_arelt_descr (stdout, abfd, verbose);
1022 }
This page took 0.082619 seconds and 4 git commands to generate.