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