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