* ar.c: added "b" to fopens for dos
[deliverable/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 <stdio.h>
33 #include <sys/time.h>
34 #include <errno.h>
35 #define BUFSIZE 8192
36 /* PROTO (void, open_inarch, (char *archive_filename)); */
37 #ifdef __STDC__
38 static void open_inarch(char *archive_filename);
39 #else
40 static void open_inarch();
41 #endif /* __STDC__ */
42
43 PROTO(void, map_over_members, (void (*function) (), char **files, int count));
44 PROTO(void, print_contents, (bfd * member));
45 PROTO(void, extract_file, (bfd * abfd));
46 PROTO(void, delete_members, (char **files_to_delete));
47 PROTO(void, do_quick_append, (char *archive_filename, char **files_to_append));
48 PROTO(void, move_members, (char **files_to_move));
49 PROTO(void, replace_members, (char **files_to_replace));
50 PROTO(void, print_descr, (bfd * abfd));
51 PROTO(void, ranlib_only, (char *archname));
52
53 /** Globals and flags */
54
55 char *program_name = NULL;
56 bfd bogus_archive;
57 bfd *inarch; /* The input arch we're manipulating */
58
59 /* This flag distinguishes between ar and ranlib:
60 1 means this is 'ranlib'; 0 means this is 'ar'.
61 -1 means if we should use argv[0] to decide. */
62 extern int is_ranlib;
63 /* Nonzero means don't warn about creating the archive file if necessary. */
64 int silent_create = 0;
65 /* Nonzero means describe each action performed. */
66 int verbose = 0;
67 /* Nonzero means preserve dates of members when extracting them. */
68 int preserve_dates = 0;
69 /*
70 Nonzero means don't replace existing members whose dates are more recent
71 than the corresponding files.
72 */
73 int newer_only = 0;
74 /* write a __.SYMDEF member into the modified archive. */
75 boolean write_armap = false;
76 /*
77 Nonzero means don't update __.SYMDEF unless command line explicitly
78 requested it
79 */
80 int 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 */
85 char *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 */
92 enum pos {
93 pos_default, pos_before, pos_after, pos_end
94 } postype = pos_default;
95
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
117
118 boolean operation_alters_arch = false;
119
120 /*
121 The option parsing should be in its own function. It will be when I have
122 getopt working.
123 */
124 int
125 main(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;
139
140 bfd_init();
141
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];
148
149 temp = strrchr(program_name, '/');
150 if (temp == (char *) NULL)
151 temp = program_name; /* shouldn't happen, but... */
152 else
153 ++temp;
154 if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
155 if (argc < 2)
156 bfd_fatal("Too few command arguments.");
157 ranlib_only(argv[1]);
158 }
159
160
161 if (argc < 3)
162 bfd_fatal("Too few command arguments.");
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;
183 operation_alters_arch = true;
184 break;
185 case 'm':
186 operation = move;
187 operation_alters_arch = true;
188 break;
189 case 'p':
190 operation = print_files;
191 break;
192 case 'q':
193 operation = quick_append;
194 operation_alters_arch = true;
195 break;
196 case 'r':
197 operation = replace;
198 operation_alters_arch = true;
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
238 if ((operation == none || operation == print_table)
239 && write_armap == true)
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 */
277 #if 0
278 if (operation == replace && inarch == &bogus_archive) {
279 silent_create = 1;
280 do_quick_append(inarch_filename, 0);
281 open_inarch(inarch_filename);
282 }
283 #endif
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
321 static
322 char *normalize(file)
323 char *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
335 static void
336 open_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);
346 if (!operation_alters_arch) {
347 fprintf (stderr, "%s: %s not found.\n", program_name,
348 archive_filename);
349 exit (1);
350 }
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 {
361 #ifdef GNU960
362 inarch = bfd_openr(archive_filename, default_target);
363 #else
364 inarch = bfd_openr(archive_filename, NULL);
365 #endif
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);
374 #ifdef GNU960
375 gnu960_verify_target(inarch); /* Exits on failure */
376 #endif
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 */
398 void
399 map_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
436 void
437 print_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
473 We 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
482 void
483 extract_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;
503 if (size == 0) {
504 /* Seems like an abstraction violation, eh? Well it's OK! */
505 ostream = fopen(abfd->filename, "wb");
506 if (!ostream) {
507 perror(abfd->filename);
508 exit(1);
509 }
510 } else
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! */
523 ostream = fopen(abfd->filename, "wb");
524 if (!ostream) {
525 perror(abfd->filename);
526 exit(1);
527 }
528 }
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
558 PROTO(struct ar_hdr *, bfd_special_undocumented_glue, (bfd *abfd, char *filename));
559
560 void
561 do_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
583 ofile = fopen(archive_filename, "a+b");
584 if (ofile == NULL) {
585 perror(program_name);
586 exit(1);
587 }
588
589 /* bletch */
590 #ifdef GNU960
591 temp = bfd_openr(archive_filename, default_target);
592 #else
593 temp = bfd_openr(archive_filename, NULL);
594 #endif
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);
602 #ifdef GNU960
603 gnu960_verify_target(temp); /* Exits on failure */
604 #endif
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) {
616 struct ar_hdr *hdr = bfd_special_undocumented_glue(temp, *files_to_append);
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
624 ifile = fopen(*files_to_append, "rb");
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
654 void
655 write_archive()
656 {
657 bfd *obfd;
658 int namelen = strlen(inarch->filename);
659 char *new_name = xmalloc(namelen + 6);
660 bfd *contents_head = inarch->next;
661 #if 0
662 if (inarch == &bogus_archive) {
663 /* How can this be ? */
664 return;
665 }
666 else {
667 #endif
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 #if 0
693 }
694 #endif
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
705 bfd **
706 get_pos_bfd(contents, default_pos)
707 bfd **contents;
708 enum pos default_pos;
709 {
710 bfd **after_bfd = contents;
711 enum pos realpos = (postype == pos_default ? default_pos : postype);
712
713 if (realpos == pos_end) {
714 while (*after_bfd)
715 after_bfd = &((*after_bfd)->next);
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;
722 break;
723 }
724 }
725 return after_bfd;
726 }
727
728
729 void
730 delete_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 }
770 next_file:;
771
772 }
773
774 if (something_changed == true) {
775 write_archive();
776 }
777 }
778
779
780 /* Reposition existing members within an archive */
781
782 void
783 move_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);
818 next_file:;
819 }
820
821 write_archive();
822 }
823
824
825 /* Ought to default to replacing in place, but this is existing practice! */
826
827 void
828 replace_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)) {
851 if (newer_only) {
852 struct stat fsbuf,
853 asbuf;
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
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
874 /* snip out this entry from the chain */
875 *current_ptr = current->next;
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 }
884 #ifdef GNU960
885 gnu960_verify_target(*after_bfd); /* Exits on failure */
886 #endif
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 }
907 #ifdef GNU960
908 gnu960_verify_target(*after_bfd); /* Exits on failure */
909 #endif
910 if (verbose) {
911 printf("c - %s\n", *files_to_move);
912 }
913
914 (*after_bfd)->next = temp;
915
916 next_file:;
917
918 files_to_move++;
919 }
920
921
922 write_archive();
923 }
924
925 void
926 ranlib_only(archname)
927 char *archname;
928 {
929 write_armap = true;
930 open_inarch(archname);
931 write_archive();
932 exit(0);
933 }
934
935
936
937 /* Things which are interesting to map over all or some of the files: */
938
939 void
940 print_descr(abfd)
941 bfd *abfd;
942 {
943 print_arelt_descr(abfd, verbose);
944 }
This page took 0.04936 seconds and 5 git commands to generate.