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