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