Merge from vendor branch LIBARCHIVE:
[dragonfly.git] / contrib / binutils-2.17 / 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
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 "bfd.h"
30 #include "libiberty.h"
31 #include "progress.h"
32 #include "bucomm.h"
33 #include "aout/ar.h"
34 #include "libbfd.h"
35 #include "arsup.h"
36 #include "filenames.h"
37 #include "binemul.h"
38 #include <sys/stat.h>
39
40 #ifdef __GO32___
41 #define EXT_NAME_LEN 3          /* bufflen of addition to name if it's MS-DOS */
42 #else
43 #define EXT_NAME_LEN 6          /* ditto for *NIX */
44 #endif
45
46 /* We need to open files in binary modes on system where that makes a
47    difference.  */
48 #ifndef O_BINARY
49 #define O_BINARY 0
50 #endif
51
52 /* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
53
54 struct ar_hdr *
55   bfd_special_undocumented_glue (bfd * abfd, const char *filename);
56
57 /* Static declarations */
58
59 static void mri_emul (void);
60 static const char *normalize (const char *, bfd *);
61 static void remove_output (void);
62 static void map_over_members (bfd *, void (*)(bfd *), char **, int);
63 static void print_contents (bfd * member);
64 static void delete_members (bfd *, char **files_to_delete);
65
66 static void move_members (bfd *, char **files_to_move);
67 static void replace_members
68   (bfd *, char **files_to_replace, bfd_boolean quick);
69 static void print_descr (bfd * abfd);
70 static void write_archive (bfd *);
71 static void ranlib_only (const char *archname);
72 static void ranlib_touch (const char *archname);
73 static void usage (int);
74 \f
75 /** Globals and flags */
76
77 static int mri_mode;
78
79 /* This flag distinguishes between ar and ranlib:
80    1 means this is 'ranlib'; 0 means this is 'ar'.
81    -1 means if we should use argv[0] to decide.  */
82 extern int is_ranlib;
83
84 /* Nonzero means don't warn about creating the archive file if necessary.  */
85 int silent_create = 0;
86
87 /* Nonzero means describe each action performed.  */
88 int verbose = 0;
89
90 /* Nonzero means preserve dates of members when extracting them.  */
91 int preserve_dates = 0;
92
93 /* Nonzero means don't replace existing members whose dates are more recent
94    than the corresponding files.  */
95 int newer_only = 0;
96
97 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
98    member).  -1 means we've been explicitly asked to not write a symbol table;
99    +1 means we've been explicitly asked to write it;
100    0 is the default.
101    Traditionally, the default in BSD has been to not write the table.
102    However, for POSIX.2 compliance the default is now to write a symbol table
103    if any of the members are object files.  */
104 int write_armap = 0;
105
106 /* Nonzero means it's the name of an existing member; position new or moved
107    files with respect to this one.  */
108 char *posname = NULL;
109
110 /* Sez how to use `posname': pos_before means position before that member.
111    pos_after means position after that member. pos_end means always at end.
112    pos_default means default appropriately. For the latter two, `posname'
113    should also be zero.  */
114 enum pos
115   {
116     pos_default, pos_before, pos_after, pos_end
117   } postype = pos_default;
118
119 static bfd **
120 get_pos_bfd (bfd **, enum pos, const char *);
121
122 /* For extract/delete only.  If COUNTED_NAME_MODE is TRUE, we only
123    extract the COUNTED_NAME_COUNTER instance of that name.  */
124 static bfd_boolean counted_name_mode = 0;
125 static int counted_name_counter = 0;
126
127 /* Whether to truncate names of files stored in the archive.  */
128 static bfd_boolean ar_truncate = FALSE;
129
130 /* Whether to use a full file name match when searching an archive.
131    This is convenient for archives created by the Microsoft lib
132    program.  */
133 static bfd_boolean full_pathname = FALSE;
134
135 int interactive = 0;
136
137 static void
138 mri_emul (void)
139 {
140   interactive = isatty (fileno (stdin));
141   yyparse ();
142 }
143
144 /* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
145    COUNT is the length of the FILES chain; FUNCTION is called on each entry
146    whose name matches one in FILES.  */
147
148 static void
149 map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
150 {
151   bfd *head;
152   int match_count;
153
154   if (count == 0)
155     {
156       for (head = arch->next; head; head = head->next)
157         {
158           PROGRESS (1);
159           function (head);
160         }
161       return;
162     }
163
164   /* This may appear to be a baroque way of accomplishing what we want.
165      However we have to iterate over the filenames in order to notice where
166      a filename is requested but does not exist in the archive.  Ditto
167      mapping over each file each time -- we want to hack multiple
168      references.  */
169
170   for (; count > 0; files++, count--)
171     {
172       bfd_boolean found = FALSE;
173
174       match_count = 0;
175       for (head = arch->next; head; head = head->next)
176         {
177           PROGRESS (1);
178           if (head->filename == NULL)
179             {
180               /* Some archive formats don't get the filenames filled in
181                  until the elements are opened.  */
182               struct stat buf;
183               bfd_stat_arch_elt (head, &buf);
184             }
185           if ((head->filename != NULL) &&
186               (!FILENAME_CMP (normalize (*files, arch), head->filename)))
187             {
188               ++match_count;
189               if (counted_name_mode
190                   && match_count != counted_name_counter)
191                 {
192                   /* Counting, and didn't match on count; go on to the
193                      next one.  */
194                   continue;
195                 }
196
197               found = TRUE;
198               function (head);
199             }
200         }
201       if (!found)
202         /* xgettext:c-format */
203         fprintf (stderr, _("no entry %s in archive\n"), *files);
204     }
205 }
206 \f
207 bfd_boolean operation_alters_arch = FALSE;
208
209 static void
210 usage (int help)
211 {
212   FILE *s;
213
214   s = help ? stdout : stderr;
215
216   if (! is_ranlib)
217     {
218       /* xgettext:c-format */
219       fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
220                program_name);
221       /* xgettext:c-format */
222       fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
223       fprintf (s, _(" commands:\n"));
224       fprintf (s, _("  d            - delete file(s) from the archive\n"));
225       fprintf (s, _("  m[ab]        - move file(s) in the archive\n"));
226       fprintf (s, _("  p            - print file(s) found in the archive\n"));
227       fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
228       fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
229       fprintf (s, _("  t            - display contents of archive\n"));
230       fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
231       fprintf (s, _(" command specific modifiers:\n"));
232       fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
233       fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
234       fprintf (s, _("  [N]          - use instance [count] of name\n"));
235       fprintf (s, _("  [f]          - truncate inserted file names\n"));
236       fprintf (s, _("  [P]          - use full path names when matching\n"));
237       fprintf (s, _("  [o]          - preserve original dates\n"));
238       fprintf (s, _("  [u]          - only replace files that are newer than current archive contents\n"));
239       fprintf (s, _(" generic modifiers:\n"));
240       fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
241       fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
242       fprintf (s, _("  [S]          - do not build a symbol table\n"));
243       fprintf (s, _("  [v]          - be verbose\n"));
244       fprintf (s, _("  [V]          - display the version number\n"));
245       fprintf (s, _("  @<file>      - read options from <file>\n"));
246  
247       ar_emul_usage (s);
248     }
249   else
250     {
251       /* xgettext:c-format */
252       fprintf (s, _("Usage: %s [options] archive\n"), program_name);
253       fprintf (s, _(" Generate an index to speed access to archives\n"));
254       fprintf (s, _(" The options are:\n\
255   @<file>                      Read options from <file>\n\
256   -h --help                    Print this help message\n\
257   -V --version                 Print version information\n"));
258     }
259
260   list_supported_targets (program_name, stderr);
261
262   if (help)
263     fprintf (s, _("Report bugs to %s\n"), REPORT_BUGS_TO);
264
265   xexit (help ? 0 : 1);
266 }
267
268 /* Normalize a file name specified on the command line into a file
269    name which we will use in an archive.  */
270
271 static const char *
272 normalize (const char *file, bfd *abfd)
273 {
274   const char *filename;
275
276   if (full_pathname)
277     return file;
278
279   filename = strrchr (file, '/');
280 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
281   {
282     /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
283     char *bslash = strrchr (file, '\\');
284     if (filename == NULL || (bslash != NULL && bslash > filename))
285       filename = bslash;
286     if (filename == NULL && file[0] != '\0' && file[1] == ':')
287       filename = file + 1;
288   }
289 #endif
290   if (filename != (char *) NULL)
291     filename++;
292   else
293     filename = file;
294
295   if (ar_truncate
296       && abfd != NULL
297       && strlen (filename) > abfd->xvec->ar_max_namelen)
298     {
299       char *s;
300
301       /* Space leak.  */
302       s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
303       memcpy (s, filename, abfd->xvec->ar_max_namelen);
304       s[abfd->xvec->ar_max_namelen] = '\0';
305       filename = s;
306     }
307
308   return filename;
309 }
310
311 /* Remove any output file.  This is only called via xatexit.  */
312
313 static const char *output_filename = NULL;
314 static FILE *output_file = NULL;
315 static bfd *output_bfd = NULL;
316
317 static void
318 remove_output (void)
319 {
320   if (output_filename != NULL)
321     {
322       if (output_bfd != NULL)
323         bfd_cache_close (output_bfd);
324       if (output_file != NULL)
325         fclose (output_file);
326       unlink_if_ordinary (output_filename);
327     }
328 }
329
330 /* The option parsing should be in its own function.
331    It will be when I have getopt working.  */
332
333 int main (int, char **);
334
335 int
336 main (int argc, char **argv)
337 {
338   char *arg_ptr;
339   char c;
340   enum
341     {
342       none = 0, delete, replace, print_table,
343       print_files, extract, move, quick_append
344     } operation = none;
345   int arg_index;
346   char **files;
347   int file_count;
348   char *inarch_filename;
349   int show_version;
350   int i;
351   int do_posix = 0;
352
353 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
354   setlocale (LC_MESSAGES, "");
355 #endif
356 #if defined (HAVE_SETLOCALE)
357   setlocale (LC_CTYPE, "");
358 #endif
359   bindtextdomain (PACKAGE, LOCALEDIR);
360   textdomain (PACKAGE);
361
362   program_name = argv[0];
363   xmalloc_set_program_name (program_name);
364
365   expandargv (&argc, &argv);
366
367   if (is_ranlib < 0)
368     {
369       char *temp;
370
371       temp = strrchr (program_name, '/');
372 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
373       {
374         /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
375         char *bslash = strrchr (program_name, '\\');
376         if (temp == NULL || (bslash != NULL && bslash > temp))
377           temp = bslash;
378         if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
379           temp = program_name + 1;
380       }
381 #endif
382       if (temp == NULL)
383         temp = program_name;
384       else
385         ++temp;
386       if (strlen (temp) >= 6
387           && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
388         is_ranlib = 1;
389       else
390         is_ranlib = 0;
391     }
392
393   if (argc > 1 && argv[1][0] == '-')
394     {
395       if (strcmp (argv[1], "--help") == 0)
396         usage (1);
397       else if (strcmp (argv[1], "--version") == 0)
398         {
399           if (is_ranlib)
400             print_version ("ranlib");
401           else
402             print_version ("ar");
403         }
404     }
405
406   START_PROGRESS (program_name, 0);
407
408   bfd_init ();
409   set_default_bfd_target ();
410
411   show_version = 0;
412
413   xatexit (remove_output);
414
415   for (i = 1; i < argc; i++)
416     if (! ar_emul_parse_arg (argv[i]))
417       break;
418   argv += (i - 1);
419   argc -= (i - 1);
420
421   if (is_ranlib)
422     {
423       bfd_boolean touch = FALSE;
424
425       if (argc < 2
426           || strcmp (argv[1], "--help") == 0
427           || strcmp (argv[1], "-h") == 0
428           || strcmp (argv[1], "-H") == 0)
429         usage (0);
430       if (strcmp (argv[1], "-V") == 0
431           || strcmp (argv[1], "-v") == 0
432           || strncmp (argv[1], "--v", 3) == 0)
433         print_version ("ranlib");
434       arg_index = 1;
435       if (strcmp (argv[1], "-t") == 0)
436         {
437           ++arg_index;
438           touch = TRUE;
439         }
440       while (arg_index < argc)
441         {
442           if (! touch)
443             ranlib_only (argv[arg_index]);
444           else
445             ranlib_touch (argv[arg_index]);
446           ++arg_index;
447         }
448       xexit (0);
449     }
450
451   if (argc == 2 && strcmp (argv[1], "-M") == 0)
452     {
453       mri_emul ();
454       xexit (0);
455     }
456
457   if (argc < 2)
458     usage (0);
459
460   arg_index = 1;
461   arg_ptr = argv[arg_index];
462
463   if (*arg_ptr == '-')
464     {
465       /* When the first option starts with '-' we support POSIX-compatible
466          option parsing.  */
467       do_posix = 1;
468       ++arg_ptr;                        /* compatibility */
469     }
470
471   do
472     {
473       while ((c = *arg_ptr++) != '\0')
474         {
475           switch (c)
476             {
477             case 'd':
478             case 'm':
479             case 'p':
480             case 'q':
481             case 'r':
482             case 't':
483             case 'x':
484               if (operation != none)
485                 fatal (_("two different operation options specified"));
486               switch (c)
487                 {
488                 case 'd':
489                   operation = delete;
490                   operation_alters_arch = TRUE;
491                   break;
492                 case 'm':
493                   operation = move;
494                   operation_alters_arch = TRUE;
495                   break;
496                 case 'p':
497                   operation = print_files;
498                   break;
499                 case 'q':
500                   operation = quick_append;
501                   operation_alters_arch = TRUE;
502                   break;
503                 case 'r':
504                   operation = replace;
505                   operation_alters_arch = TRUE;
506                   break;
507                 case 't':
508                   operation = print_table;
509                   break;
510                 case 'x':
511                   operation = extract;
512                   break;
513                 }
514             case 'l':
515               break;
516             case 'c':
517               silent_create = 1;
518               break;
519             case 'o':
520               preserve_dates = 1;
521               break;
522             case 'V':
523               show_version = TRUE;
524               break;
525             case 's':
526               write_armap = 1;
527               break;
528             case 'S':
529               write_armap = -1;
530               break;
531             case 'u':
532               newer_only = 1;
533               break;
534             case 'v':
535               verbose = 1;
536               break;
537             case 'a':
538               postype = pos_after;
539               break;
540             case 'b':
541               postype = pos_before;
542               break;
543             case 'i':
544               postype = pos_before;
545               break;
546             case 'M':
547               mri_mode = 1;
548               break;
549             case 'N':
550               counted_name_mode = TRUE;
551               break;
552             case 'f':
553               ar_truncate = TRUE;
554               break;
555             case 'P':
556               full_pathname = TRUE;
557               break;
558             default:
559               /* xgettext:c-format */
560               non_fatal (_("illegal option -- %c"), c);
561               usage (0);
562             }
563         }
564
565       /* With POSIX-compatible option parsing continue with the next
566          argument if it starts with '-'.  */
567       if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
568         arg_ptr = argv[++arg_index] + 1;
569       else
570         do_posix = 0;
571     }
572   while (do_posix);
573
574   if (show_version)
575     print_version ("ar");
576
577   ++arg_index;
578   if (arg_index >= argc)
579     usage (0);
580
581   if (mri_mode)
582     {
583       mri_emul ();
584     }
585   else
586     {
587       bfd *arch;
588
589       /* We don't use do_quick_append any more.  Too many systems
590          expect ar to always rebuild the symbol table even when q is
591          used.  */
592
593       /* We can't write an armap when using ar q, so just do ar r
594          instead.  */
595       if (operation == quick_append && write_armap)
596         operation = replace;
597
598       if ((operation == none || operation == print_table)
599           && write_armap == 1)
600         {
601           ranlib_only (argv[arg_index]);
602           xexit (0);
603         }
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->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->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   int ncopied = 0;
783   char *cbuf = xmalloc (BUFSIZE);
784   struct stat buf;
785   long 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       int nread;
801       int 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       fwrite (cbuf, 1, nread, stdout);
811       ncopied += tocopy;
812     }
813   free (cbuf);
814 }
815
816 /* Extract a member of the archive into its own file.
817
818    We defer opening the new file until after we have read a BUFSIZ chunk of the
819    old one, since we know we have just read the archive header for the old
820    one.  Since most members are shorter than BUFSIZ, this means we will read
821    the old header, read the old data, write a new inode for the new file, and
822    write the new data, and be done. This 'optimization' is what comes from
823    sitting next to a bare disk and hearing it every time it seeks.  -- Gnu
824    Gilmore  */
825
826 void
827 extract_file (bfd *abfd)
828 {
829   FILE *ostream;
830   char *cbuf = xmalloc (BUFSIZE);
831   int nread, tocopy;
832   long ncopied = 0;
833   long size;
834   struct stat buf;
835
836   if (bfd_stat_arch_elt (abfd, &buf) != 0)
837     /* xgettext:c-format */
838     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
839   size = buf.st_size;
840
841   if (size < 0)
842     /* xgettext:c-format */
843     fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
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         fwrite (cbuf, 1, nread, ostream);
894         ncopied += tocopy;
895       }
896
897   if (ostream != NULL)
898     fclose (ostream);
899
900   output_file = NULL;
901   output_filename = NULL;
902
903   chmod (bfd_get_filename (abfd), buf.st_mode);
904
905   if (preserve_dates)
906     {
907       /* Set access time to modification time.  Only st_mtime is
908          initialized by bfd_stat_arch_elt.  */
909       buf.st_atime = buf.st_mtime;
910       set_times (bfd_get_filename (abfd), &buf);
911     }
912
913   free (cbuf);
914 }
915
916 static void
917 write_archive (bfd *iarch)
918 {
919   bfd *obfd;
920   char *old_name, *new_name;
921   bfd *contents_head = iarch->next;
922
923   old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
924   strcpy (old_name, bfd_get_filename (iarch));
925   new_name = make_tempname (old_name);
926
927   output_filename = new_name;
928
929   obfd = bfd_openw (new_name, bfd_get_target (iarch));
930
931   if (obfd == NULL)
932     bfd_fatal (old_name);
933
934   output_bfd = obfd;
935
936   bfd_set_format (obfd, bfd_archive);
937
938   /* Request writing the archive symbol table unless we've
939      been explicitly requested not to.  */
940   obfd->has_armap = write_armap >= 0;
941
942   if (ar_truncate)
943     {
944       /* This should really use bfd_set_file_flags, but that rejects
945          archives.  */
946       obfd->flags |= BFD_TRADITIONAL_FORMAT;
947     }
948
949   if (!bfd_set_archive_head (obfd, contents_head))
950     bfd_fatal (old_name);
951
952   if (!bfd_close (obfd))
953     bfd_fatal (old_name);
954
955   output_bfd = NULL;
956   output_filename = NULL;
957
958   /* We don't care if this fails; we might be creating the archive.  */
959   bfd_close (iarch);
960
961   if (smart_rename (new_name, old_name, 0) != 0)
962     xexit (1);
963 }
964
965 /* Return a pointer to the pointer to the entry which should be rplacd'd
966    into when altering.  DEFAULT_POS should be how to interpret pos_default,
967    and should be a pos value.  */
968
969 static bfd **
970 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
971 {
972   bfd **after_bfd = contents;
973   enum pos realpos;
974   const char *realposname;
975
976   if (postype == pos_default)
977     {
978       realpos = default_pos;
979       realposname = default_posname;
980     }
981   else
982     {
983       realpos = postype;
984       realposname = posname;
985     }
986
987   if (realpos == pos_end)
988     {
989       while (*after_bfd)
990         after_bfd = &((*after_bfd)->next);
991     }
992   else
993     {
994       for (; *after_bfd; after_bfd = &(*after_bfd)->next)
995         if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
996           {
997             if (realpos == pos_after)
998               after_bfd = &(*after_bfd)->next;
999             break;
1000           }
1001     }
1002   return after_bfd;
1003 }
1004
1005 static void
1006 delete_members (bfd *arch, char **files_to_delete)
1007 {
1008   bfd **current_ptr_ptr;
1009   bfd_boolean found;
1010   bfd_boolean something_changed = FALSE;
1011   int match_count;
1012
1013   for (; *files_to_delete != NULL; ++files_to_delete)
1014     {
1015       /* In a.out systems, the armap is optional.  It's also called
1016          __.SYMDEF.  So if the user asked to delete it, we should remember
1017          that fact. This isn't quite right for COFF systems (where
1018          __.SYMDEF might be regular member), but it's very unlikely
1019          to be a problem.  FIXME */
1020
1021       if (!strcmp (*files_to_delete, "__.SYMDEF"))
1022         {
1023           arch->has_armap = FALSE;
1024           write_armap = -1;
1025           continue;
1026         }
1027
1028       found = FALSE;
1029       match_count = 0;
1030       current_ptr_ptr = &(arch->next);
1031       while (*current_ptr_ptr)
1032         {
1033           if (FILENAME_CMP (normalize (*files_to_delete, arch),
1034                             (*current_ptr_ptr)->filename) == 0)
1035             {
1036               ++match_count;
1037               if (counted_name_mode
1038                   && match_count != counted_name_counter)
1039                 {
1040                   /* Counting, and didn't match on count; go on to the
1041                      next one.  */
1042                 }
1043               else
1044                 {
1045                   found = TRUE;
1046                   something_changed = TRUE;
1047                   if (verbose)
1048                     printf ("d - %s\n",
1049                             *files_to_delete);
1050                   *current_ptr_ptr = ((*current_ptr_ptr)->next);
1051                   goto next_file;
1052                 }
1053             }
1054
1055           current_ptr_ptr = &((*current_ptr_ptr)->next);
1056         }
1057
1058       if (verbose && !found)
1059         {
1060           /* xgettext:c-format */
1061           printf (_("No member named `%s'\n"), *files_to_delete);
1062         }
1063     next_file:
1064       ;
1065     }
1066
1067   if (something_changed)
1068     write_archive (arch);
1069   else
1070     output_filename = NULL;
1071 }
1072
1073
1074 /* Reposition existing members within an archive */
1075
1076 static void
1077 move_members (bfd *arch, char **files_to_move)
1078 {
1079   bfd **after_bfd;              /* New entries go after this one */
1080   bfd **current_ptr_ptr;        /* cdr pointer into contents */
1081
1082   for (; *files_to_move; ++files_to_move)
1083     {
1084       current_ptr_ptr = &(arch->next);
1085       while (*current_ptr_ptr)
1086         {
1087           bfd *current_ptr = *current_ptr_ptr;
1088           if (FILENAME_CMP (normalize (*files_to_move, arch),
1089                             current_ptr->filename) == 0)
1090             {
1091               /* Move this file to the end of the list - first cut from
1092                  where it is.  */
1093               bfd *link;
1094               *current_ptr_ptr = current_ptr->next;
1095
1096               /* Now glue to end */
1097               after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1098               link = *after_bfd;
1099               *after_bfd = current_ptr;
1100               current_ptr->next = link;
1101
1102               if (verbose)
1103                 printf ("m - %s\n", *files_to_move);
1104
1105               goto next_file;
1106             }
1107
1108           current_ptr_ptr = &((*current_ptr_ptr)->next);
1109         }
1110       /* xgettext:c-format */
1111       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1112
1113     next_file:;
1114     }
1115
1116   write_archive (arch);
1117 }
1118
1119 /* Ought to default to replacing in place, but this is existing practice!  */
1120
1121 static void
1122 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1123 {
1124   bfd_boolean changed = FALSE;
1125   bfd **after_bfd;              /* New entries go after this one.  */
1126   bfd *current;
1127   bfd **current_ptr;
1128
1129   while (files_to_move && *files_to_move)
1130     {
1131       if (! quick)
1132         {
1133           current_ptr = &arch->next;
1134           while (*current_ptr)
1135             {
1136               current = *current_ptr;
1137
1138               /* For compatibility with existing ar programs, we
1139                  permit the same file to be added multiple times.  */
1140               if (FILENAME_CMP (normalize (*files_to_move, arch),
1141                                 normalize (current->filename, arch)) == 0
1142                   && current->arelt_data != NULL)
1143                 {
1144                   if (newer_only)
1145                     {
1146                       struct stat fsbuf, asbuf;
1147
1148                       if (stat (*files_to_move, &fsbuf) != 0)
1149                         {
1150                           if (errno != ENOENT)
1151                             bfd_fatal (*files_to_move);
1152                           goto next_file;
1153                         }
1154                       if (bfd_stat_arch_elt (current, &asbuf) != 0)
1155                         /* xgettext:c-format */
1156                         fatal (_("internal stat error on %s"),
1157                                current->filename);
1158
1159                       if (fsbuf.st_mtime <= asbuf.st_mtime)
1160                         goto next_file;
1161                     }
1162
1163                   after_bfd = get_pos_bfd (&arch->next, pos_after,
1164                                            current->filename);
1165                   if (ar_emul_replace (after_bfd, *files_to_move,
1166                                        verbose))
1167                     {
1168                       /* Snip out this entry from the chain.  */
1169                       *current_ptr = (*current_ptr)->next;
1170                       changed = TRUE;
1171                     }
1172
1173                   goto next_file;
1174                 }
1175               current_ptr = &(current->next);
1176             }
1177         }
1178
1179       /* Add to the end of the archive.  */
1180       after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1181
1182       if (ar_emul_append (after_bfd, *files_to_move, verbose))
1183         changed = TRUE;
1184
1185     next_file:;
1186
1187       files_to_move++;
1188     }
1189
1190   if (changed)
1191     write_archive (arch);
1192   else
1193     output_filename = NULL;
1194 }
1195
1196 static void
1197 ranlib_only (const char *archname)
1198 {
1199   bfd *arch;
1200
1201   if (get_file_size (archname) < 1)
1202     return;
1203   write_armap = 1;
1204   arch = open_inarch (archname, (char *) NULL);
1205   if (arch == NULL)
1206     xexit (1);
1207   write_archive (arch);
1208 }
1209
1210 /* Update the timestamp of the symbol map of an archive.  */
1211
1212 static void
1213 ranlib_touch (const char *archname)
1214 {
1215 #ifdef __GO32__
1216   /* I don't think updating works on go32.  */
1217   ranlib_only (archname);
1218 #else
1219   int f;
1220   bfd *arch;
1221   char **matching;
1222
1223   if (get_file_size (archname) < 1)
1224     return;
1225   f = open (archname, O_RDWR | O_BINARY, 0);
1226   if (f < 0)
1227     {
1228       bfd_set_error (bfd_error_system_call);
1229       bfd_fatal (archname);
1230     }
1231
1232   arch = bfd_fdopenr (archname, (const char *) NULL, f);
1233   if (arch == NULL)
1234     bfd_fatal (archname);
1235   if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1236     {
1237       bfd_nonfatal (archname);
1238       if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1239         {
1240           list_matching_formats (matching);
1241           free (matching);
1242         }
1243       xexit (1);
1244     }
1245
1246   if (! bfd_has_map (arch))
1247     /* xgettext:c-format */
1248     fatal (_("%s: no archive map to update"), archname);
1249
1250   bfd_update_armap_timestamp (arch);
1251
1252   if (! bfd_close (arch))
1253     bfd_fatal (archname);
1254 #endif
1255 }
1256
1257 /* Things which are interesting to map over all or some of the files: */
1258
1259 static void
1260 print_descr (bfd *abfd)
1261 {
1262   print_arelt_descr (stdout, abfd, verbose);
1263 }