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