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