ar.c revision 33965
1246074Sgabor/* ar.c - Archive modify and extract.
2246074Sgabor   Copyright 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
3246074Sgabor
4246074SgaborThis file is part of GNU Binutils.
5246074Sgabor
6246074SgaborThis program is free software; you can redistribute it and/or modify
7246074Sgaborit under the terms of the GNU General Public License as published by
8246074Sgaborthe Free Software Foundation; either version 2 of the License, or
9246074Sgabor(at your option) any later version.
10246074Sgabor
11246074SgaborThis program is distributed in the hope that it will be useful,
12246074Sgaborbut WITHOUT ANY WARRANTY; without even the implied warranty of
13246074SgaborMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14246074SgaborGNU General Public License for more details.
15246074Sgabor
16246074SgaborYou should have received a copy of the GNU General Public License
17246074Sgaboralong with this program; if not, write to the Free Software
18246074SgaborFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19246074Sgabor
20246074Sgabor/*
21246074Sgabor   Bugs: should use getopt the way tar does (complete w/optional -) and
22246074Sgabor   should have long options too. GNU ar used to check file against filesystem
23246074Sgabor   in quick_update and replace operations (would check mtime). Doesn't warn
24246074Sgabor   when name truncated. No way to specify pos_end. Error messages should be
25246074Sgabor   more consistant.
26246091Sdelphij*/
27246091Sdelphij#include "bfd.h"
28246074Sgabor#include "libiberty.h"
29246074Sgabor#include "progress.h"
30246074Sgabor#include "bucomm.h"
31246074Sgabor#include "aout/ar.h"
32246074Sgabor#include "libbfd.h"
33246074Sgabor#include "arsup.h"
34246074Sgabor#include <sys/stat.h>
35246074Sgabor
36287223Sdelphij#ifdef HAVE_GOOD_UTIME_H
37246074Sgabor#include <utime.h>
38246074Sgabor#else /* ! HAVE_GOOD_UTIME_H */
39246074Sgabor#ifdef HAVE_UTIMES
40246074Sgabor#include <sys/time.h>
41246074Sgabor#endif /* HAVE_UTIMES */
42246074Sgabor#endif /* ! HAVE_GOOD_UTIME_H */
43246074Sgabor
44246074Sgabor#ifdef __GO32___
45246074Sgabor#define EXT_NAME_LEN 3		/* bufflen of addition to name if it's MS-DOS */
46246074Sgabor#else
47246074Sgabor#define EXT_NAME_LEN 6		/* ditto for *NIX */
48246074Sgabor#endif
49246074Sgabor
50246074Sgabor#define BUFSIZE 8192
51246074Sgabor
52246074Sgabor/* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
53246074Sgabor
54246074Sgaborstruct ar_hdr *
55246074Sgabor  bfd_special_undocumented_glue PARAMS ((bfd * abfd, char *filename));
56246074Sgabor
57246074Sgabor/* Static declarations */
58246074Sgabor
59246074Sgaborstatic void
60246074Sgabormri_emul PARAMS ((void));
61246074Sgabor
62246074Sgaborstatic const char *
63246074Sgabornormalize PARAMS ((const char *, bfd *));
64246074Sgabor
65246074Sgaborstatic void
66246074Sgaborremove_output PARAMS ((void));
67246074Sgabor
68246074Sgaborstatic void
69246074Sgabormap_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int));
70246074Sgabor
71246074Sgaborstatic void
72246074Sgaborprint_contents PARAMS ((bfd * member));
73246074Sgabor
74246074Sgaborstatic void
75246074Sgabordelete_members PARAMS ((bfd *, char **files_to_delete));
76246074Sgabor
77246074Sgabor#if 0
78246074Sgaborstatic void
79246074Sgabordo_quick_append PARAMS ((const char *archive_filename,
80246074Sgabor			 char **files_to_append));
81246074Sgabor#endif
82246074Sgabor
83246074Sgaborstatic void
84246074Sgabormove_members PARAMS ((bfd *, char **files_to_move));
85246074Sgabor
86246074Sgaborstatic void
87246074Sgaborreplace_members PARAMS ((bfd *, char **files_to_replace, boolean quick));
88246074Sgabor
89246074Sgaborstatic void
90246074Sgaborprint_descr PARAMS ((bfd * abfd));
91246074Sgabor
92246074Sgaborstatic void
93246074Sgaborwrite_archive PARAMS ((bfd *));
94246074Sgabor
95246074Sgaborstatic void
96246074Sgaborranlib_only PARAMS ((const char *archname));
97246074Sgabor
98246074Sgaborstatic void
99287223Sdelphijranlib_touch PARAMS ((const char *archname));
100246074Sgabor
101246074Sgaborstatic void
102246074Sgaborusage PARAMS ((int));
103246074Sgabor
104246074Sgabor/** Globals and flags */
105246074Sgabor
106246074Sgaborint mri_mode;
107246074Sgabor
108246074Sgabor/* This flag distinguishes between ar and ranlib:
109246074Sgabor   1 means this is 'ranlib'; 0 means this is 'ar'.
110246074Sgabor   -1 means if we should use argv[0] to decide.  */
111246074Sgaborextern int is_ranlib;
112246074Sgabor
113246074Sgabor/* Nonzero means don't warn about creating the archive file if necessary.  */
114246074Sgaborint silent_create = 0;
115246074Sgabor
116246074Sgabor/* Nonzero means describe each action performed.  */
117246074Sgaborint verbose = 0;
118246074Sgabor
119246074Sgabor/* Nonzero means preserve dates of members when extracting them.  */
120246074Sgaborint preserve_dates = 0;
121246074Sgabor
122246074Sgabor/* Nonzero means don't replace existing members whose dates are more recent
123246074Sgabor   than the corresponding files.  */
124246074Sgaborint newer_only = 0;
125246074Sgabor
126246074Sgabor/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
127246074Sgabor   member).  -1 means we've been explicitly asked to not write a symbol table;
128246074Sgabor   +1 means we've been explictly asked to write it;
129246074Sgabor   0 is the default.
130246074Sgabor   Traditionally, the default in BSD has been to not write the table.
131246074Sgabor   However, for POSIX.2 compliance the default is now to write a symbol table
132246074Sgabor   if any of the members are object files.  */
133246074Sgaborint write_armap = 0;
134246074Sgabor
135246074Sgabor/* Nonzero means it's the name of an existing member; position new or moved
136246074Sgabor   files with respect to this one.  */
137246074Sgaborchar *posname = NULL;
138246074Sgabor
139246074Sgabor/* Sez how to use `posname': pos_before means position before that member.
140246074Sgabor   pos_after means position after that member. pos_end means always at end.
141246074Sgabor   pos_default means default appropriately. For the latter two, `posname'
142246074Sgabor   should also be zero.  */
143246074Sgaborenum pos
144246074Sgabor  {
145246074Sgabor    pos_default, pos_before, pos_after, pos_end
146246074Sgabor  } postype = pos_default;
147246074Sgabor
148246074Sgaborstatic bfd **
149246074Sgaborget_pos_bfd PARAMS ((bfd **, enum pos));
150246074Sgabor
151246074Sgabor/* Whether to truncate names of files stored in the archive.  */
152246074Sgaborstatic boolean ar_truncate = false;
153246074Sgabor
154246074Sgaborint interactive = 0;
155246074Sgabor
156246074Sgaborstatic void
157246074Sgabormri_emul ()
158246074Sgabor{
159246074Sgabor  interactive = isatty (fileno (stdin));
160246074Sgabor  yyparse ();
161246074Sgabor}
162246074Sgabor
163246074Sgabor/* If COUNT is 0, then FUNCTION is called once on each entry.  If nonzero,
164246074Sgabor   COUNT is the length of the FILES chain; FUNCTION is called on each entry
165246074Sgabor   whose name matches one in FILES.  */
166246074Sgabor
167246074Sgaborstatic void
168246074Sgabormap_over_members (arch, function, files, count)
169246074Sgabor     bfd *arch;
170246074Sgabor     void (*function) PARAMS ((bfd *));
171246074Sgabor     char **files;
172246074Sgabor     int count;
173246074Sgabor{
174246074Sgabor  bfd *head;
175246074Sgabor
176246074Sgabor  if (count == 0)
177246074Sgabor    {
178246074Sgabor      for (head = arch->next; head; head = head->next)
179246074Sgabor	{
180246074Sgabor	  PROGRESS (1);
181246074Sgabor	  function (head);
182246074Sgabor	}
183246074Sgabor      return;
184246074Sgabor    }
185246074Sgabor  /* This may appear to be a baroque way of accomplishing what we want.
186246074Sgabor     However we have to iterate over the filenames in order to notice where
187246074Sgabor     a filename is requested but does not exist in the archive.  Ditto
188246074Sgabor     mapping over each file each time -- we want to hack multiple
189246074Sgabor     references.  */
190246074Sgabor
191246074Sgabor  for (; count > 0; files++, count--)
192246074Sgabor    {
193246074Sgabor      boolean found = false;
194246074Sgabor
195246074Sgabor      for (head = arch->next; head; head = head->next)
196246074Sgabor	{
197246074Sgabor	  PROGRESS (1);
198246074Sgabor	  if (head->filename == NULL)
199246074Sgabor	    {
200246074Sgabor	      /* Some archive formats don't get the filenames filled in
201246074Sgabor		 until the elements are opened.  */
202246074Sgabor	      struct stat buf;
203246074Sgabor	      bfd_stat_arch_elt (head, &buf);
204246074Sgabor	    }
205276807Spfg	  if ((head->filename != NULL) &&
206276807Spfg	      (!strcmp (*files, head->filename)))
207276807Spfg	    {
208276807Spfg	      found = true;
209276807Spfg	      function (head);
210276807Spfg	    }
211276807Spfg	}
212276807Spfg      if (!found)
213276807Spfg	fprintf (stderr, "no entry %s in archive\n", *files);
214276807Spfg    }
215276807Spfg}
216276807Spfg
217276807Spfgboolean operation_alters_arch = false;
218276807Spfg
219276807Spfgstatic void
220276807Spfgusage (help)
221246074Sgabor     int help;
222246074Sgabor{
223246074Sgabor  FILE *s;
224246074Sgabor
225246074Sgabor  s = help ? stdout : stderr;
226246074Sgabor  if (! is_ranlib)
227246074Sgabor    fprintf (s, "\
228246074SgaborUsage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\
229246091Sdelphij       %s -M [<mri-script]\n",
230246074Sgabor	     program_name, program_name);
231246091Sdelphij  else
232246074Sgabor    fprintf (s, "\
233246074SgaborUsage: %s [-vV] archive\n", program_name);
234246074Sgabor
235246074Sgabor  list_supported_targets (program_name, stderr);
236246074Sgabor
237246074Sgabor  if (help)
238246074Sgabor    fprintf (s, "Report bugs to bug-gnu-utils@prep.ai.mit.edu\n");
239246074Sgabor
240246074Sgabor  xexit (help ? 0 : 1);
241246074Sgabor}
242246074Sgabor
243246074Sgabor/* Normalize a file name specified on the command line into a file
244246074Sgabor   name which we will use in an archive.  */
245246074Sgabor
246246074Sgaborstatic const char *
247246074Sgabornormalize (file, abfd)
248246074Sgabor     const char *file;
249246074Sgabor     bfd *abfd;
250246074Sgabor{
251246074Sgabor  const char *filename;
252246074Sgabor
253246074Sgabor  filename = strrchr (file, '/');
254246074Sgabor  if (filename != (char *) NULL)
255246074Sgabor    filename++;
256246074Sgabor  else
257246074Sgabor    filename = file;
258246074Sgabor
259246074Sgabor  if (ar_truncate
260246074Sgabor      && abfd != NULL
261246074Sgabor      && strlen (filename) > abfd->xvec->ar_max_namelen)
262246074Sgabor    {
263246074Sgabor      char *s;
264246074Sgabor
265246074Sgabor      /* Space leak.  */
266246074Sgabor      s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
267246074Sgabor      memcpy (s, filename, abfd->xvec->ar_max_namelen);
268246074Sgabor      s[abfd->xvec->ar_max_namelen] = '\0';
269246074Sgabor      filename = s;
270246074Sgabor    }
271246074Sgabor
272246074Sgabor  return filename;
273246074Sgabor}
274246074Sgabor
275246074Sgabor/* Remove any output file.  This is only called via xatexit.  */
276246074Sgabor
277246074Sgaborstatic char *output_filename = NULL;
278246074Sgaborstatic FILE *output_file = NULL;
279246074Sgaborstatic bfd *output_bfd = NULL;
280246074Sgabor
281246074Sgaborstatic void
282246074Sgaborremove_output ()
283246074Sgabor{
284246074Sgabor  if (output_filename != NULL)
285246074Sgabor    {
286246074Sgabor      if (output_bfd != NULL && output_bfd->iostream != NULL)
287246074Sgabor	fclose ((FILE *) (output_bfd->iostream));
288246074Sgabor      if (output_file != NULL)
289246074Sgabor	fclose (output_file);
290246074Sgabor      unlink (output_filename);
291246074Sgabor    }
292246074Sgabor}
293246074Sgabor
294246074Sgabor/* The option parsing should be in its own function.
295246074Sgabor   It will be when I have getopt working.  */
296246074Sgabor
297246074Sgaborint
298246074Sgabormain (argc, argv)
299246074Sgabor     int argc;
300246074Sgabor     char **argv;
301246074Sgabor{
302246074Sgabor  char *arg_ptr;
303246074Sgabor  char c;
304246074Sgabor  enum
305246074Sgabor    {
306246074Sgabor      none = 0, delete, replace, print_table,
307246074Sgabor      print_files, extract, move, quick_append
308246074Sgabor    } operation = none;
309246074Sgabor  int arg_index;
310246074Sgabor  char **files;
311246074Sgabor  char *inarch_filename;
312246074Sgabor  int show_version;
313246074Sgabor
314246074Sgabor  program_name = argv[0];
315246074Sgabor  xmalloc_set_program_name (program_name);
316246074Sgabor
317246074Sgabor  if (is_ranlib < 0)
318246074Sgabor    {
319246074Sgabor      char *temp;
320246074Sgabor
321246074Sgabor      temp = strrchr (program_name, '/');
322246074Sgabor      if (temp == NULL)
323246074Sgabor	temp = program_name;
324246074Sgabor      else
325246074Sgabor	++temp;
326246074Sgabor      if (strlen (temp) >= 6
327246074Sgabor	  && strcmp (temp + strlen (temp) - 6, "ranlib") == 0)
328246074Sgabor	is_ranlib = 1;
329246074Sgabor      else
330246074Sgabor	is_ranlib = 0;
331246074Sgabor    }
332246074Sgabor
333246074Sgabor  if (argc > 1 && argv[1][0] == '-')
334246074Sgabor    {
335246074Sgabor      if (strcmp (argv[1], "--help") == 0)
336246074Sgabor	usage (1);
337246074Sgabor      else if (strcmp (argv[1], "--version") == 0)
338246074Sgabor	{
339246074Sgabor	  if (is_ranlib)
340246074Sgabor	    print_version ("ranlib");
341246074Sgabor	  else
342246074Sgabor	    print_version ("ar");
343246074Sgabor	}
344246074Sgabor    }
345246074Sgabor
346246074Sgabor  START_PROGRESS (program_name, 0);
347246074Sgabor
348246074Sgabor  bfd_init ();
349246074Sgabor  set_default_bfd_target ();
350246074Sgabor
351246074Sgabor  show_version = 0;
352246074Sgabor
353246074Sgabor  xatexit (remove_output);
354246074Sgabor
355246074Sgabor  if (is_ranlib)
356246074Sgabor    {
357246074Sgabor      boolean touch = false;
358246074Sgabor
359246074Sgabor      if (argc < 2 || strcmp (argv[1], "--help") == 0)
360246074Sgabor	usage (0);
361246074Sgabor      if (strcmp (argv[1], "-V") == 0
362246074Sgabor	  || strcmp (argv[1], "-v") == 0
363246074Sgabor	  || strncmp (argv[1], "--v", 3) == 0)
364246074Sgabor	print_version ("ranlib");
365246074Sgabor      arg_index = 1;
366246074Sgabor      if (strcmp (argv[1], "-t") == 0)
367246074Sgabor	{
368246074Sgabor	  ++arg_index;
369246074Sgabor	  touch = true;
370246074Sgabor	}
371246074Sgabor      while (arg_index < argc)
372246074Sgabor	{
373246074Sgabor	  if (! touch)
374246074Sgabor	    ranlib_only (argv[arg_index]);
375246074Sgabor	  else
376246074Sgabor	    ranlib_touch (argv[arg_index]);
377246074Sgabor	  ++arg_index;
378246074Sgabor	}
379246074Sgabor      xexit (0);
380246074Sgabor    }
381246074Sgabor
382246074Sgabor  if (argc == 2 && strcmp (argv[1], "-M") == 0)
383246074Sgabor    {
384246074Sgabor      mri_emul ();
385246074Sgabor      xexit (0);
386246074Sgabor    }
387246074Sgabor
388246074Sgabor  if (argc < 2)
389246074Sgabor    usage (0);
390246074Sgabor
391246074Sgabor  arg_ptr = argv[1];
392246074Sgabor
393246074Sgabor  if (*arg_ptr == '-')
394246074Sgabor    ++arg_ptr;			/* compatibility */
395246074Sgabor
396246074Sgabor  while ((c = *arg_ptr++) != '\0')
397246074Sgabor    {
398246074Sgabor      switch (c)
399246074Sgabor	{
400246074Sgabor	case 'd':
401246074Sgabor	case 'm':
402246074Sgabor	case 'p':
403246074Sgabor	case 'q':
404246074Sgabor	case 'r':
405246074Sgabor	case 't':
406246074Sgabor	case 'x':
407246074Sgabor	  if (operation != none)
408246074Sgabor	    fatal ("two different operation options specified");
409287223Sdelphij	  switch (c)
410246074Sgabor	    {
411246074Sgabor	    case 'd':
412246074Sgabor	      operation = delete;
413246074Sgabor	      operation_alters_arch = true;
414246074Sgabor	      break;
415246074Sgabor	    case 'm':
416246074Sgabor	      operation = move;
417246074Sgabor	      operation_alters_arch = true;
418246074Sgabor	      break;
419246074Sgabor	    case 'p':
420246074Sgabor	      operation = print_files;
421246074Sgabor	      break;
422246074Sgabor	    case 'q':
423246074Sgabor	      operation = quick_append;
424246074Sgabor	      operation_alters_arch = true;
425246074Sgabor	      break;
426246074Sgabor	    case 'r':
427246074Sgabor	      operation = replace;
428246074Sgabor	      operation_alters_arch = true;
429246074Sgabor	      break;
430246074Sgabor	    case 't':
431276706Spfg	      operation = print_table;
432246074Sgabor	      break;
433246074Sgabor	    case 'x':
434246074Sgabor	      operation = extract;
435246074Sgabor	      break;
436246074Sgabor	    }
437246074Sgabor	case 'l':
438246074Sgabor	  break;
439246074Sgabor	case 'c':
440246074Sgabor	  silent_create = 1;
441246074Sgabor	  break;
442246074Sgabor	case 'o':
443246074Sgabor	  preserve_dates = 1;
444246074Sgabor	  break;
445246074Sgabor	case 'V':
446246074Sgabor	  show_version = true;
447246074Sgabor	  break;
448246074Sgabor	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