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