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