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