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