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