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