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