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