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