This commit was generated by cvs2svn to track changes on a CVS vendor
[deliverable/binutils-gdb.git] / binutils / ar.c
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 \f
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 \f
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 \f
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 expandargv (&argc, &argv);
366
367 if (is_ranlib < 0)
368 {
369 char *temp;
370
371 temp = strrchr (program_name, '/');
372 #ifdef HAVE_DOS_BASED_FILE_SYSTEM
373 {
374 /* We could have foo/bar\\baz, or foo\\bar, or d:bar. */
375 char *bslash = strrchr (program_name, '\\');
376 if (temp == NULL || (bslash != NULL && bslash > temp))
377 temp = bslash;
378 if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
379 temp = program_name + 1;
380 }
381 #endif
382 if (temp == NULL)
383 temp = program_name;
384 else
385 ++temp;
386 if (strlen (temp) >= 6
387 && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
388 is_ranlib = 1;
389 else
390 is_ranlib = 0;
391 }
392
393 if (argc > 1 && argv[1][0] == '-')
394 {
395 if (strcmp (argv[1], "--help") == 0)
396 usage (1);
397 else if (strcmp (argv[1], "--version") == 0)
398 {
399 if (is_ranlib)
400 print_version ("ranlib");
401 else
402 print_version ("ar");
403 }
404 }
405
406 START_PROGRESS (program_name, 0);
407
408 bfd_init ();
409 set_default_bfd_target ();
410
411 show_version = 0;
412
413 xatexit (remove_output);
414
415 for (i = 1; i < argc; i++)
416 if (! ar_emul_parse_arg (argv[i]))
417 break;
418 argv += (i - 1);
419 argc -= (i - 1);
420
421 if (is_ranlib)
422 {
423 bfd_boolean touch = FALSE;
424
425 if (argc < 2
426 || strcmp (argv[1], "--help") == 0
427 || strcmp (argv[1], "-h") == 0
428 || strcmp (argv[1], "-H") == 0)
429 usage (0);
430 if (strcmp (argv[1], "-V") == 0
431 || strcmp (argv[1], "-v") == 0
432 || strncmp (argv[1], "--v", 3) == 0)
433 print_version ("ranlib");
434 arg_index = 1;
435 if (strcmp (argv[1], "-t") == 0)
436 {
437 ++arg_index;
438 touch = TRUE;
439 }
440 while (arg_index < argc)
441 {
442 if (! touch)
443 ranlib_only (argv[arg_index]);
444 else
445 ranlib_touch (argv[arg_index]);
446 ++arg_index;
447 }
448 xexit (0);
449 }
450
451 if (argc == 2 && strcmp (argv[1], "-M") == 0)
452 {
453 mri_emul ();
454 xexit (0);
455 }
456
457 if (argc < 2)
458 usage (0);
459
460 arg_index = 1;
461 arg_ptr = argv[arg_index];
462
463 if (*arg_ptr == '-')
464 {
465 /* When the first option starts with '-' we support POSIX-compatible
466 option parsing. */
467 do_posix = 1;
468 ++arg_ptr; /* compatibility */
469 }
470
471 do
472 {
473 while ((c = *arg_ptr++) != '\0')
474 {
475 switch (c)
476 {
477 case 'd':
478 case 'm':
479 case 'p':
480 case 'q':
481 case 'r':
482 case 't':
483 case 'x':
484 if (operation != none)
485 fatal (_("two different operation options specified"));
486 switch (c)
487 {
488 case 'd':
489 operation = delete;
490 operation_alters_arch = TRUE;
491 break;
492 case 'm':
493 operation = move;
494 operation_alters_arch = TRUE;
495 break;
496 case 'p':
497 operation = print_files;
498 break;
499 case 'q':
500 operation = quick_append;
501 operation_alters_arch = TRUE;
502 break;
503 case 'r':
504 operation = replace;
505 operation_alters_arch = TRUE;
506 break;
507 case 't':
508 operation = print_table;
509 break;
510 case 'x':
511 operation = extract;
512 break;
513 }
514 case 'l':
515 break;
516 case 'c':
517 silent_create = 1;
518 break;
519 case 'o':
520 preserve_dates = 1;
521 break;
522 case 'V':
523 show_version = TRUE;
524 break;
525 case 's':
526 write_armap = 1;
527 break;
528 case 'S':
529 write_armap = -1;
530 break;
531 case 'u':
532 newer_only = 1;
533 break;
534 case 'v':
535 verbose = 1;
536 break;
537 case 'a':
538 postype = pos_after;
539 break;
540 case 'b':
541 postype = pos_before;
542 break;
543 case 'i':
544 postype = pos_before;
545 break;
546 case 'M':
547 mri_mode = 1;
548 break;
549 case 'N':
550 counted_name_mode = TRUE;
551 break;
552 case 'f':
553 ar_truncate = TRUE;
554 break;
555 case 'P':
556 full_pathname = TRUE;
557 break;
558 default:
559 /* xgettext:c-format */
560 non_fatal (_("illegal option -- %c"), c);
561 usage (0);
562 }
563 }
564
565 /* With POSIX-compatible option parsing continue with the next
566 argument if it starts with '-'. */
567 if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
568 arg_ptr = argv[++arg_index] + 1;
569 else
570 do_posix = 0;
571 }
572 while (do_posix);
573
574 if (show_version)
575 print_version ("ar");
576
577 ++arg_index;
578 if (arg_index >= argc)
579 usage (0);
580
581 if (mri_mode)
582 {
583 mri_emul ();
584 }
585 else
586 {
587 bfd *arch;
588
589 /* We don't use do_quick_append any more. Too many systems
590 expect ar to always rebuild the symbol table even when q is
591 used. */
592
593 /* We can't write an armap when using ar q, so just do ar r
594 instead. */
595 if (operation == quick_append && write_armap)
596 operation = replace;
597
598 if ((operation == none || operation == print_table)
599 && write_armap == 1)
600 {
601 ranlib_only (argv[arg_index]);
602 xexit (0);
603 }
604
605 if (operation == none)
606 fatal (_("no operation specified"));
607
608 if (newer_only && operation != replace)
609 fatal (_("`u' is only meaningful with the `r' option."));
610
611 if (postype != pos_default)
612 posname = argv[arg_index++];
613
614 if (counted_name_mode)
615 {
616 if (operation != extract && operation != delete)
617 fatal (_("`N' is only meaningful with the `x' and `d' options."));
618 counted_name_counter = atoi (argv[arg_index++]);
619 if (counted_name_counter <= 0)
620 fatal (_("Value for `N' must be positive."));
621 }
622
623 inarch_filename = argv[arg_index++];
624
625 files = arg_index < argc ? argv + arg_index : NULL;
626 file_count = argc - arg_index;
627
628 arch = open_inarch (inarch_filename,
629 files == NULL ? (char *) NULL : files[0]);
630
631 switch (operation)
632 {
633 case print_table:
634 map_over_members (arch, print_descr, files, file_count);
635 break;
636
637 case print_files:
638 map_over_members (arch, print_contents, files, file_count);
639 break;
640
641 case extract:
642 map_over_members (arch, extract_file, files, file_count);
643 break;
644
645 case delete:
646 if (files != NULL)
647 delete_members (arch, files);
648 else
649 output_filename = NULL;
650 break;
651
652 case move:
653 if (files != NULL)
654 move_members (arch, files);
655 else
656 output_filename = NULL;
657 break;
658
659 case replace:
660 case quick_append:
661 if (files != NULL || write_armap > 0)
662 replace_members (arch, files, operation == quick_append);
663 else
664 output_filename = NULL;
665 break;
666
667 /* Shouldn't happen! */
668 default:
669 /* xgettext:c-format */
670 fatal (_("internal error -- this option not implemented"));
671 }
672 }
673
674 END_PROGRESS (program_name);
675
676 xexit (0);
677 return 0;
678 }
679
680 bfd *
681 open_inarch (const char *archive_filename, const char *file)
682 {
683 const char *target;
684 bfd **last_one;
685 bfd *next_one;
686 struct stat sbuf;
687 bfd *arch;
688 char **matching;
689
690 bfd_set_error (bfd_error_no_error);
691
692 target = NULL;
693
694 if (stat (archive_filename, &sbuf) != 0)
695 {
696 #if !defined(__GO32__) || defined(__DJGPP__)
697
698 /* FIXME: I don't understand why this fragment was ifndef'ed
699 away for __GO32__; perhaps it was in the days of DJGPP v1.x.
700 stat() works just fine in v2.x, so I think this should be
701 removed. For now, I enable it for DJGPP v2. -- EZ. */
702
703 /* KLUDGE ALERT! Temporary fix until I figger why
704 stat() is wrong ... think it's buried in GO32's IDT - Jax */
705 if (errno != ENOENT)
706 bfd_fatal (archive_filename);
707 #endif
708
709 if (!operation_alters_arch)
710 {
711 fprintf (stderr, "%s: ", program_name);
712 perror (archive_filename);
713 maybequit ();
714 return NULL;
715 }
716
717 /* Try to figure out the target to use for the archive from the
718 first object on the list. */
719 if (file != NULL)
720 {
721 bfd *obj;
722
723 obj = bfd_openr (file, NULL);
724 if (obj != NULL)
725 {
726 if (bfd_check_format (obj, bfd_object))
727 target = bfd_get_target (obj);
728 (void) bfd_close (obj);
729 }
730 }
731
732 /* Create an empty archive. */
733 arch = bfd_openw (archive_filename, target);
734 if (arch == NULL
735 || ! bfd_set_format (arch, bfd_archive)
736 || ! bfd_close (arch))
737 bfd_fatal (archive_filename);
738 else if (!silent_create)
739 non_fatal (_("creating %s"), archive_filename);
740
741 /* If we die creating a new archive, don't leave it around. */
742 output_filename = archive_filename;
743 }
744
745 arch = bfd_openr (archive_filename, target);
746 if (arch == NULL)
747 {
748 bloser:
749 bfd_fatal (archive_filename);
750 }
751
752 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
753 {
754 bfd_nonfatal (archive_filename);
755 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
756 {
757 list_matching_formats (matching);
758 free (matching);
759 }
760 xexit (1);
761 }
762
763 last_one = &(arch->next);
764 /* Read all the contents right away, regardless. */
765 for (next_one = bfd_openr_next_archived_file (arch, NULL);
766 next_one;
767 next_one = bfd_openr_next_archived_file (arch, next_one))
768 {
769 PROGRESS (1);
770 *last_one = next_one;
771 last_one = &next_one->next;
772 }
773 *last_one = (bfd *) NULL;
774 if (bfd_get_error () != bfd_error_no_more_archived_files)
775 goto bloser;
776 return arch;
777 }
778
779 static void
780 print_contents (bfd *abfd)
781 {
782 int ncopied = 0;
783 char *cbuf = xmalloc (BUFSIZE);
784 struct stat buf;
785 long size;
786 if (bfd_stat_arch_elt (abfd, &buf) != 0)
787 /* xgettext:c-format */
788 fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
789
790 if (verbose)
791 /* xgettext:c-format */
792 printf (_("\n<%s>\n\n"), bfd_get_filename (abfd));
793
794 bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
795
796 size = buf.st_size;
797 while (ncopied < size)
798 {
799
800 int nread;
801 int tocopy = size - ncopied;
802 if (tocopy > BUFSIZE)
803 tocopy = BUFSIZE;
804
805 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
806 if (nread != tocopy)
807 /* xgettext:c-format */
808 fatal (_("%s is not a valid archive"),
809 bfd_get_filename (bfd_my_archive (abfd)));
810 fwrite (cbuf, 1, nread, stdout);
811 ncopied += tocopy;
812 }
813 free (cbuf);
814 }
815
816 /* Extract a member of the archive into its own file.
817
818 We defer opening the new file until after we have read a BUFSIZ chunk of the
819 old one, since we know we have just read the archive header for the old
820 one. Since most members are shorter than BUFSIZ, this means we will read
821 the old header, read the old data, write a new inode for the new file, and
822 write the new data, and be done. This 'optimization' is what comes from
823 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
824 Gilmore */
825
826 void
827 extract_file (bfd *abfd)
828 {
829 FILE *ostream;
830 char *cbuf = xmalloc (BUFSIZE);
831 int nread, tocopy;
832 long ncopied = 0;
833 long size;
834 struct stat buf;
835
836 if (bfd_stat_arch_elt (abfd, &buf) != 0)
837 /* xgettext:c-format */
838 fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
839 size = buf.st_size;
840
841 if (size < 0)
842 /* xgettext:c-format */
843 fatal (_("stat returns negative size for %s"), bfd_get_filename (abfd));
844
845 if (verbose)
846 printf ("x - %s\n", bfd_get_filename (abfd));
847
848 bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
849
850 ostream = NULL;
851 if (size == 0)
852 {
853 /* Seems like an abstraction violation, eh? Well it's OK! */
854 output_filename = bfd_get_filename (abfd);
855
856 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
857 if (ostream == NULL)
858 {
859 perror (bfd_get_filename (abfd));
860 xexit (1);
861 }
862
863 output_file = ostream;
864 }
865 else
866 while (ncopied < size)
867 {
868 tocopy = size - ncopied;
869 if (tocopy > BUFSIZE)
870 tocopy = BUFSIZE;
871
872 nread = bfd_bread (cbuf, (bfd_size_type) tocopy, abfd);
873 if (nread != tocopy)
874 /* xgettext:c-format */
875 fatal (_("%s is not a valid archive"),
876 bfd_get_filename (bfd_my_archive (abfd)));
877
878 /* See comment above; this saves disk arm motion */
879 if (ostream == NULL)
880 {
881 /* Seems like an abstraction violation, eh? Well it's OK! */
882 output_filename = bfd_get_filename (abfd);
883
884 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
885 if (ostream == NULL)
886 {
887 perror (bfd_get_filename (abfd));
888 xexit (1);
889 }
890
891 output_file = ostream;
892 }
893 fwrite (cbuf, 1, nread, ostream);
894 ncopied += tocopy;
895 }
896
897 if (ostream != NULL)
898 fclose (ostream);
899
900 output_file = NULL;
901 output_filename = NULL;
902
903 chmod (bfd_get_filename (abfd), buf.st_mode);
904
905 if (preserve_dates)
906 {
907 /* Set access time to modification time. Only st_mtime is
908 initialized by bfd_stat_arch_elt. */
909 buf.st_atime = buf.st_mtime;
910 set_times (bfd_get_filename (abfd), &buf);
911 }
912
913 free (cbuf);
914 }
915
916 static void
917 write_archive (bfd *iarch)
918 {
919 bfd *obfd;
920 char *old_name, *new_name;
921 bfd *contents_head = iarch->next;
922
923 old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
924 strcpy (old_name, bfd_get_filename (iarch));
925 new_name = make_tempname (old_name);
926
927 output_filename = new_name;
928
929 obfd = bfd_openw (new_name, bfd_get_target (iarch));
930
931 if (obfd == NULL)
932 bfd_fatal (old_name);
933
934 output_bfd = obfd;
935
936 bfd_set_format (obfd, bfd_archive);
937
938 /* Request writing the archive symbol table unless we've
939 been explicitly requested not to. */
940 obfd->has_armap = write_armap >= 0;
941
942 if (ar_truncate)
943 {
944 /* This should really use bfd_set_file_flags, but that rejects
945 archives. */
946 obfd->flags |= BFD_TRADITIONAL_FORMAT;
947 }
948
949 if (!bfd_set_archive_head (obfd, contents_head))
950 bfd_fatal (old_name);
951
952 if (!bfd_close (obfd))
953 bfd_fatal (old_name);
954
955 output_bfd = NULL;
956 output_filename = NULL;
957
958 /* We don't care if this fails; we might be creating the archive. */
959 bfd_close (iarch);
960
961 if (smart_rename (new_name, old_name, 0) != 0)
962 xexit (1);
963 }
964
965 /* Return a pointer to the pointer to the entry which should be rplacd'd
966 into when altering. DEFAULT_POS should be how to interpret pos_default,
967 and should be a pos value. */
968
969 static bfd **
970 get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
971 {
972 bfd **after_bfd = contents;
973 enum pos realpos;
974 const char *realposname;
975
976 if (postype == pos_default)
977 {
978 realpos = default_pos;
979 realposname = default_posname;
980 }
981 else
982 {
983 realpos = postype;
984 realposname = posname;
985 }
986
987 if (realpos == pos_end)
988 {
989 while (*after_bfd)
990 after_bfd = &((*after_bfd)->next);
991 }
992 else
993 {
994 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
995 if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
996 {
997 if (realpos == pos_after)
998 after_bfd = &(*after_bfd)->next;
999 break;
1000 }
1001 }
1002 return after_bfd;
1003 }
1004
1005 static void
1006 delete_members (bfd *arch, char **files_to_delete)
1007 {
1008 bfd **current_ptr_ptr;
1009 bfd_boolean found;
1010 bfd_boolean something_changed = FALSE;
1011 int match_count;
1012
1013 for (; *files_to_delete != NULL; ++files_to_delete)
1014 {
1015 /* In a.out systems, the armap is optional. It's also called
1016 __.SYMDEF. So if the user asked to delete it, we should remember
1017 that fact. This isn't quite right for COFF systems (where
1018 __.SYMDEF might be regular member), but it's very unlikely
1019 to be a problem. FIXME */
1020
1021 if (!strcmp (*files_to_delete, "__.SYMDEF"))
1022 {
1023 arch->has_armap = FALSE;
1024 write_armap = -1;
1025 continue;
1026 }
1027
1028 found = FALSE;
1029 match_count = 0;
1030 current_ptr_ptr = &(arch->next);
1031 while (*current_ptr_ptr)
1032 {
1033 if (FILENAME_CMP (normalize (*files_to_delete, arch),
1034 (*current_ptr_ptr)->filename) == 0)
1035 {
1036 ++match_count;
1037 if (counted_name_mode
1038 && match_count != counted_name_counter)
1039 {
1040 /* Counting, and didn't match on count; go on to the
1041 next one. */
1042 }
1043 else
1044 {
1045 found = TRUE;
1046 something_changed = TRUE;
1047 if (verbose)
1048 printf ("d - %s\n",
1049 *files_to_delete);
1050 *current_ptr_ptr = ((*current_ptr_ptr)->next);
1051 goto next_file;
1052 }
1053 }
1054
1055 current_ptr_ptr = &((*current_ptr_ptr)->next);
1056 }
1057
1058 if (verbose && !found)
1059 {
1060 /* xgettext:c-format */
1061 printf (_("No member named `%s'\n"), *files_to_delete);
1062 }
1063 next_file:
1064 ;
1065 }
1066
1067 if (something_changed)
1068 write_archive (arch);
1069 else
1070 output_filename = NULL;
1071 }
1072
1073
1074 /* Reposition existing members within an archive */
1075
1076 static void
1077 move_members (bfd *arch, char **files_to_move)
1078 {
1079 bfd **after_bfd; /* New entries go after this one */
1080 bfd **current_ptr_ptr; /* cdr pointer into contents */
1081
1082 for (; *files_to_move; ++files_to_move)
1083 {
1084 current_ptr_ptr = &(arch->next);
1085 while (*current_ptr_ptr)
1086 {
1087 bfd *current_ptr = *current_ptr_ptr;
1088 if (FILENAME_CMP (normalize (*files_to_move, arch),
1089 current_ptr->filename) == 0)
1090 {
1091 /* Move this file to the end of the list - first cut from
1092 where it is. */
1093 bfd *link;
1094 *current_ptr_ptr = current_ptr->next;
1095
1096 /* Now glue to end */
1097 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1098 link = *after_bfd;
1099 *after_bfd = current_ptr;
1100 current_ptr->next = link;
1101
1102 if (verbose)
1103 printf ("m - %s\n", *files_to_move);
1104
1105 goto next_file;
1106 }
1107
1108 current_ptr_ptr = &((*current_ptr_ptr)->next);
1109 }
1110 /* xgettext:c-format */
1111 fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
1112
1113 next_file:;
1114 }
1115
1116 write_archive (arch);
1117 }
1118
1119 /* Ought to default to replacing in place, but this is existing practice! */
1120
1121 static void
1122 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
1123 {
1124 bfd_boolean changed = FALSE;
1125 bfd **after_bfd; /* New entries go after this one. */
1126 bfd *current;
1127 bfd **current_ptr;
1128
1129 while (files_to_move && *files_to_move)
1130 {
1131 if (! quick)
1132 {
1133 current_ptr = &arch->next;
1134 while (*current_ptr)
1135 {
1136 current = *current_ptr;
1137
1138 /* For compatibility with existing ar programs, we
1139 permit the same file to be added multiple times. */
1140 if (FILENAME_CMP (normalize (*files_to_move, arch),
1141 normalize (current->filename, arch)) == 0
1142 && current->arelt_data != NULL)
1143 {
1144 if (newer_only)
1145 {
1146 struct stat fsbuf, asbuf;
1147
1148 if (stat (*files_to_move, &fsbuf) != 0)
1149 {
1150 if (errno != ENOENT)
1151 bfd_fatal (*files_to_move);
1152 goto next_file;
1153 }
1154 if (bfd_stat_arch_elt (current, &asbuf) != 0)
1155 /* xgettext:c-format */
1156 fatal (_("internal stat error on %s"),
1157 current->filename);
1158
1159 if (fsbuf.st_mtime <= asbuf.st_mtime)
1160 goto next_file;
1161 }
1162
1163 after_bfd = get_pos_bfd (&arch->next, pos_after,
1164 current->filename);
1165 if (ar_emul_replace (after_bfd, *files_to_move,
1166 verbose))
1167 {
1168 /* Snip out this entry from the chain. */
1169 *current_ptr = (*current_ptr)->next;
1170 changed = TRUE;
1171 }
1172
1173 goto next_file;
1174 }
1175 current_ptr = &(current->next);
1176 }
1177 }
1178
1179 /* Add to the end of the archive. */
1180 after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
1181
1182 if (ar_emul_append (after_bfd, *files_to_move, verbose))
1183 changed = TRUE;
1184
1185 next_file:;
1186
1187 files_to_move++;
1188 }
1189
1190 if (changed)
1191 write_archive (arch);
1192 else
1193 output_filename = NULL;
1194 }
1195
1196 static void
1197 ranlib_only (const char *archname)
1198 {
1199 bfd *arch;
1200
1201 if (get_file_size (archname) < 1)
1202 return;
1203 write_armap = 1;
1204 arch = open_inarch (archname, (char *) NULL);
1205 if (arch == NULL)
1206 xexit (1);
1207 write_archive (arch);
1208 }
1209
1210 /* Update the timestamp of the symbol map of an archive. */
1211
1212 static void
1213 ranlib_touch (const char *archname)
1214 {
1215 #ifdef __GO32__
1216 /* I don't think updating works on go32. */
1217 ranlib_only (archname);
1218 #else
1219 int f;
1220 bfd *arch;
1221 char **matching;
1222
1223 if (get_file_size (archname) < 1)
1224 return;
1225 f = open (archname, O_RDWR | O_BINARY, 0);
1226 if (f < 0)
1227 {
1228 bfd_set_error (bfd_error_system_call);
1229 bfd_fatal (archname);
1230 }
1231
1232 arch = bfd_fdopenr (archname, (const char *) NULL, f);
1233 if (arch == NULL)
1234 bfd_fatal (archname);
1235 if (! bfd_check_format_matches (arch, bfd_archive, &matching))
1236 {
1237 bfd_nonfatal (archname);
1238 if (bfd_get_error () == bfd_error_file_ambiguously_recognized)
1239 {
1240 list_matching_formats (matching);
1241 free (matching);
1242 }
1243 xexit (1);
1244 }
1245
1246 if (! bfd_has_map (arch))
1247 /* xgettext:c-format */
1248 fatal (_("%s: no archive map to update"), archname);
1249
1250 bfd_update_armap_timestamp (arch);
1251
1252 if (! bfd_close (arch))
1253 bfd_fatal (archname);
1254 #endif
1255 }
1256
1257 /* Things which are interesting to map over all or some of the files: */
1258
1259 static void
1260 print_descr (bfd *abfd)
1261 {
1262 print_arelt_descr (stdout, abfd, verbose);
1263 }
This page took 0.058446 seconds and 5 git commands to generate.