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