Eli Zaretskii's DOSish file name patches.
[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 (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 (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     printf ("\n<%s>\n\n", bfd_get_filename (abfd));
816
817   bfd_seek (abfd, 0, SEEK_SET);
818
819   size = buf.st_size;
820   while (ncopied < size)
821     {
822
823       int nread;
824       int tocopy = size - ncopied;
825       if (tocopy > BUFSIZE)
826         tocopy = BUFSIZE;
827
828       nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
829                                                            abstraction!  */
830       if (nread != tocopy)
831         /* xgettext:c-format */
832         fatal (_("%s is not a valid archive"),
833                bfd_get_filename (bfd_my_archive (abfd)));
834       fwrite (cbuf, 1, nread, stdout);
835       ncopied += tocopy;
836     }
837   free (cbuf);
838 }
839
840 /* Extract a member of the archive into its own file.
841
842    We defer opening the new file until after we have read a BUFSIZ chunk of the
843    old one, since we know we have just read the archive header for the old
844    one.  Since most members are shorter than BUFSIZ, this means we will read
845    the old header, read the old data, write a new inode for the new file, and
846    write the new data, and be done. This 'optimization' is what comes from
847    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
848    Gilmore  */
849
850 void
851 extract_file (abfd)
852      bfd *abfd;
853 {
854   FILE *ostream;
855   char *cbuf = xmalloc (BUFSIZE);
856   int nread, tocopy;
857   long ncopied = 0;
858   long size;
859   struct stat buf;
860   
861   if (bfd_stat_arch_elt (abfd, &buf) != 0)
862     /* xgettext:c-format */
863     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
864   size = buf.st_size;
865
866   if (size < 0)
867     /* xgettext:c-format */
868     fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
869   
870   if (verbose)
871     printf ("x - %s\n", bfd_get_filename (abfd));
872
873   bfd_seek (abfd, 0, SEEK_SET);
874
875   ostream = NULL;
876   if (size == 0)
877     {
878       /* Seems like an abstraction violation, eh?  Well it's OK! */
879       output_filename = bfd_get_filename (abfd);
880
881       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
882       if (ostream == NULL)
883         {
884           perror (bfd_get_filename (abfd));
885           xexit (1);
886         }
887
888       output_file = ostream;
889     }
890   else
891     while (ncopied < size)
892       {
893         tocopy = size - ncopied;
894         if (tocopy > BUFSIZE)
895           tocopy = BUFSIZE;
896
897         nread = bfd_read (cbuf, 1, tocopy, abfd);
898         if (nread != tocopy)
899           /* xgettext:c-format */
900           fatal (_("%s is not a valid archive"),
901                  bfd_get_filename (bfd_my_archive (abfd)));
902
903         /* See comment above; this saves disk arm motion */
904         if (ostream == NULL)
905           {
906             /* Seems like an abstraction violation, eh?  Well it's OK! */
907             output_filename = bfd_get_filename (abfd);
908
909             ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
910             if (ostream == NULL)
911               {
912                 perror (bfd_get_filename (abfd));
913                 xexit (1);
914               }
915
916             output_file = ostream;
917           }
918         fwrite (cbuf, 1, nread, ostream);
919         ncopied += tocopy;
920       }
921
922   if (ostream != NULL)
923     fclose (ostream);
924
925   output_file = NULL;
926   output_filename = NULL;
927
928   chmod (bfd_get_filename (abfd), buf.st_mode);
929
930   if (preserve_dates)
931     set_times (bfd_get_filename (abfd), &buf);
932
933   free (cbuf);
934 }
935
936 #if 0
937
938 /* We don't use this anymore.  Too many systems expect ar to rebuild
939    the symbol table even when q is used.  */
940
941 /* Just do it quickly; don't worry about dups, armap, or anything like that */
942
943 static void
944 do_quick_append (archive_filename, files_to_append)
945      const char *archive_filename;
946      char **files_to_append;
947 {
948   FILE *ofile, *ifile;
949   char *buf = xmalloc (BUFSIZE);
950   long tocopy, thistime;
951   bfd *temp;
952   struct stat sbuf;
953   boolean newfile = false;
954   bfd_set_error (bfd_error_no_error);
955
956   if (stat (archive_filename, &sbuf) != 0)
957     {
958
959 #if !defined(__GO32__) || defined(__DJGPP__)
960
961       /* FIXME: I don't understand why this fragment was ifndef'ed
962          away for __GO32__; perhaps it was in the days of DJGPP v1.x.
963          stat() works just fine in v2.x, so I think this should be
964          removed.  For now, I enable it for DJGPP v2.
965
966          (And yes, I know this is all unused, but somebody, someday,
967          might wish to resurrect this again... -- EZ.  */
968
969 /* KLUDGE ALERT! Temporary fix until I figger why
970    stat() is wrong ... think it's buried in GO32's IDT - Jax  */
971
972       if (errno != ENOENT)
973         bfd_fatal (archive_filename);
974 #endif
975
976       newfile = true;
977     }
978
979   ofile = fopen (archive_filename, FOPEN_AUB);
980   if (ofile == NULL)
981     {
982       perror (program_name);
983       xexit (1);
984     }
985
986   temp = bfd_openr (archive_filename, NULL);
987   if (temp == NULL)
988     {
989       bfd_fatal (archive_filename);
990     }
991   if (newfile == false)
992     {
993       if (bfd_check_format (temp, bfd_archive) != true)
994         /* xgettext:c-format */
995         fatal (_("%s is not an archive"), archive_filename);
996     }
997   else
998     {
999       fwrite (ARMAG, 1, SARMAG, ofile);
1000       if (!silent_create)
1001         /* xgettext:c-format */
1002         non_fatal (_("creating %s"), archive_filename);
1003     }
1004
1005   if (ar_truncate)
1006     temp->flags |= BFD_TRADITIONAL_FORMAT;
1007
1008   /* assume it's an achive, go straight to the end, sans $200 */
1009   fseek (ofile, 0, 2);
1010
1011   for (; files_to_append && *files_to_append; ++files_to_append)
1012     {
1013       struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
1014       if (hdr == NULL)
1015         {
1016           bfd_fatal (*files_to_append);
1017         }
1018
1019       BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
1020
1021       ifile = fopen (*files_to_append, FOPEN_RB);
1022       if (ifile == NULL)
1023         {
1024           bfd_nonfatal (*files_to_append);
1025         }
1026
1027       if (stat (*files_to_append, &sbuf) != 0)
1028         {
1029           bfd_nonfatal (*files_to_append);
1030         }
1031
1032       tocopy = sbuf.st_size;
1033
1034       /* XXX should do error-checking! */
1035       fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
1036
1037       while (tocopy > 0)
1038         {
1039           thistime = tocopy;
1040           if (thistime > BUFSIZE)
1041             thistime = BUFSIZE;
1042           fread (buf, 1, thistime, ifile);
1043           fwrite (buf, 1, thistime, ofile);
1044           tocopy -= thistime;
1045         }
1046       fclose (ifile);
1047       if ((sbuf.st_size % 2) == 1)
1048         putc ('\012', ofile);
1049     }
1050   fclose (ofile);
1051   bfd_close (temp);
1052   free (buf);
1053 }
1054
1055 #endif /* 0 */
1056
1057 static void
1058 write_archive (iarch)
1059      bfd *iarch;
1060 {
1061   bfd *obfd;
1062   char *old_name, *new_name;
1063   bfd *contents_head = iarch->next;
1064
1065   old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
1066   strcpy (old_name, bfd_get_filename (iarch));
1067   new_name = make_tempname (old_name);
1068
1069   output_filename = new_name;
1070
1071   obfd = bfd_openw (new_name, bfd_get_target (iarch));
1072
1073   if (obfd == NULL)
1074     bfd_fatal (old_name);
1075
1076   output_bfd = obfd;
1077
1078   bfd_set_format (obfd, bfd_archive);
1079
1080   /* Request writing the archive symbol table unless we've
1081      been explicitly requested not to.  */
1082   obfd->has_armap = write_armap >= 0;
1083
1084   if (ar_truncate)
1085     {
1086       /* This should really use bfd_set_file_flags, but that rejects
1087          archives.  */
1088       obfd->flags |= BFD_TRADITIONAL_FORMAT;
1089     }
1090
1091   if (bfd_set_archive_head (obfd, contents_head) != true)
1092     bfd_fatal (old_name);
1093
1094   if (!bfd_close (obfd))
1095     bfd_fatal (old_name);
1096
1097   output_bfd = NULL;
1098   output_filename = NULL;
1099
1100   /* We don't care if this fails; we might be creating the archive.  */
1101   bfd_close (iarch);
1102
1103   if (smart_rename (new_name, old_name, 0) != 0)
1104     xexit (1);
1105 }
1106
1107 /* Return a pointer to the pointer to the entry which should be rplacd'd
1108    into when altering.  DEFAULT_POS should be how to interpret pos_default,
1109    and should be a pos value.  */
1110
1111 static bfd **
1112 get_pos_bfd (contents, default_pos, default_posname)
1113      bfd **contents;
1114      enum pos default_pos;
1115      const char *default_posname;
1116 {
1117   bfd **after_bfd = contents;
1118   enum pos realpos;
1119   const char *realposname;
1120
1121   if (postype == pos_default)
1122     {
1123       realpos = default_pos;
1124       realposname = default_posname;
1125     }
1126   else
1127     {
1128       realpos = postype;
1129       realposname = posname;
1130     }
1131
1132   if (realpos == pos_end)
1133     {
1134       while (*after_bfd)
1135         after_bfd = &((*after_bfd)->next);
1136     }
1137   else
1138     {
1139       for (; *after_bfd; after_bfd = &(*after_bfd)->next)
1140         if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
1141           {
1142             if (realpos == pos_after)
1143               after_bfd = &(*after_bfd)->next;
1144             break;
1145           }
1146     }
1147   return after_bfd;
1148 }
1149
1150 static void
1151 delete_members (arch, files_to_delete)
1152      bfd *arch;
1153      char **files_to_delete;
1154 {
1155   bfd **current_ptr_ptr;
1156   boolean found;
1157   boolean something_changed = false;
1158   int match_count;
1159
1160   for (; *files_to_delete != NULL; ++files_to_delete)
1161     {
1162       /* In a.out systems, the armap is optional.  It's also called
1163          __.SYMDEF.  So if the user asked to delete it, we should remember
1164          that fact. This isn't quite right for COFF systems (where
1165          __.SYMDEF might be regular member), but it's very unlikely
1166          to be a problem.  FIXME */
1167
1168       if (!strcmp (*files_to_delete, "__.SYMDEF"))
1169         {
1170           arch->has_armap = false;
1171           write_armap = -1;
1172           continue;
1173         }
1174
1175       found = false;
1176       match_count = 0;
1177       current_ptr_ptr = &(arch->next);
1178       while (*current_ptr_ptr)
1179         {
1180           if (FILENAME_CMP (normalize (*files_to_delete, arch),
1181                       (*current_ptr_ptr)->filename) == 0)
1182             {
1183               ++match_count;
1184               if (counted_name_mode
1185                   && match_count != counted_name_counter) 
1186                 {
1187                   /* Counting, and didn't match on count; go on to the
1188                      next one.  */
1189                 }
1190               else
1191                 {
1192                   found = true;
1193                   something_changed = true;
1194                   if (verbose)
1195                     printf ("d - %s\n",
1196                             *files_to_delete);
1197                   *current_ptr_ptr = ((*current_ptr_ptr)->next);
1198                   goto next_file;
1199                 }
1200             }
1201
1202           current_ptr_ptr = &((*current_ptr_ptr)->next);
1203         }
1204
1205       if (verbose && found == false)
1206         {
1207           /* xgettext:c-format */
1208           printf (_("No member named `%s'\n"), *files_to_delete);
1209         }
1210     next_file:
1211       ;
1212     }
1213
1214   if (something_changed == true)
1215     write_archive (arch);
1216   else
1217     output_filename = NULL;
1218 }
1219
1220
1221 /* Reposition existing members within an archive */
1222
1223 static void
1224 move_members (arch, files_to_move)
1225      bfd *arch;
1226      char **files_to_move;
1227 {
1228   bfd **after_bfd;              /* New entries go after this one */
1229   bfd **current_ptr_ptr;        /* cdr pointer into contents */
1230
1231   for (; *files_to_move; ++files_to_move)
1232     {
1233       current_ptr_ptr = &(arch->next);
1234       while (*current_ptr_ptr)
1235         {
1236           bfd *current_ptr = *current_ptr_ptr;
1237           if (FILENAME_CMP (normalize (*files_to_move, arch),
1238                             current_ptr->filename) == 0)
1239             {
1240               /* Move this file to the end of the list - first cut from
1241                  where it is.  */
1242               bfd *link;
1243               *current_ptr_ptr = current_ptr->next;
1244
1245               /* Now glue to end */
1246               after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1247               link = *after_bfd;
1248               *after_bfd = current_ptr;
1249               current_ptr->next = link;
1250
1251               if (verbose)
1252                 printf ("m - %s\n", *files_to_move);
1253
1254               goto next_file;
1255             }
1256
1257           current_ptr_ptr = &((*current_ptr_ptr)->next);
1258         }
1259       /* xgettext:c-format */
1260       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1261
1262     next_file:;
1263     }
1264
1265   write_archive (arch);
1266 }
1267
1268 /* Ought to default to replacing in place, but this is existing practice!  */
1269
1270 static void
1271 replace_members (arch, files_to_move, quick)
1272      bfd *arch;
1273      char **files_to_move;
1274      boolean quick;
1275 {
1276   boolean changed = false;
1277   bfd **after_bfd;              /* New entries go after this one */
1278   bfd *current;
1279   bfd **current_ptr;
1280   bfd *temp;
1281
1282   while (files_to_move && *files_to_move)
1283     {
1284       if (! quick)
1285         {
1286           current_ptr = &arch->next;
1287           while (*current_ptr)
1288             {
1289               current = *current_ptr;
1290
1291               /* For compatibility with existing ar programs, we
1292                  permit the same file to be added multiple times.  */
1293               if (FILENAME_CMP (normalize (*files_to_move, arch),
1294                                 normalize (current->filename, arch)) == 0
1295                   && current->arelt_data != NULL)
1296                 {
1297                   if (newer_only)
1298                     {
1299                       struct stat fsbuf, asbuf;
1300
1301                       if (stat (*files_to_move, &fsbuf) != 0)
1302                         {
1303                           if (errno != ENOENT)
1304                             bfd_fatal (*files_to_move);
1305                           goto next_file;
1306                         }
1307                       if (bfd_stat_arch_elt (current, &asbuf) != 0)
1308                         /* xgettext:c-format */
1309                         fatal (_("internal stat error on %s"), current->filename);
1310
1311                       if (fsbuf.st_mtime <= asbuf.st_mtime)
1312                         goto next_file;
1313                     }
1314
1315                   after_bfd = get_pos_bfd (&arch->next, pos_after,
1316                                            current->filename);
1317                   temp = *after_bfd;
1318
1319                   *after_bfd = bfd_openr (*files_to_move, NULL);
1320                   if (*after_bfd == (bfd *) NULL)
1321                     {
1322                       bfd_fatal (*files_to_move);
1323                     }
1324                   (*after_bfd)->next = temp;
1325
1326                   /* snip out this entry from the chain */
1327                   *current_ptr = (*current_ptr)->next;
1328
1329                   if (verbose)
1330                     {
1331                       printf ("r - %s\n", *files_to_move);
1332                     }
1333
1334                   changed = true;
1335
1336                   goto next_file;
1337                 }
1338               current_ptr = &(current->next);
1339             }
1340         }
1341
1342       /* Add to the end of the archive.  */
1343
1344       after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1345       temp = *after_bfd;
1346       *after_bfd = bfd_openr (*files_to_move, NULL);
1347       if (*after_bfd == (bfd *) NULL)
1348         {
1349           bfd_fatal (*files_to_move);
1350         }
1351       if (verbose)
1352         {
1353           printf ("a - %s\n", *files_to_move);
1354         }
1355
1356       (*after_bfd)->next = temp;
1357
1358       changed = true;
1359
1360     next_file:;
1361
1362       files_to_move++;
1363     }
1364
1365   if (changed)
1366     write_archive (arch);
1367   else
1368     output_filename = NULL;
1369 }
1370
1371 static void
1372 ranlib_only (archname)
1373      const char *archname;
1374 {
1375   bfd *arch;
1376
1377   write_armap = 1;
1378   arch = open_inarch (archname, (char *) NULL);
1379   if (arch == NULL)
1380     xexit (1);
1381   write_archive (arch);
1382 }
1383
1384 /* Update the timestamp of the symbol map of an archive.  */
1385
1386 static void
1387 ranlib_touch (archname)
1388      const char *archname;
1389 {
1390 #ifdef __GO32__
1391   /* I don't think updating works on go32.  */
1392   ranlib_only (archname);
1393 #else
1394   int f;
1395   bfd *arch;
1396   char **matching;
1397
1398   f = open (archname, O_RDWR | O_BINARY, 0);
1399   if (f < 0)
1400     {
1401       bfd_set_error (bfd_error_system_call);
1402       bfd_fatal (archname);
1403     }
1404
1405   arch = bfd_fdopenr (archname, (const char *) NULL, f);
1406   if (arch == NULL)
1407     bfd_fatal (archname);
1408   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1409     {
1410       bfd_nonfatal (archname);
1411       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1412         {
1413           list_matching_formats (matching);
1414           free (matching);
1415         }
1416       xexit (1);
1417     }
1418
1419   if (! bfd_has_map (arch))
1420     /* xgettext:c-format */
1421     fatal (_("%s: no archive map to update"), archname);
1422
1423   bfd_update_armap_timestamp (arch);
1424
1425   if (! bfd_close (arch))
1426     bfd_fatal (archname);
1427 #endif
1428 }
1429
1430 /* Things which are interesting to map over all or some of the files: */
1431
1432 static void
1433 print_descr (abfd)
1434      bfd *abfd;
1435 {
1436   print_arelt_descr (stdout, abfd, verbose);
1437 }