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