* ar.c (usage): Mention -t command line switch.
[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, 2008
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   -t                           Update the archive's symbol map timestamp\n\
259   -h --help                    Print this help message\n\
260   -v --version                 Print version information\n"));
261     }
262
263   list_supported_targets (program_name, s);
264
265   if (REPORT_BUGS_TO[0] && help)
266     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
267
268   xexit (help ? 0 : 1);
269 }
270
271 /* Normalize a file name specified on the command line into a file
272    name which we will use in an archive.  */
273
274 static const char *
275 normalize (const char *file, bfd *abfd)
276 {
277   const char *filename;
278
279   if (full_pathname)
280     return file;
281
282   filename = strrchr (file, '/');
283 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
284   {
285     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
286     char *bslash = strrchr (file, '\\');
287     if (filename == NULL || (bslash != NULL && bslash > filename))
288       filename = bslash;
289     if (filename == NULL && file[0] != '\0' && file[1] == ':')
290       filename = file + 1;
291   }
292 #endif
293   if (filename != (char *) NULL)
294     filename++;
295   else
296     filename = file;
297
298   if (ar_truncate
299       && abfd != NULL
300       && strlen (filename) > abfd->xvec->ar_max_namelen)
301     {
302       char *s;
303
304       /* Space leak.  */
305       s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
306       memcpy (s, filename, abfd->xvec->ar_max_namelen);
307       s[abfd->xvec->ar_max_namelen] = '\0';
308       filename = s;
309     }
310
311   return filename;
312 }
313
314 /* Remove any output file.  This is only called via xatexit.  */
315
316 static const char *output_filename = NULL;
317 static FILE *output_file = NULL;
318 static bfd *output_bfd = NULL;
319
320 static void
321 remove_output (void)
322 {
323   if (output_filename != NULL)
324     {
325       if (output_bfd != NULL)
326         bfd_cache_close (output_bfd);
327       if (output_file != NULL)
328         fclose (output_file);
329       unlink_if_ordinary (output_filename);
330     }
331 }
332
333 /* The option parsing should be in its own function.
334    It will be when I have getopt working.  */
335
336 int main (int, char **);
337
338 int
339 main (int argc, char **argv)
340 {
341   char *arg_ptr;
342   char c;
343   enum
344     {
345       none = 0, delete, replace, print_table,
346       print_files, extract, move, quick_append
347     } operation = none;
348   int arg_index;
349   char **files;
350   int file_count;
351   char *inarch_filename;
352   int show_version;
353   int i;
354   int do_posix = 0;
355
356 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
357   setlocale (LC_MESSAGES, "");
358 #endif
359 #if defined (HAVE_SETLOCALE)
360   setlocale (LC_CTYPE, "");
361 #endif
362   bindtextdomain (PACKAGE, LOCALEDIR);
363   textdomain (PACKAGE);
364
365   program_name = argv[0];
366   xmalloc_set_program_name (program_name);
367
368   expandargv (&argc, &argv);
369
370   if (is_ranlib < 0)
371     {
372       char *temp;
373
374       temp = strrchr (program_name, '/');
375 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
376       {
377         /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
378         char *bslash = strrchr (program_name, '\\');
379         if (temp == NULL || (bslash != NULL && bslash > temp))
380           temp = bslash;
381         if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
382           temp = program_name + 1;
383       }
384 #endif
385       if (temp == NULL)
386         temp = program_name;
387       else
388         ++temp;
389       if (strlen (temp) >= 6
390           && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
391         is_ranlib = 1;
392       else
393         is_ranlib = 0;
394     }
395
396   if (argc > 1 && argv[1][0] == '-')
397     {
398       if (strcmp (argv[1], "--help") == 0)
399         usage (1);
400       else if (strcmp (argv[1], "--version") == 0)
401         {
402           if (is_ranlib)
403             print_version ("ranlib");
404           else
405             print_version ("ar");
406         }
407     }
408
409   START_PROGRESS (program_name, 0);
410
411   bfd_init ();
412   set_default_bfd_target ();
413
414   show_version = 0;
415
416   xatexit (remove_output);
417
418   for (i = 1; i < argc; i++)
419     if (! ar_emul_parse_arg (argv[i]))
420       break;
421   argv += (i - 1);
422   argc -= (i - 1);
423
424   if (is_ranlib)
425     {
426       int status = 0;
427       bfd_boolean touch = FALSE;
428
429       if (argc < 2
430           || strcmp (argv[1], "--help") == 0
431           || strcmp (argv[1], "-h") == 0
432           || strcmp (argv[1], "-H") == 0)
433         usage (0);
434       if (strcmp (argv[1], "-V") == 0
435           || strcmp (argv[1], "-v") == 0
436           || CONST_STRNEQ (argv[1], "--v"))
437         print_version ("ranlib");
438       arg_index = 1;
439       if (strcmp (argv[1], "-t") == 0)
440         {
441           ++arg_index;
442           touch = TRUE;
443         }
444       while (arg_index < argc)
445         {
446           if (! touch)
447             status |= ranlib_only (argv[arg_index]);
448           else
449             status |= ranlib_touch (argv[arg_index]);
450           ++arg_index;
451         }
452       xexit (status);
453     }
454
455   if (argc == 2 && strcmp (argv[1], "-M") == 0)
456     {
457       mri_emul ();
458       xexit (0);
459     }
460
461   if (argc < 2)
462     usage (0);
463
464   arg_index = 1;
465   arg_ptr = argv[arg_index];
466
467   if (*arg_ptr == '-')
468     {
469       /* When the first option starts with '-' we support POSIX-compatible
470          option parsing.  */
471       do_posix = 1;
472       ++arg_ptr;                        /* compatibility */
473     }
474
475   do
476     {
477       while ((c = *arg_ptr++) != '\0')
478         {
479           switch (c)
480             {
481             case 'd':
482             case 'm':
483             case 'p':
484             case 'q':
485             case 'r':
486             case 't':
487             case 'x':
488               if (operation != none)
489                 fatal (_("two different operation options specified"));
490               switch (c)
491                 {
492                 case 'd':
493                   operation = delete;
494                   operation_alters_arch = TRUE;
495                   break;
496                 case 'm':
497                   operation = move;
498                   operation_alters_arch = TRUE;
499                   break;
500                 case 'p':
501                   operation = print_files;
502                   break;
503                 case 'q':
504                   operation = quick_append;
505                   operation_alters_arch = TRUE;
506                   break;
507                 case 'r':
508                   operation = replace;
509                   operation_alters_arch = TRUE;
510                   break;
511                 case 't':
512                   operation = print_table;
513                   break;
514                 case 'x':
515                   operation = extract;
516                   break;
517                 }
518             case 'l':
519               break;
520             case 'c':
521               silent_create = 1;
522               break;
523             case 'o':
524               preserve_dates = 1;
525               break;
526             case 'V':
527               show_version = TRUE;
528               break;
529             case 's':
530               write_armap = 1;
531               break;
532             case 'S':
533               write_armap = -1;
534               break;
535             case 'u':
536               newer_only = 1;
537               break;
538             case 'v':
539               verbose = 1;
540               break;
541             case 'a':
542               postype = pos_after;
543               break;
544             case 'b':
545               postype = pos_before;
546               break;
547             case 'i':
548               postype = pos_before;
549               break;
550             case 'M':
551               mri_mode = 1;
552               break;
553             case 'N':
554               counted_name_mode = TRUE;
555               break;
556             case 'f':
557               ar_truncate = TRUE;
558               break;
559             case 'P':
560               full_pathname = TRUE;
561               break;
562             default:
563               /* xgettext:c-format */
564               non_fatal (_("illegal option -- %c"), c);
565               usage (0);
566             }
567         }
568
569       /* With POSIX-compatible option parsing continue with the next
570          argument if it starts with '-'.  */
571       if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
572         arg_ptr = argv[++arg_index] + 1;
573       else
574         do_posix = 0;
575     }
576   while (do_posix);
577
578   if (show_version)
579     print_version ("ar");
580
581   ++arg_index;
582   if (arg_index >= argc)
583     usage (0);
584
585   if (mri_mode)
586     {
587       mri_emul ();
588     }
589   else
590     {
591       bfd *arch;
592
593       /* We don't use do_quick_append any more.  Too many systems
594          expect ar to always rebuild the symbol table even when q is
595          used.  */
596
597       /* We can't write an armap when using ar q, so just do ar r
598          instead.  */
599       if (operation == quick_append && write_armap)
600         operation = replace;
601
602       if ((operation == none || operation == print_table)
603           && write_armap == 1)
604         xexit (ranlib_only (argv[arg_index]));
605
606       if (operation == none)
607         fatal (_("no operation specified"));
608
609       if (newer_only && operation != replace)
610         fatal (_("`u' is only meaningful with the `r' option."));
611
612       if (postype != pos_default)
613         posname = argv[arg_index++];
614
615       if (counted_name_mode)
616         {
617           if (operation != extract && operation != delete)
618              fatal (_("`N' is only meaningful with the `x' and `d' options."));
619           counted_name_counter = atoi (argv[arg_index++]);
620           if (counted_name_counter <= 0)
621             fatal (_("Value for `N' must be positive."));
622         }
623
624       inarch_filename = argv[arg_index++];
625
626       files = arg_index < argc ? argv + arg_index : NULL;
627       file_count = argc - arg_index;
628
629       arch = open_inarch (inarch_filename,
630                           files == NULL ? (char *) NULL : files[0]);
631
632       switch (operation)
633         {
634         case print_table:
635           map_over_members (arch, print_descr, files, file_count);
636           break;
637
638         case print_files:
639           map_over_members (arch, print_contents, files, file_count);
640           break;
641
642         case extract:
643           map_over_members (arch, extract_file, files, file_count);
644           break;
645
646         case delete:
647           if (files != NULL)
648             delete_members (arch, files);
649           else
650             output_filename = NULL;
651           break;
652
653         case move:
654           if (files != NULL)
655             move_members (arch, files);
656           else
657             output_filename = NULL;
658           break;
659
660         case replace:
661         case quick_append:
662           if (files != NULL || write_armap > 0)
663             replace_members (arch, files, operation == quick_append);
664           else
665             output_filename = NULL;
666           break;
667
668           /* Shouldn't happen! */
669         default:
670           /* xgettext:c-format */
671           fatal (_("internal error -- this option not implemented"));
672         }
673     }
674
675   END_PROGRESS (program_name);
676
677   xexit (0);
678   return 0;
679 }
680
681 bfd *
682 open_inarch (const char *archive_filename, const char *file)
683 {
684   const char *target;
685   bfd **last_one;
686   bfd *next_one;
687   struct stat sbuf;
688   bfd *arch;
689   char **matching;
690
691   bfd_set_error (bfd_error_no_error);
692
693   target = NULL;
694
695   if (stat (archive_filename, &sbuf) != 0)
696     {
697 #if !defined(__GO32__) || defined(__DJGPP__)
698
699       /* FIXME: I don't understand why this fragment was ifndef'ed
700          away for __GO32__; perhaps it was in the days of DJGPP v1.x.
701          stat() works just fine in v2.x, so I think this should be
702          removed.  For now, I enable it for DJGPP v2. -- EZ.  */
703
704 /* KLUDGE ALERT! Temporary fix until I figger why
705    stat() is wrong ... think it's buried in GO32's IDT - Jax */
706       if (errno != ENOENT)
707         bfd_fatal (archive_filename);
708 #endif
709
710       if (!operation_alters_arch)
711         {
712           fprintf (stderr, "%s: ", program_name);
713           perror (archive_filename);
714           maybequit ();
715           return NULL;
716         }
717
718       /* Try to figure out the target to use for the archive from the
719          first object on the list.  */
720       if (file != NULL)
721         {
722           bfd *obj;
723
724           obj = bfd_openr (file, NULL);
725           if (obj != NULL)
726             {
727               if (bfd_check_format (obj, bfd_object))
728                 target = bfd_get_target (obj);
729               (void) bfd_close (obj);
730             }
731         }
732
733       /* Create an empty archive.  */
734       arch = bfd_openw (archive_filename, target);
735       if (arch == NULL
736           || ! bfd_set_format (arch, bfd_archive)
737           || ! bfd_close (arch))
738         bfd_fatal (archive_filename);
739       else if (!silent_create)
740         non_fatal (_("creating %s"), archive_filename);
741
742       /* If we die creating a new archive, don't leave it around.  */
743       output_filename = archive_filename;
744     }
745
746   arch = bfd_openr (archive_filename, target);
747   if (arch == NULL)
748     {
749     bloser:
750       bfd_fatal (archive_filename);
751     }
752
753   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
754     {
755       bfd_nonfatal (archive_filename);
756       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
757         {
758           list_matching_formats (matching);
759           free (matching);
760         }
761       xexit (1);
762     }
763
764   last_one = &(arch->archive_next);
765   /* Read all the contents right away, regardless.  */
766   for (next_one = bfd_openr_next_archived_file (arch, NULL);
767        next_one;
768        next_one = bfd_openr_next_archived_file (arch, next_one))
769     {
770       PROGRESS (1);
771       *last_one = next_one;
772       last_one = &next_one->archive_next;
773     }
774   *last_one = (bfd *) NULL;
775   if (bfd_get_error () != bfd_error_no_more_archived_files)
776     goto bloser;
777   return arch;
778 }
779
780 static void
781 print_contents (bfd *abfd)
782 {
783   size_t ncopied = 0;
784   char *cbuf = xmalloc (BUFSIZE);
785   struct stat buf;
786   size_t size;
787   if (bfd_stat_arch_elt (abfd, &buf) != 0)
788     /* xgettext:c-format */
789     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
790
791   if (verbose)
792     /* xgettext:c-format */
793     printf (_("\n<%s>\n\n"), bfd_get_filename (abfd));
794
795   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
796
797   size = buf.st_size;
798   while (ncopied < size)
799     {
800
801       size_t nread;
802       size_t tocopy = size - ncopied;
803       if (tocopy > BUFSIZE)
804         tocopy = BUFSIZE;
805
806       nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
807       if (nread != tocopy)
808         /* xgettext:c-format */
809         fatal (_("%s is not a valid archive"),
810                bfd_get_filename (bfd_my_archive (abfd)));
811
812       /* fwrite in mingw32 may return int instead of size_t. Cast the
813          return value to size_t to avoid comparison between signed and
814          unsigned values.  */
815       if ((size_t) fwrite (cbuf, 1, nread, stdout) != nread)
816         fatal ("stdout: %s", strerror (errno));
817       ncopied += tocopy;
818     }
819   free (cbuf);
820 }
821
822 /* Extract a member of the archive into its own file.
823
824    We defer opening the new file until after we have read a BUFSIZ chunk of the
825    old one, since we know we have just read the archive header for the old
826    one.  Since most members are shorter than BUFSIZ, this means we will read
827    the old header, read the old data, write a new inode for the new file, and
828    write the new data, and be done. This 'optimization' is what comes from
829    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
830    Gilmore  */
831
832 void
833 extract_file (bfd *abfd)
834 {
835   FILE *ostream;
836   char *cbuf = xmalloc (BUFSIZE);
837   size_t nread, tocopy;
838   size_t ncopied = 0;
839   size_t size;
840   struct stat buf;
841
842   if (bfd_stat_arch_elt (abfd, &buf) != 0)
843     /* xgettext:c-format */
844     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
845   size = buf.st_size;
846
847   if (verbose)
848     printf ("x - %s\n", bfd_get_filename (abfd));
849
850   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
851
852   ostream = NULL;
853   if (size == 0)
854     {
855       /* Seems like an abstraction violation, eh?  Well it's OK! */
856       output_filename = bfd_get_filename (abfd);
857
858       ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
859       if (ostream == NULL)
860         {
861           perror (bfd_get_filename (abfd));
862           xexit (1);
863         }
864
865       output_file = ostream;
866     }
867   else
868     while (ncopied < size)
869       {
870         tocopy = size - ncopied;
871         if (tocopy > BUFSIZE)
872           tocopy = BUFSIZE;
873
874         nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
875         if (nread != tocopy)
876           /* xgettext:c-format */
877           fatal (_("%s is not a valid archive"),
878                  bfd_get_filename (bfd_my_archive (abfd)));
879
880         /* See comment above; this saves disk arm motion */
881         if (ostream == NULL)
882           {
883             /* Seems like an abstraction violation, eh?  Well it's OK! */
884             output_filename = bfd_get_filename (abfd);
885
886             ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
887             if (ostream == NULL)
888               {
889                 perror (bfd_get_filename (abfd));
890                 xexit (1);
891               }
892
893             output_file = ostream;
894           }
895
896         /* fwrite in mingw32 may return int instead of size_t. Cast
897            the return value to size_t to avoid comparison between
898            signed and unsigned values.  */
899         if ((size_t) fwrite (cbuf, 1, nread, ostream) != nread)
900           fatal ("%s: %s", output_filename, strerror (errno));
901         ncopied += tocopy;
902       }
903
904   if (ostream != NULL)
905     fclose (ostream);
906
907   output_file = NULL;
908   output_filename = NULL;
909
910   chmod (bfd_get_filename (abfd), buf.st_mode);
911
912   if (preserve_dates)
913     {
914       /* Set access time to modification time.  Only st_mtime is
915          initialized by bfd_stat_arch_elt.  */
916       buf.st_atime = buf.st_mtime;
917       set_times (bfd_get_filename (abfd), &buf);
918     }
919
920   free (cbuf);
921 }
922
923 static void
924 write_archive (bfd *iarch)
925 {
926   bfd *obfd;
927   char *old_name, *new_name;
928   bfd *contents_head = iarch->archive_next;
929
930   old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
931   strcpy (old_name, bfd_get_filename (iarch));
932   new_name = make_tempname (old_name);
933
934   if (new_name == NULL)
935     bfd_fatal ("could not create temporary file whilst writing archive");
936   
937   output_filename = new_name;
938
939   obfd = bfd_openw (new_name, bfd_get_target (iarch));
940
941   if (obfd == NULL)
942     bfd_fatal (old_name);
943
944   output_bfd = obfd;
945
946   bfd_set_format (obfd, bfd_archive);
947
948   /* Request writing the archive symbol table unless we've
949      been explicitly requested not to.  */
950   obfd->has_armap = write_armap >= 0;
951
952   if (ar_truncate)
953     {
954       /* This should really use bfd_set_file_flags, but that rejects
955          archives.  */
956       obfd->flags |= BFD_TRADITIONAL_FORMAT;
957     }
958
959   if (!bfd_set_archive_head (obfd, contents_head))
960     bfd_fatal (old_name);
961
962   if (!bfd_close (obfd))
963     bfd_fatal (old_name);
964
965   output_bfd = NULL;
966   output_filename = NULL;
967
968   /* We don't care if this fails; we might be creating the archive.  */
969   bfd_close (iarch);
970
971   if (smart_rename (new_name, old_name, 0) != 0)
972     xexit (1);
973 }
974
975 /* Return a pointer to the pointer to the entry which should be rplacd'd
976    into when altering.  DEFAULT_POS should be how to interpret pos_default,
977    and should be a pos value.  */
978
979 static bfd **
980 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
981 {
982   bfd **after_bfd = contents;
983   enum pos realpos;
984   const char *realposname;
985
986   if (postype == pos_default)
987     {
988       realpos = default_pos;
989       realposname = default_posname;
990     }
991   else
992     {
993       realpos = postype;
994       realposname = posname;
995     }
996
997   if (realpos == pos_end)
998     {
999       while (*after_bfd)
1000         after_bfd = &((*after_bfd)->archive_next);
1001     }
1002   else
1003     {
1004       for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
1005         if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
1006           {
1007             if (realpos == pos_after)
1008               after_bfd = &(*after_bfd)->archive_next;
1009             break;
1010           }
1011     }
1012   return after_bfd;
1013 }
1014
1015 static void
1016 delete_members (bfd *arch, char **files_to_delete)
1017 {
1018   bfd **current_ptr_ptr;
1019   bfd_boolean found;
1020   bfd_boolean something_changed = FALSE;
1021   int match_count;
1022
1023   for (; *files_to_delete != NULL; ++files_to_delete)
1024     {
1025       /* In a.out systems, the armap is optional.  It's also called
1026          __.SYMDEF.  So if the user asked to delete it, we should remember
1027          that fact. This isn't quite right for COFF systems (where
1028          __.SYMDEF might be regular member), but it's very unlikely
1029          to be a problem.  FIXME */
1030
1031       if (!strcmp (*files_to_delete, "__.SYMDEF"))
1032         {
1033           arch->has_armap = FALSE;
1034           write_armap = -1;
1035           continue;
1036         }
1037
1038       found = FALSE;
1039       match_count = 0;
1040       current_ptr_ptr = &(arch->archive_next);
1041       while (*current_ptr_ptr)
1042         {
1043           if (FILENAME_CMP (normalize (*files_to_delete, arch),
1044                             (*current_ptr_ptr)->filename) == 0)
1045             {
1046               ++match_count;
1047               if (counted_name_mode
1048                   && match_count != counted_name_counter)
1049                 {
1050                   /* Counting, and didn't match on count; go on to the
1051                      next one.  */
1052                 }
1053               else
1054                 {
1055                   found = TRUE;
1056                   something_changed = TRUE;
1057                   if (verbose)
1058                     printf ("d - %s\n",
1059                             *files_to_delete);
1060                   *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
1061                   goto next_file;
1062                 }
1063             }
1064
1065           current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
1066         }
1067
1068       if (verbose && !found)
1069         {
1070           /* xgettext:c-format */
1071           printf (_("No member named `%s'\n"), *files_to_delete);
1072         }
1073     next_file:
1074       ;
1075     }
1076
1077   if (something_changed)
1078     write_archive (arch);
1079   else
1080     output_filename = NULL;
1081 }
1082
1083
1084 /* Reposition existing members within an archive */
1085
1086 static void
1087 move_members (bfd *arch, char **files_to_move)
1088 {
1089   bfd **after_bfd;              /* New entries go after this one */
1090   bfd **current_ptr_ptr;        /* cdr pointer into contents */
1091
1092   for (; *files_to_move; ++files_to_move)
1093     {
1094       current_ptr_ptr = &(arch->archive_next);
1095       while (*current_ptr_ptr)
1096         {
1097           bfd *current_ptr = *current_ptr_ptr;
1098           if (FILENAME_CMP (normalize (*files_to_move, arch),
1099                             current_ptr->filename) == 0)
1100             {
1101               /* Move this file to the end of the list - first cut from
1102                  where it is.  */
1103               bfd *link;
1104               *current_ptr_ptr = current_ptr->archive_next;
1105
1106               /* Now glue to end */
1107               after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
1108               link = *after_bfd;
1109               *after_bfd = current_ptr;
1110               current_ptr->archive_next = link;
1111
1112               if (verbose)
1113                 printf ("m - %s\n", *files_to_move);
1114
1115               goto next_file;
1116             }
1117
1118           current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
1119         }
1120       /* xgettext:c-format */
1121       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1122
1123     next_file:;
1124     }
1125
1126   write_archive (arch);
1127 }
1128
1129 /* Ought to default to replacing in place, but this is existing practice!  */
1130
1131 static void
1132 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1133 {
1134   bfd_boolean changed = FALSE;
1135   bfd **after_bfd;              /* New entries go after this one.  */
1136   bfd *current;
1137   bfd **current_ptr;
1138
1139   while (files_to_move && *files_to_move)
1140     {
1141       if (! quick)
1142         {
1143           current_ptr = &arch->archive_next;
1144           while (*current_ptr)
1145             {
1146               current = *current_ptr;
1147
1148               /* For compatibility with existing ar programs, we
1149                  permit the same file to be added multiple times.  */
1150               if (FILENAME_CMP (normalize (*files_to_move, arch),
1151                                 normalize (current->filename, arch)) == 0
1152                   && current->arelt_data != NULL)
1153                 {
1154                   if (newer_only)
1155                     {
1156                       struct stat fsbuf, asbuf;
1157
1158                       if (stat (*files_to_move, &fsbuf) != 0)
1159                         {
1160                           if (errno != ENOENT)
1161                             bfd_fatal (*files_to_move);
1162                           goto next_file;
1163                         }
1164                       if (bfd_stat_arch_elt (current, &asbuf) != 0)
1165                         /* xgettext:c-format */
1166                         fatal (_("internal stat error on %s"),
1167                                current->filename);
1168
1169                       if (fsbuf.st_mtime <= asbuf.st_mtime)
1170                         goto next_file;
1171                     }
1172
1173                   after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
1174                                            current->filename);
1175                   if (ar_emul_replace (after_bfd, *files_to_move,
1176                                        verbose))
1177                     {
1178                       /* Snip out this entry from the chain.  */
1179                       *current_ptr = (*current_ptr)->archive_next;
1180                       changed = TRUE;
1181                     }
1182
1183                   goto next_file;
1184                 }
1185               current_ptr = &(current->archive_next);
1186             }
1187         }
1188
1189       /* Add to the end of the archive.  */
1190       after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
1191
1192       if (ar_emul_append (after_bfd, *files_to_move, verbose))
1193         changed = TRUE;
1194
1195     next_file:;
1196
1197       files_to_move++;
1198     }
1199
1200   if (changed)
1201     write_archive (arch);
1202   else
1203     output_filename = NULL;
1204 }
1205
1206 static int
1207 ranlib_only (const char *archname)
1208 {
1209   bfd *arch;
1210
1211   if (get_file_size (archname) < 1)
1212     return 1;
1213   write_armap = 1;
1214   arch = open_inarch (archname, (char *) NULL);
1215   if (arch == NULL)
1216     xexit (1);
1217   write_archive (arch);
1218   return 0;
1219 }
1220
1221 /* Update the timestamp of the symbol map of an archive.  */
1222
1223 static int
1224 ranlib_touch (const char *archname)
1225 {
1226 #ifdef __GO32__
1227   /* I don't think updating works on go32.  */
1228   ranlib_only (archname);
1229 #else
1230   int f;
1231   bfd *arch;
1232   char **matching;
1233
1234   if (get_file_size (archname) < 1)
1235     return 1;
1236   f = open (archname, O_RDWR | O_BINARY, 0);
1237   if (f < 0)
1238     {
1239       bfd_set_error (bfd_error_system_call);
1240       bfd_fatal (archname);
1241     }
1242
1243   arch = bfd_fdopenr (archname, (const char *) NULL, f);
1244   if (arch == NULL)
1245     bfd_fatal (archname);
1246   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1247     {
1248       bfd_nonfatal (archname);
1249       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1250         {
1251           list_matching_formats (matching);
1252           free (matching);
1253         }
1254       xexit (1);
1255     }
1256
1257   if (! bfd_has_map (arch))
1258     /* xgettext:c-format */
1259     fatal (_("%s: no archive map to update"), archname);
1260
1261   bfd_update_armap_timestamp (arch);
1262
1263   if (! bfd_close (arch))
1264     bfd_fatal (archname);
1265 #endif
1266   return 0;
1267 }
1268
1269 /* Things which are interesting to map over all or some of the files: */
1270
1271 static void
1272 print_descr (bfd *abfd)
1273 {
1274   print_arelt_descr (stdout, abfd, verbose);
1275 }