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