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