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