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