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