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