Revert incorrect 2000-06-25 patch.
[external/binutils.git] / binutils / ar.c
1 /* ar.c - Archive modify and extract.
2    Copyright 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
3    Free Software Foundation, Inc.
4
5 This file is part of GNU Binutils.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
20 \f
21 /*
22    Bugs: should use getopt the way tar does (complete w/optional -) and
23    should have long options too. GNU ar used to check file against filesystem
24    in quick_update and replace operations (would check mtime). Doesn't warn
25    when name truncated. No way to specify pos_end. Error messages should be
26    more consistant.
27 */
28 #include "bfd.h"
29 #include "libiberty.h"
30 #include "progress.h"
31 #include "bucomm.h"
32 #include "aout/ar.h"
33 #include "libbfd.h"
34 #include "arsup.h"
35 #include "filenames.h"
36 #include <sys/stat.h>
37
38 #ifdef __GO32___
39 #define EXT_NAME_LEN 3          /* bufflen of addition to name if it's MS-DOS */
40 #else
41 #define EXT_NAME_LEN 6          /* ditto for *NIX */
42 #endif
43
44 /* We need to open files in binary modes on system where that makes a
45    difference.  */
46 #ifndef O_BINARY
47 #define O_BINARY 0
48 #endif
49
50 #define BUFSIZE 8192
51
52 /* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
53
54 struct ar_hdr *
55   bfd_special_undocumented_glue PARAMS ((bfd * abfd, const char *filename));
56
57 /* Static declarations */
58
59 static void
60 mri_emul PARAMS ((void));
61
62 static const char *
63 normalize PARAMS ((const char *, bfd *));
64
65 static void
66 remove_output PARAMS ((void));
67
68 static void
69 map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int));
70
71 static void
72 print_contents PARAMS ((bfd * member));
73
74 static void
75 delete_members PARAMS ((bfd *, char **files_to_delete));
76
77 #if 0
78 static void
79 do_quick_append PARAMS ((const char *archive_filename,
80                          char **files_to_append));
81 #endif
82
83 static void
84 move_members PARAMS ((bfd *, char **files_to_move));
85
86 static void
87 replace_members PARAMS ((bfd *, char **files_to_replace, boolean quick));
88
89 static void
90 print_descr PARAMS ((bfd * abfd));
91
92 static void
93 write_archive PARAMS ((bfd *));
94
95 static void
96 ranlib_only PARAMS ((const char *archname));
97
98 static void
99 ranlib_touch PARAMS ((const char *archname));
100
101 static void
102 usage PARAMS ((int));
103 \f
104 /** Globals and flags */
105
106 int mri_mode;
107
108 /* This flag distinguishes between ar and ranlib:
109    1 means this is 'ranlib'; 0 means this is 'ar'.
110    -1 means if we should use argv[0] to decide.  */
111 extern int is_ranlib;
112
113 /* Nonzero means don't warn about creating the archive file if necessary.  */
114 int silent_create = 0;
115
116 /* Nonzero means describe each action performed.  */
117 int verbose = 0;
118
119 /* Nonzero means preserve dates of members when extracting them.  */
120 int preserve_dates = 0;
121
122 /* Nonzero means don't replace existing members whose dates are more recent
123    than the corresponding files.  */
124 int newer_only = 0;
125
126 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
127    member).  -1 means we've been explicitly asked to not write a symbol table;
128    +1 means we've been explictly asked to write it;
129    0 is the default.
130    Traditionally, the default in BSD has been to not write the table.
131    However, for POSIX.2 compliance the default is now to write a symbol table
132    if any of the members are object files.  */
133 int write_armap = 0;
134
135 /* Nonzero means it's the name of an existing member; position new or moved
136    files with respect to this one.  */
137 char *posname = NULL;
138
139 /* Sez how to use `posname': pos_before means position before that member.
140    pos_after means position after that member. pos_end means always at end.
141    pos_default means default appropriately. For the latter two, `posname'
142    should also be zero.  */
143 enum pos
144   {
145     pos_default, pos_before, pos_after, pos_end
146   } postype = pos_default;
147
148 static bfd **
149 get_pos_bfd PARAMS ((bfd **, enum pos, const char *));
150
151 /* For extract/delete only.  If COUNTED_NAME_MODE is true, we only
152    extract the COUNTED_NAME_COUNTER instance of that name.  */
153 static boolean counted_name_mode = 0;
154 static int counted_name_counter = 0;
155
156 /* Whether to truncate names of files stored in the archive.  */
157 static boolean ar_truncate = false;
158
159 /* Whether to use a full file name match when searching an archive.
160    This is convenient for archives created by the Microsoft lib
161    program.  */
162 static boolean full_pathname = false;
163
164 int interactive = 0;
165
166 static void
167 mri_emul ()
168 {
169   interactive = isatty (fileno (stdin));
170   yyparse ();
171 }
172
173 /* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
174    COUNT is the length of the FILES chain; FUNCTION is called on each entry
175    whose name matches one in FILES.  */
176
177 static void
178 map_over_members (arch, function, files, count)
179      bfd *arch;
180      void (*function) PARAMS ((bfd *));
181      char **files;
182      int count;
183 {
184   bfd *head;
185   int match_count;
186
187   if (count == 0)
188     {
189       for (head = arch->next; head; head = head->next)
190         {
191           PROGRESS (1);
192           function (head);
193         }
194       return;
195     }
196
197   /* This may appear to be a baroque way of accomplishing what we want.
198      However we have to iterate over the filenames in order to notice where
199      a filename is requested but does not exist in the archive.  Ditto
200      mapping over each file each time -- we want to hack multiple
201      references.  */
202
203   for (; count > 0; files++, count--)
204     {
205       boolean found = false;
206
207       match_count = 0;
208       for (head = arch->next; head; head = head->next)
209         {
210           PROGRESS (1);
211           if (head->filename == NULL)
212             {
213               /* Some archive formats don't get the filenames filled in
214                  until the elements are opened.  */
215               struct stat buf;
216               bfd_stat_arch_elt (head, &buf);
217             }
218           if ((head->filename != NULL) &&
219               (!FILENAME_CMP (normalize (*files, arch), head->filename)))
220             {
221               ++match_count;
222               if (counted_name_mode
223                   && match_count != counted_name_counter) 
224                 {
225                   /* Counting, and didn't match on count; go on to the
226                      next one.  */
227                   continue;
228                 }
229
230               found = true;
231               function (head);
232             }
233         }
234       if (!found)
235         /* xgettext:c-format */
236         fprintf (stderr, _("no entry %s in archive\n"), *files);
237     }
238 }
239 \f
240 boolean operation_alters_arch = false;
241
242 static void
243 usage (help)
244      int help;
245 {
246   FILE *s;
247
248   s = help ? stdout : stderr;
249   
250   if (! is_ranlib)
251     {
252       /* xgettext:c-format */
253       fprintf (s, _("Usage: %s [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
254                program_name);
255       /* xgettext:c-format */
256       fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
257       fprintf (s, _(" commands:\n"));
258       fprintf (s, _("  d            - delete file(s) from the archive\n"));
259       fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
260       fprintf (s, _("  p            - print file(s) found in the archive\n"));
261       fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
262       fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
263       fprintf (s, _("  t            - display contents of archive\n"));
264       fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
265       fprintf (s, _(" command specific modifiers:\n"));
266       fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
267       fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
268       fprintf (s, _("  [N]          - use instance [count] of name\n"));
269       fprintf (s, _("  [f]          - truncate inserted file names\n"));
270       fprintf (s, _("  [P]          - use full path names when matching\n"));
271       fprintf (s, _("  [o]          - preserve original dates\n"));
272       fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
273       fprintf (s, _(" generic modifiers:\n"));
274       fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
275       fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
276       fprintf (s, _("  [S]          - do not build a symbol table\n"));
277       fprintf (s, _("  [v]          - be verbose\n"));
278       fprintf (s, _("  [V]          - display the version number\n"));
279     }
280   else
281     /* xgettext:c-format */
282     fprintf (s, _("Usage: %s [-vV] archive\n"), program_name);
283
284   list_supported_targets (program_name, stderr);
285
286   if (help)
287     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
288
289   xexit (help ? 0 : 1);
290 }
291
292 /* Normalize a file name specified on the command line into a file
293    name which we will use in an archive.  */
294
295 static const char *
296 normalize (file, abfd)
297      const char *file;
298      bfd *abfd;
299 {
300   const char *filename;
301
302   if (full_pathname)
303     return file;
304
305   filename = strrchr (file, '/');
306 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
307   {
308     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
309     char *bslash = strrchr (file, '\\');
310     if (filename == NULL || (bslash != NULL && bslash > filename))
311       filename = bslash;
312     if (filename == NULL && file[0] != '\0' && file[1] == ':')
313       filename = file + 1;
314   }
315 #endif
316   if (filename != (char *) NULL)
317     filename++;
318   else
319     filename = file;
320
321   if (ar_truncate
322       && abfd != NULL
323       && strlen (filename) > abfd->xvec->ar_max_namelen)
324     {
325       char *s;
326
327       /* Space leak.  */
328       s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
329       memcpy (s, filename, abfd->xvec->ar_max_namelen);
330       s[abfd->xvec->ar_max_namelen] = '\0';
331       filename = s;
332     }
333
334   return filename;
335 }
336
337 /* Remove any output file.  This is only called via xatexit.  */
338
339 static const char *output_filename = NULL;
340 static FILE *output_file = NULL;
341 static bfd *output_bfd = NULL;
342
343 static void
344 remove_output ()
345 {
346   if (output_filename != NULL)
347     {
348       if (output_bfd != NULL && output_bfd->iostream != NULL)
349         fclose ((FILE *) (output_bfd->iostream));
350       if (output_file != NULL)
351         fclose (output_file);
352       unlink (output_filename);
353     }
354 }
355
356 /* The option parsing should be in its own function.
357    It will be when I have getopt working.  */
358
359 int
360 main (argc, argv)
361      int argc;
362      char **argv;
363 {
364   char *arg_ptr;
365   char c;
366   enum
367     {
368       none = 0, delete, replace, print_table,
369       print_files, extract, move, quick_append
370     } operation = none;
371   int arg_index;
372   char **files;
373   int file_count;
374   char *inarch_filename;
375   int show_version;
376
377 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
378   setlocale (LC_MESSAGES, "");
379 #endif
380   bindtextdomain (PACKAGE, LOCALEDIR);
381   textdomain (PACKAGE);
382
383   program_name = argv[0];
384   xmalloc_set_program_name (program_name);
385
386   if (is_ranlib < 0)
387     {
388       char *temp;
389
390       temp = strrchr (program_name, '/');
391 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
392         {
393           /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
394           char *bslash = strrchr (program_name, '\\');
395           if (temp == NULL || (bslash != NULL && bslash > temp))
396             temp = bslash;
397           if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
398             temp = program_name + 1;
399         }
400 #endif
401       if (temp == NULL)
402         temp = program_name;
403       else
404         ++temp;
405       if (strlen (temp) >= 6
406           && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
407         is_ranlib = 1;
408       else
409         is_ranlib = 0;
410     }
411
412   if (argc > 1 && argv[1][0] == '-')
413     {
414       if (strcmp (argv[1], "--help") == 0)
415         usage (1);
416       else if (strcmp (argv[1], "--version") == 0)
417         {
418           if (is_ranlib)
419             print_version ("ranlib");
420           else
421             print_version ("ar");
422         }
423     }
424
425   START_PROGRESS (program_name, 0);
426
427   bfd_init ();
428   set_default_bfd_target ();
429
430   show_version = 0;
431
432   xatexit (remove_output);
433
434   if (is_ranlib)
435     {
436       boolean touch = false;
437
438       if (argc < 2 || strcmp (argv[1], "--help") == 0)
439         usage (0);
440       if (strcmp (argv[1], "-V") == 0
441           || strcmp (argv[1], "-v") == 0
442           || strncmp (argv[1], "--v", 3) == 0)
443         print_version ("ranlib");
444       arg_index = 1;
445       if (strcmp (argv[1], "-t") == 0)
446         {
447           ++arg_index;
448           touch = true;
449         }
450       while (arg_index < argc)
451         {
452           if (! touch)
453             ranlib_only (argv[arg_index]);
454           else
455             ranlib_touch (argv[arg_index]);
456           ++arg_index;
457         }
458       xexit (0);
459     }
460
461   if (argc == 2 && strcmp (argv[1], "-M") == 0)
462     {
463       mri_emul ();
464       xexit (0);
465     }
466
467   if (argc < 2)
468     usage (0);
469
470   arg_ptr = argv[1];
471
472   if (*arg_ptr == '-')
473     ++arg_ptr;                  /* compatibility */
474
475   while ((c = *arg_ptr++) != '\0')
476     {
477       switch (c)
478         {
479         case 'd':
480         case 'm':
481         case 'p':
482         case 'q':
483         case 'r':
484         case 't':
485         case 'x':
486           if (operation != none)
487             fatal (_("two different operation options specified"));
488           switch (c)
489             {
490             case 'd':
491               operation = delete;
492               operation_alters_arch = true;
493               break;
494             case 'm':
495               operation = move;
496               operation_alters_arch = true;
497               break;
498             case 'p':
499               operation = print_files;
500               break;
501             case 'q':
502               operation = quick_append;
503               operation_alters_arch = true;
504               break;
505             case 'r':
506               operation = replace;
507               operation_alters_arch = true;
508               break;
509             case 't':
510               operation = print_table;
511               break;
512             case 'x':
513               operation = extract;
514               break;
515             }
516         case 'l':
517           break;
518         case 'c':
519           silent_create = 1;
520           break;
521         case 'o':
522           preserve_dates = 1;
523           break;
524         case 'V':
525           show_version = true;
526           break;
527         case 's':
528           write_armap = 1;
529           break;
530         case 'S':
531           write_armap = -1;
532           break;
533         case 'u':
534           newer_only = 1;
535           break;
536         case 'v':
537           verbose = 1;
538           break;
539         case 'a':
540           postype = pos_after;
541           break;
542         case 'b':
543           postype = pos_before;
544           break;
545         case 'i':
546           postype = pos_before;
547           break;
548         case 'M':
549           mri_mode = 1;
550           break;
551         case 'N':
552           counted_name_mode = true;
553           break;
554         case 'f':
555           ar_truncate = true;
556           break;
557         case 'P':
558           full_pathname = true;
559           break;
560         default:
561           /* xgettext:c-format */
562           non_fatal (_("illegal option -- %c"), c);
563           usage (0);
564         }
565     }
566
567   if (show_version)
568     print_version ("ar");
569
570   if (argc < 3)
571     usage (0);
572
573   if (mri_mode)
574     {
575       mri_emul ();
576     }
577   else
578     {
579       bfd *arch;
580
581       /* We can't write an armap when using ar q, so just do ar r
582          instead.  */
583       if (operation == quick_append && write_armap)
584         operation = replace;
585
586       if ((operation == none || operation == print_table)
587           && write_armap == 1)
588         {
589           ranlib_only (argv[2]);
590           xexit (0);
591         }
592
593       if (operation == none)
594         fatal (_("no operation specified"));
595
596       if (newer_only && operation != replace)
597         fatal (_("`u' is only meaningful with the `r' option."));
598
599       arg_index = 2;
600
601       if (postype != pos_default)
602         posname = argv[arg_index++];
603
604       if (counted_name_mode) 
605         {
606           if (operation != extract && operation != delete) 
607              fatal (_("`N' is only meaningful with the `x' and `d' options."));
608           counted_name_counter = atoi (argv[arg_index++]);
609           if (counted_name_counter <= 0)
610             fatal (_("Value for `N' must be positive."));
611         }
612
613       inarch_filename = argv[arg_index++];
614
615       files = arg_index < argc ? argv + arg_index : NULL;
616       file_count = argc - arg_index;
617
618 #if 0
619       /* We don't use do_quick_append any more.  Too many systems
620          expect ar to always rebuild the symbol table even when q is
621          used.  */
622
623       /* We can't do a quick append if we need to construct an
624          extended name table, because do_quick_append won't be able to
625          rebuild the name table.  Unfortunately, at this point we
626          don't actually know the maximum name length permitted by this
627          object file format.  So, we guess.  FIXME.  */
628       if (operation == quick_append && ! ar_truncate)
629         {
630           char **chk;
631
632           for (chk = files; chk != NULL && *chk != '\0'; chk++)
633             {
634               if (strlen (normalize (*chk, (bfd *) NULL)) > 14)
635                 {
636                   operation = replace;
637                   break;
638                 }
639             }
640         }
641
642       if (operation == quick_append)
643         {
644           /* Note that quick appending to a non-existent archive creates it,
645              even if there are no files to append. */
646           do_quick_append (inarch_filename, files);
647           xexit (0);
648         }
649 #endif
650
651       arch = open_inarch (inarch_filename,
652                           files == NULL ? (char *) NULL : files[0]);
653
654       switch (operation)
655         {
656         case print_table:
657           map_over_members (arch, print_descr, files, file_count);
658           break;
659
660         case print_files:
661           map_over_members (arch, print_contents, files, file_count);
662           break;
663
664         case extract:
665           map_over_members (arch, extract_file, files, file_count);
666           break;
667
668         case delete:
669           if (files != NULL)
670             delete_members (arch, files);
671           else
672             output_filename = NULL;
673           break;
674
675         case move:
676           if (files != NULL)
677             move_members (arch, files);
678           else
679             output_filename = NULL;
680           break;
681
682         case replace:
683         case quick_append:
684           if (files != NULL || write_armap > 0)
685             replace_members (arch, files, operation == quick_append);
686           else
687             output_filename = NULL;
688           break;
689
690           /* Shouldn't happen! */
691         default:
692           /* xgettext:c-format */
693           fatal (_("internal error -- this option not implemented"));
694         }
695     }
696
697   END_PROGRESS (program_name);
698
699   xexit (0);
700   return 0;
701 }
702
703 bfd *
704 open_inarch (archive_filename, file)
705      const char *archive_filename;
706      const char *file;
707 {
708   const char *target;
709   bfd **last_one;
710   bfd *next_one;
711   struct stat sbuf;
712   bfd *arch;
713   char **matching;
714
715   bfd_set_error (bfd_error_no_error);
716
717   target = NULL;
718
719   if (stat (archive_filename, &sbuf) != 0)
720     {
721 #if !defined(__GO32__) || defined(__DJGPP__)
722
723       /* FIXME: I don't understand why this fragment was ifndef'ed
724          away for __GO32__; perhaps it was in the days of DJGPP v1.x.
725          stat() works just fine in v2.x, so I think this should be
726          removed.  For now, I enable it for DJGPP v2. -- EZ.  */
727
728 /* KLUDGE ALERT! Temporary fix until I figger why
729    stat() is wrong ... think it's buried in GO32's IDT - Jax */
730       if (errno != ENOENT)
731         bfd_fatal (archive_filename);
732 #endif
733
734       if (!operation_alters_arch)
735         {
736           fprintf (stderr, "%s: ", program_name);
737           perror (archive_filename);
738           maybequit ();
739           return NULL;
740         }
741
742       /* Try to figure out the target to use for the archive from the
743          first object on the list.  */
744       if (file != NULL)
745         {
746           bfd *obj;
747
748           obj = bfd_openr (file, NULL);
749           if (obj != NULL)
750             {
751               if (bfd_check_format (obj, bfd_object))
752                 target = bfd_get_target (obj);
753               (void) bfd_close (obj);
754             }
755         }
756
757       /* Create an empty archive.  */
758       arch = bfd_openw (archive_filename, target);
759       if (arch == NULL
760           || ! bfd_set_format (arch, bfd_archive)
761           || ! bfd_close (arch))
762         bfd_fatal (archive_filename);
763
764       /* If we die creating a new archive, don't leave it around.  */
765       output_filename = archive_filename;
766     }
767
768   arch = bfd_openr (archive_filename, target);
769   if (arch == NULL)
770     {
771     bloser:
772       bfd_fatal (archive_filename);
773     }
774
775   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
776     {
777       bfd_nonfatal (archive_filename);
778       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
779         {
780           list_matching_formats (matching);
781           free (matching);
782         }
783       xexit (1);
784     }
785
786   last_one = &(arch->next);
787   /* Read all the contents right away, regardless.  */
788   for (next_one = bfd_openr_next_archived_file (arch, NULL);
789        next_one;
790        next_one = bfd_openr_next_archived_file (arch, next_one))
791     {
792       PROGRESS (1);
793       *last_one = next_one;
794       last_one = &next_one->next;
795     }
796   *last_one = (bfd *) NULL;
797   if (bfd_get_error () != bfd_error_no_more_archived_files)
798     goto bloser;
799   return arch;
800 }
801
802 static void
803 print_contents (abfd)
804      bfd *abfd;
805 {
806   int ncopied = 0;
807   char *cbuf = xmalloc (BUFSIZE);
808   struct stat buf;
809   long size;
810   if (bfd_stat_arch_elt (abfd, &buf) != 0)
811     /* xgettext:c-format */
812     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
813
814   if (verbose)
815     /* xgettext:c-format */
816     printf (_("\n<member %s>\n\n"), bfd_get_filename (abfd));
817
818   bfd_seek (abfd, 0, SEEK_SET);
819
820   size = buf.st_size;
821   while (ncopied < size)
822     {
823
824       int nread;
825       int tocopy = size - ncopied;
826       if (tocopy > BUFSIZE)
827         tocopy = BUFSIZE;
828
829       nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
830                                                            abstraction!  */
831       if (nread != tocopy)
832         /* xgettext:c-format */
833         fatal (_("%s is not a valid archive"),
834                bfd_get_filename (bfd_my_archive (abfd)));
835       fwrite (cbuf, 1, nread, stdout);
836       ncopied += tocopy;
837     }
838   free (cbuf);
839 }
840
841 /* Extract a member of the archive into its own file.
842
843    We defer opening the new file until after we have read a BUFSIZ chunk of the
844    old one, since we know we have just read the archive header for the old
845    one.  Since most members are shorter than BUFSIZ, this means we will read
846    the old header, read the old data, write a new inode for the new file, and
847    write the new data, and be done. This 'optimization' is what comes from
848    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
849    Gilmore  */
850
851 void
852 extract_file (abfd)
853      bfd *abfd;
854 {
855   FILE *ostream;
856   char *cbuf = xmalloc (BUFSIZE);
857   int nread, tocopy;
858   long ncopied = 0;
859   long size;
860   struct stat buf;
861   
862   if (bfd_stat_arch_elt (abfd, &buf) != 0)
863     /* xgettext:c-format */
864     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
865   size = buf.st_size;
866
867   if (size < 0)
868     /* xgettext:c-format */
869     fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
870   
871   if (verbose)
872     printf ("x - %s\n", bfd_get_filename (abfd));
873
874   bfd_seek (abfd, 0, SEEK_SET);
875
876   ostream = NULL;
877   if (size == 0)
878     {
879       /* Seems like an abstraction violation, eh?  Well it's OK! */
880       output_filename = bfd_get_filename (abfd);
881
882       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
883       if (ostream == NULL)
884         {
885           perror (bfd_get_filename (abfd));
886           xexit (1);
887         }
888
889       output_file = ostream;
890     }
891   else
892     while (ncopied < size)
893       {
894         tocopy = size - ncopied;
895         if (tocopy > BUFSIZE)
896           tocopy = BUFSIZE;
897
898         nread = bfd_read (cbuf, 1, tocopy, abfd);
899         if (nread != tocopy)
900           /* xgettext:c-format */
901           fatal (_("%s is not a valid archive"),
902                  bfd_get_filename (bfd_my_archive (abfd)));
903
904         /* See comment above; this saves disk arm motion */
905         if (ostream == NULL)
906           {
907             /* Seems like an abstraction violation, eh?  Well it's OK! */
908             output_filename = bfd_get_filename (abfd);
909
910             ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
911             if (ostream == NULL)
912               {
913                 perror (bfd_get_filename (abfd));
914                 xexit (1);
915               }
916
917             output_file = ostream;
918           }
919         fwrite (cbuf, 1, nread, ostream);
920         ncopied += tocopy;
921       }
922
923   if (ostream != NULL)
924     fclose (ostream);
925
926   output_file = NULL;
927   output_filename = NULL;
928
929   chmod (bfd_get_filename (abfd), buf.st_mode);
930
931   if (preserve_dates)
932     set_times (bfd_get_filename (abfd), &buf);
933
934   free (cbuf);
935 }
936
937 #if 0
938
939 /* We don't use this anymore.  Too many systems expect ar to rebuild
940    the symbol table even when q is used.  */
941
942 /* Just do it quickly; don't worry about dups, armap, or anything like that */
943
944 static void
945 do_quick_append (archive_filename, files_to_append)
946      const char *archive_filename;
947      char **files_to_append;
948 {
949   FILE *ofile, *ifile;
950   char *buf = xmalloc (BUFSIZE);
951   long tocopy, thistime;
952   bfd *temp;
953   struct stat sbuf;
954   boolean newfile = false;
955   bfd_set_error (bfd_error_no_error);
956
957   if (stat (archive_filename, &sbuf) != 0)
958     {
959
960 #if !defined(__GO32__) || defined(__DJGPP__)
961
962       /* FIXME: I don't understand why this fragment was ifndef'ed
963          away for __GO32__; perhaps it was in the days of DJGPP v1.x.
964          stat() works just fine in v2.x, so I think this should be
965          removed.  For now, I enable it for DJGPP v2.
966
967          (And yes, I know this is all unused, but somebody, someday,
968          might wish to resurrect this again... -- EZ.  */
969
970 /* KLUDGE ALERT! Temporary fix until I figger why
971    stat() is wrong ... think it's buried in GO32's IDT - Jax  */
972
973       if (errno != ENOENT)
974         bfd_fatal (archive_filename);
975 #endif
976
977       newfile = true;
978     }
979
980   ofile = fopen (archive_filename, FOPEN_AUB);
981   if (ofile == NULL)
982     {
983       perror (program_name);
984       xexit (1);
985     }
986
987   temp = bfd_openr (archive_filename, NULL);
988   if (temp == NULL)
989     {
990       bfd_fatal (archive_filename);
991     }
992   if (newfile == false)
993     {
994       if (bfd_check_format (temp, bfd_archive) != true)
995         /* xgettext:c-format */
996         fatal (_("%s is not an archive"), archive_filename);
997     }
998   else
999     {
1000       fwrite (ARMAG, 1, SARMAG, ofile);
1001       if (!silent_create)
1002         /* xgettext:c-format */
1003         non_fatal (_("creating %s"), archive_filename);
1004     }
1005
1006   if (ar_truncate)
1007     temp->flags |= BFD_TRADITIONAL_FORMAT;
1008
1009   /* assume it's an achive, go straight to the end, sans $200 */
1010   fseek (ofile, 0, 2);
1011
1012   for (; files_to_append && *files_to_append; ++files_to_append)
1013     {
1014       struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
1015       if (hdr == NULL)
1016         {
1017           bfd_fatal (*files_to_append);
1018         }
1019
1020       BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
1021
1022       ifile = fopen (*files_to_append, FOPEN_RB);
1023       if (ifile == NULL)
1024         {
1025           bfd_nonfatal (*files_to_append);
1026         }
1027
1028       if (stat (*files_to_append, &sbuf) != 0)
1029         {
1030           bfd_nonfatal (*files_to_append);
1031         }
1032
1033       tocopy = sbuf.st_size;
1034
1035       /* XXX should do error-checking! */
1036       fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
1037
1038       while (tocopy > 0)
1039         {
1040           thistime = tocopy;
1041           if (thistime > BUFSIZE)
1042             thistime = BUFSIZE;
1043           fread (buf, 1, thistime, ifile);
1044           fwrite (buf, 1, thistime, ofile);
1045           tocopy -= thistime;
1046         }
1047       fclose (ifile);
1048       if ((sbuf.st_size % 2) == 1)
1049         putc ('\012', ofile);
1050     }
1051   fclose (ofile);
1052   bfd_close (temp);
1053   free (buf);
1054 }
1055
1056 #endif /* 0 */
1057
1058 static void
1059 write_archive (iarch)
1060      bfd *iarch;
1061 {
1062   bfd *obfd;
1063   char *old_name, *new_name;
1064   bfd *contents_head = iarch->next;
1065
1066   old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
1067   strcpy (old_name, bfd_get_filename (iarch));
1068   new_name = make_tempname (old_name);
1069
1070   output_filename = new_name;
1071
1072   obfd = bfd_openw (new_name, bfd_get_target (iarch));
1073
1074   if (obfd == NULL)
1075     bfd_fatal (old_name);
1076
1077   output_bfd = obfd;
1078
1079   bfd_set_format (obfd, bfd_archive);
1080
1081   /* Request writing the archive symbol table unless we've
1082      been explicitly requested not to.  */
1083   obfd->has_armap = write_armap >= 0;
1084
1085   if (ar_truncate)
1086     {
1087       /* This should really use bfd_set_file_flags, but that rejects
1088          archives.  */
1089       obfd->flags |= BFD_TRADITIONAL_FORMAT;
1090     }
1091
1092   if (bfd_set_archive_head (obfd, contents_head) != true)
1093     bfd_fatal (old_name);
1094
1095   if (!bfd_close (obfd))
1096     bfd_fatal (old_name);
1097
1098   output_bfd = NULL;
1099   output_filename = NULL;
1100
1101   /* We don't care if this fails; we might be creating the archive.  */
1102   bfd_close (iarch);
1103
1104   if (smart_rename (new_name, old_name, 0) != 0)
1105     xexit (1);
1106 }
1107
1108 /* Return a pointer to the pointer to the entry which should be rplacd'd
1109    into when altering.  DEFAULT_POS should be how to interpret pos_default,
1110    and should be a pos value.  */
1111
1112 static bfd **
1113 get_pos_bfd (contents, default_pos, default_posname)
1114      bfd **contents;
1115      enum pos default_pos;
1116      const char *default_posname;
1117 {
1118   bfd **after_bfd = contents;
1119   enum pos realpos;
1120   const char *realposname;
1121
1122   if (postype == pos_default)
1123     {
1124       realpos = default_pos;
1125       realposname = default_posname;
1126     }
1127   else
1128     {
1129       realpos = postype;
1130       realposname = posname;
1131     }
1132
1133   if (realpos == pos_end)
1134     {
1135       while (*after_bfd)
1136         after_bfd = &((*after_bfd)->next);
1137     }
1138   else
1139     {
1140       for (; *after_bfd; after_bfd = &(*after_bfd)->next)
1141         if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
1142           {
1143             if (realpos == pos_after)
1144               after_bfd = &(*after_bfd)->next;
1145             break;
1146           }
1147     }
1148   return after_bfd;
1149 }
1150
1151 static void
1152 delete_members (arch, files_to_delete)
1153      bfd *arch;
1154      char **files_to_delete;
1155 {
1156   bfd **current_ptr_ptr;
1157   boolean found;
1158   boolean something_changed = false;
1159   int match_count;
1160
1161   for (; *files_to_delete != NULL; ++files_to_delete)
1162     {
1163       /* In a.out systems, the armap is optional.  It's also called
1164          __.SYMDEF.  So if the user asked to delete it, we should remember
1165          that fact. This isn't quite right for COFF systems (where
1166          __.SYMDEF might be regular member), but it's very unlikely
1167          to be a problem.  FIXME */
1168
1169       if (!strcmp (*files_to_delete, "__.SYMDEF"))
1170         {
1171           arch->has_armap = false;
1172           write_armap = -1;
1173           continue;
1174         }
1175
1176       found = false;
1177       match_count = 0;
1178       current_ptr_ptr = &(arch->next);
1179       while (*current_ptr_ptr)
1180         {
1181           if (FILENAME_CMP (normalize (*files_to_delete, arch),
1182                       (*current_ptr_ptr)->filename) == 0)
1183             {
1184               ++match_count;
1185               if (counted_name_mode
1186                   && match_count != counted_name_counter) 
1187                 {
1188                   /* Counting, and didn't match on count; go on to the
1189                      next one.  */
1190                 }
1191               else
1192                 {
1193                   found = true;
1194                   something_changed = true;
1195                   if (verbose)
1196                     printf ("d - %s\n",
1197                             *files_to_delete);
1198                   *current_ptr_ptr = ((*current_ptr_ptr)->next);
1199                   goto next_file;
1200                 }
1201             }
1202
1203           current_ptr_ptr = &((*current_ptr_ptr)->next);
1204         }
1205
1206       if (verbose && found == false)
1207         {
1208           /* xgettext:c-format */
1209           printf (_("No member named `%s'\n"), *files_to_delete);
1210         }
1211     next_file:
1212       ;
1213     }
1214
1215   if (something_changed == true)
1216     write_archive (arch);
1217   else
1218     output_filename = NULL;
1219 }
1220
1221
1222 /* Reposition existing members within an archive */
1223
1224 static void
1225 move_members (arch, files_to_move)
1226      bfd *arch;
1227      char **files_to_move;
1228 {
1229   bfd **after_bfd;              /* New entries go after this one */
1230   bfd **current_ptr_ptr;        /* cdr pointer into contents */
1231
1232   for (; *files_to_move; ++files_to_move)
1233     {
1234       current_ptr_ptr = &(arch->next);
1235       while (*current_ptr_ptr)
1236         {
1237           bfd *current_ptr = *current_ptr_ptr;
1238           if (FILENAME_CMP (normalize (*files_to_move, arch),
1239                             current_ptr->filename) == 0)
1240             {
1241               /* Move this file to the end of the list - first cut from
1242                  where it is.  */
1243               bfd *link;
1244               *current_ptr_ptr = current_ptr->next;
1245
1246               /* Now glue to end */
1247               after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1248               link = *after_bfd;
1249               *after_bfd = current_ptr;
1250               current_ptr->next = link;
1251
1252               if (verbose)
1253                 printf ("m - %s\n", *files_to_move);
1254
1255               goto next_file;
1256             }
1257
1258           current_ptr_ptr = &((*current_ptr_ptr)->next);
1259         }
1260       /* xgettext:c-format */
1261       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1262
1263     next_file:;
1264     }
1265
1266   write_archive (arch);
1267 }
1268
1269 /* Ought to default to replacing in place, but this is existing practice!  */
1270
1271 static void
1272 replace_members (arch, files_to_move, quick)
1273      bfd *arch;
1274      char **files_to_move;
1275      boolean quick;
1276 {
1277   boolean changed = false;
1278   bfd **after_bfd;              /* New entries go after this one */
1279   bfd *current;
1280   bfd **current_ptr;
1281   bfd *temp;
1282
1283   while (files_to_move && *files_to_move)
1284     {
1285       if (! quick)
1286         {
1287           current_ptr = &arch->next;
1288           while (*current_ptr)
1289             {
1290               current = *current_ptr;
1291
1292               /* For compatibility with existing ar programs, we
1293                  permit the same file to be added multiple times.  */
1294               if (FILENAME_CMP (normalize (*files_to_move, arch),
1295                                 normalize (current->filename, arch)) == 0
1296                   && current->arelt_data != NULL)
1297                 {
1298                   if (newer_only)
1299                     {
1300                       struct stat fsbuf, asbuf;
1301
1302                       if (stat (*files_to_move, &fsbuf) != 0)
1303                         {
1304                           if (errno != ENOENT)
1305                             bfd_fatal (*files_to_move);
1306                           goto next_file;
1307                         }
1308                       if (bfd_stat_arch_elt (current, &asbuf) != 0)
1309                         /* xgettext:c-format */
1310                         fatal (_("internal stat error on %s"), current->filename);
1311
1312                       if (fsbuf.st_mtime <= asbuf.st_mtime)
1313                         goto next_file;
1314                     }
1315
1316                   after_bfd = get_pos_bfd (&arch->next, pos_after,
1317                                            current->filename);
1318                   temp = *after_bfd;
1319
1320                   *after_bfd = bfd_openr (*files_to_move, NULL);
1321                   if (*after_bfd == (bfd *) NULL)
1322                     {
1323                       bfd_fatal (*files_to_move);
1324                     }
1325                   (*after_bfd)->next = temp;
1326
1327                   /* snip out this entry from the chain */
1328                   *current_ptr = (*current_ptr)->next;
1329
1330                   if (verbose)
1331                     {
1332                       printf ("r - %s\n", *files_to_move);
1333                     }
1334
1335                   changed = true;
1336
1337                   goto next_file;
1338                 }
1339               current_ptr = &(current->next);
1340             }
1341         }
1342
1343       /* Add to the end of the archive.  */
1344
1345       after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1346       temp = *after_bfd;
1347       *after_bfd = bfd_openr (*files_to_move, NULL);
1348       if (*after_bfd == (bfd *) NULL)
1349         {
1350           bfd_fatal (*files_to_move);
1351         }
1352       if (verbose)
1353         {
1354           printf ("a - %s\n", *files_to_move);
1355         }
1356
1357       (*after_bfd)->next = temp;
1358
1359       changed = true;
1360
1361     next_file:;
1362
1363       files_to_move++;
1364     }
1365
1366   if (changed)
1367     write_archive (arch);
1368   else
1369     output_filename = NULL;
1370 }
1371
1372 static void
1373 ranlib_only (archname)
1374      const char *archname;
1375 {
1376   bfd *arch;
1377
1378   write_armap = 1;
1379   arch = open_inarch (archname, (char *) NULL);
1380   if (arch == NULL)
1381     xexit (1);
1382   write_archive (arch);
1383 }
1384
1385 /* Update the timestamp of the symbol map of an archive.  */
1386
1387 static void
1388 ranlib_touch (archname)
1389      const char *archname;
1390 {
1391 #ifdef __GO32__
1392   /* I don't think updating works on go32.  */
1393   ranlib_only (archname);
1394 #else
1395   int f;
1396   bfd *arch;
1397   char **matching;
1398
1399   f = open (archname, O_RDWR | O_BINARY, 0);
1400   if (f < 0)
1401     {
1402       bfd_set_error (bfd_error_system_call);
1403       bfd_fatal (archname);
1404     }
1405
1406   arch = bfd_fdopenr (archname, (const char *) NULL, f);
1407   if (arch == NULL)
1408     bfd_fatal (archname);
1409   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1410     {
1411       bfd_nonfatal (archname);
1412       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1413         {
1414           list_matching_formats (matching);
1415           free (matching);
1416         }
1417       xexit (1);
1418     }
1419
1420   if (! bfd_has_map (arch))
1421     /* xgettext:c-format */
1422     fatal (_("%s: no archive map to update"), archname);
1423
1424   bfd_update_armap_timestamp (arch);
1425
1426   if (! bfd_close (arch))
1427     bfd_fatal (archname);
1428 #endif
1429 }
1430
1431 /* Things which are interesting to map over all or some of the files: */
1432
1433 static void
1434 print_descr (abfd)
1435      bfd *abfd;
1436 {
1437   print_arelt_descr (stdout, abfd, verbose);
1438 }