Add hyphens in usage messages.
[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 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */
50
51 struct ar_hdr *
52 bfd_special_undocumented_glue PARAMS ((bfd *abfd, char *filename));
53
54 /* Forward declarations */
55
56 static void
57 print_contents PARAMS ((bfd * member));
58
59 static void
60 delete_members PARAMS ((char **files_to_delete));
61
62 static void
63 do_quick_append PARAMS ((char *archive_filename, char **files_to_append));
64
65 static void
66 move_members PARAMS ((char **files_to_move));
67
68 static void
69 replace_members PARAMS ((char **files_to_replace));
70
71 static void
72 print_descr PARAMS ((bfd * abfd));
73
74 static void
75 ranlib_only PARAMS ((char *archname));
76
77 /** Globals and flags */
78
79 char *program_name = NULL;
80 bfd *inarch; /* The input arch we're manipulating */
81
82 int mri_mode;
83 /* This flag distinguishes between ar and ranlib:
84 1 means this is 'ranlib'; 0 means this is 'ar'.
85 -1 means if we should use argv[0] to decide. */
86 extern int is_ranlib;
87 /* Nonzero means don't warn about creating the archive file if necessary. */
88 int silent_create = 0;
89 /* Nonzero means describe each action performed. */
90 int verbose = 0;
91 /* Nonzero means preserve dates of members when extracting them. */
92 int preserve_dates = 0;
93 /*
94 Nonzero means don't replace existing members whose dates are more recent
95 than the corresponding files.
96 */
97 int newer_only = 0;
98
99 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
100 member). -1 means we've been explicitly asked to not write a symbol table;
101 +1 means we've been explictly asked to write it;
102 0 is the default.
103 Traditionally, the default in BSD has been to not write the table.
104 However, for Posix.2 compliance the default is now to write a symbol table
105 if any of the members are object files. */
106 int write_armap = 0;
107
108 /*
109 Nonzero means it's the name of an existing member; position new or moved
110 files with respect to this one.
111 */
112 char *posname = NULL;
113 /*
114 Sez how to use `posname': pos_before means position before that member.
115 pos_after means position after that member. pos_end means always at end.
116 pos_default means default appropriately. For the latter two, `posname'
117 should also be zero.
118 */
119 enum pos {
120 pos_default, pos_before, pos_after, pos_end
121 } postype = pos_default;
122
123 #ifdef GNU960
124 char *default_target;
125
126 void
127 gnu960_verify_target(abfd)
128 bfd *abfd;
129 {
130 if ( abfd->format == bfd_unknown ){
131 bfd_check_format(abfd, bfd_object);
132 /* Don't really care if it's an object --
133 * just want to get the correct xvec.
134 */
135 }
136 if ( !BFD_COFF_FILE_P(abfd) ){
137 fatal( "'%s' not a COFF file -- operation aborted",
138 abfd->filename );
139 }
140 }
141 #endif
142
143 int interactive = 0;
144 void
145 DEFUN_VOID(mri_emul)
146 {
147 interactive = isatty(fileno(stdin)) ;
148 yyparse();
149 }
150
151 /*
152 If count is 0, then function is called once on each entry. if nonzero,
153 count is the length of the files chain; function is called on each entry
154 whose name matches one in files
155 */
156 void
157 DEFUN(map_over_members,(function, files, count),
158 void (*function) () AND
159 char **files AND
160 int count)
161 {
162 bfd *head;
163
164 if (count == 0) {
165 for (head = inarch->next; head; head = head->next)
166 function(head);
167 return;
168 }
169 /*
170 This may appear to be a baroque way of accomplishing what we want.
171 however we have to iterate over the filenames in order to notice where
172 a filename is requested but does not exist in the archive. Ditto
173 mapping over each file each time -- we want to hack multiple
174 references.
175 */
176
177 for (; count > 0; files++, count--) {
178 boolean found = false;
179 for (head = inarch->next; head; head = head->next)
180 {
181 if (head->filename == NULL)
182 {
183 /* Some archive formats don't get the filenames filled in
184 'till the elements are opened */
185 struct stat buf;
186 bfd_stat_arch_elt(head, &buf);
187 }
188 if ((head->filename != NULL) &&
189 (!strcmp(*files, head->filename))) {
190 found = true;
191 function(head);
192 }
193 }
194 if (!found)
195 fprintf(stderr, "No entry %s in archive.\n", *files);
196 }
197 }
198
199
200 boolean operation_alters_arch = false;
201
202 extern char *program_version;
203
204 void
205 do_show_version ()
206 {
207 printf ("%s version %s\n", program_name, program_version);
208 }
209
210 void
211 usage ()
212 {
213 fprintf(stderr, "ar %s\n\
214 Usage: %s [-]{dmpqrtx}[abcilosuv] [member-name] archive-file file...\n\
215 %s -M [<mri-script]\n",
216 program_version, program_name, program_name);
217 exit(1);
218 }
219
220 /*
221 The option parsing should be in its own function. It will be when I have
222 getopt working.
223 */
224 int
225 main(argc, argv)
226 int argc;
227 char **argv;
228 {
229 char *arg_ptr;
230 char c;
231 enum {
232 none = 0, delete, replace, print_table,
233 print_files, extract, move, quick_append
234 } operation = none;
235 int arg_index;
236 char **files;
237 char *inarch_filename;
238 char *temp;
239 int show_version;
240
241 bfd_init();
242 show_version = 0;
243 #ifdef GNU960
244 check_v960( argc, argv );
245 default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
246 #endif
247
248 program_name = argv[0];
249
250 temp = strrchr(program_name, '/');
251 if (temp == (char *) NULL)
252 temp = program_name; /* shouldn't happen, but... */
253 else
254 ++temp;
255 if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
256 if (argc < 2)
257 usage ();
258 arg_ptr = argv[1];
259 if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "-v") == 0) {
260 do_show_version();
261 if (argc == 2)
262 exit(0);
263 arg_ptr = argv[2];
264 }
265 ranlib_only(arg_ptr);
266 }
267
268 if (argc == 2 && strcmp(argv[1],"-M") == 0) {
269 mri_emul();
270 exit(0);
271 }
272
273 if (argc < 2)
274 usage ();
275
276 arg_ptr = argv[1];
277
278 if (*arg_ptr == '-')
279 ++arg_ptr; /* compatibility */
280
281 while (c = *arg_ptr++) {
282 switch (c) {
283 case 'd':
284 case 'm':
285 case 'p':
286 case 'q':
287 case 'r':
288 case 't':
289 case 'x':
290 if (operation != none)
291 fatal("two different operation switches specified");
292 switch (c) {
293 case 'd':
294 operation = delete;
295 operation_alters_arch = true;
296 break;
297 case 'm':
298 operation = move;
299 operation_alters_arch = true;
300 break;
301 case 'p':
302 operation = print_files;
303 break;
304 case 'q':
305 operation = quick_append;
306 operation_alters_arch = true;
307 break;
308 case 'r':
309 operation = replace;
310 operation_alters_arch = true;
311 break;
312 case 't':
313 operation = print_table;
314 break;
315 case 'x':
316 operation = extract;
317 break;
318 }
319 case 'l':
320 break;
321 case 'c':
322 silent_create = 1;
323 break;
324 case 'o':
325 preserve_dates = 1;
326 break;
327 case 'V':
328 show_version = true;
329 break;
330 case 's':
331 write_armap = 1;
332 break;
333 case 'u':
334 newer_only = 1;
335 break;
336 case 'v':
337 verbose = 1;
338 break;
339 case 'a':
340 postype = pos_after;
341 break;
342 case 'b':
343 postype = pos_before;
344 break;
345 case 'i':
346 postype = pos_before;
347 break;
348 case 'M':
349
350 mri_mode = 1;
351 break;
352 default:
353 fatal("invalid option %c", c);
354 }
355 }
356
357 if (show_version)
358 do_show_version();
359
360 if (argc < 3)
361 if (show_version)
362 exit(0);
363 else
364 usage ();
365
366 if (mri_mode) {
367 mri_emul();
368 }
369 else {
370 if ((operation == none || operation == print_table)
371 && write_armap == 1)
372 ranlib_only(argv[2]);
373
374 if (operation == none)
375 fatal("no operation specified");
376
377 if (newer_only && operation != replace)
378 fatal("'u' only meaningful with 'r' option.");
379
380 arg_index = 2;
381
382 if (postype != pos_default)
383 posname = argv[arg_index++];
384
385 inarch_filename = argv[arg_index++];
386
387 files = arg_index < argc ? argv + arg_index : NULL;
388
389 if (operation == quick_append) {
390 if (files != NULL)
391 do_quick_append(inarch_filename, files);
392 exit(0);
393 }
394
395
396 open_inarch(inarch_filename);
397
398 switch (operation) {
399
400 case print_table:
401 map_over_members(print_descr, files, argc - 3);
402 break;
403
404 case print_files:
405 map_over_members(print_contents, files, argc - 3);
406 break;
407
408 case extract:
409 map_over_members(extract_file, files, argc - 3);
410 break;
411
412 case delete:
413 if (files != NULL)
414 delete_members(files);
415 break;
416
417 case move:
418 if (files != NULL)
419 move_members(files);
420 break;
421
422 case replace:
423 if (files != NULL || write_armap > 0)
424 replace_members(files);
425 break;
426
427 /* Shouldn't happen! */
428 default:
429 fprintf(stderr, "Sorry; this option not implemented.\n");
430 }
431 }
432 return (0);
433 } /* main() */
434
435 static
436 char *normalize(file)
437 char *file;
438 {
439 char * filename = strrchr(file, '/');
440 if (filename != (char *)NULL) {
441 filename ++;
442 }
443 else {
444 filename = file;
445 }
446 return filename;
447 }
448
449 int
450 open_inarch(archive_filename)
451 char *archive_filename;
452 {
453 bfd **last_one;
454 bfd *next_one;
455 struct stat sbuf;
456 bfd_error = no_error;
457 if (stat(archive_filename, &sbuf) != 0) {
458 if (errno != ENOENT)
459 bfd_fatal(archive_filename);
460 if (!operation_alters_arch) {
461 fprintf (stderr, "%s: %s not found.\n", program_name,
462 archive_filename);
463 maybequit();
464 return 0;
465 }
466
467 /* This routine is one way to forcibly create the archive. */
468 do_quick_append(archive_filename, 0);
469 }
470
471 #ifdef GNU960
472 inarch = bfd_openr(archive_filename, default_target);
473 #else
474 inarch = bfd_openr(archive_filename, NULL);
475 #endif
476 if (inarch == NULL) {
477 bloser:
478 fprintf (stderr, "%s: ", program_name);
479 bfd_perror(archive_filename);
480 exit(1);
481 }
482
483 if (bfd_check_format(inarch, bfd_archive) != true)
484 fatal("File %s is not an archive.", archive_filename);
485 #ifdef GNU960
486 gnu960_verify_target(inarch); /* Exits on failure */
487 #endif
488 last_one = &(inarch->next);
489 /* Read all the contents right away, regardless. */
490 for (next_one = bfd_openr_next_archived_file(inarch, NULL);
491 next_one;
492 next_one = bfd_openr_next_archived_file(inarch, next_one)) {
493 *last_one = next_one;
494 last_one = &next_one->next;
495 }
496 *last_one = (bfd *) NULL;
497 if (bfd_error != no_more_archived_files)
498 goto bloser;
499 return 1;
500 }
501
502
503
504
505
506 static void
507 print_contents(abfd)
508 bfd *abfd;
509 {
510 int ncopied = 0;
511 struct stat buf;
512 long size;
513 if (bfd_stat_arch_elt(abfd, &buf) != 0)
514 fatal("Internal stat error on %s", abfd->filename);
515
516 if (verbose)
517 printf("\n<member %s>\n\n", abfd->filename);
518
519 bfd_seek(abfd, 0, SEEK_SET);
520
521 size = buf.st_size;
522 while (ncopied < size) {
523 char cbuf[BUFSIZE];
524 int nread;
525 int tocopy = size - ncopied;
526 if (tocopy > BUFSIZE)
527 tocopy = BUFSIZE;
528
529 nread = bfd_read(cbuf, 1, tocopy, abfd); /* oops -- broke
530 abstraction! */
531
532 if (nread != tocopy)
533 fatal("file %s not a valid archive", abfd->my_archive->filename);
534 fwrite(cbuf, 1, nread, stdout);
535 ncopied += tocopy;
536 }
537 }
538
539
540 /*
541 Extract a member of the archive into its own file.
542
543 We defer opening the new file until after we have read a BUFSIZ chunk of the
544 old one, since we know we have just read the archive header for the old
545 one. Since most members are shorter than BUFSIZ, this means we will read
546 the old header, read the old data, write a new inode for the new file, and
547 write the new data, and be done. This 'optimization' is what comes from
548 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
549 Gilmore
550 */
551
552 void
553 extract_file(abfd)
554 bfd *abfd;
555 {
556 FILE *ostream;
557 char cbuf[BUFSIZE];
558 int nread,
559 tocopy;
560 int ncopied = 0;
561 long size;
562 struct stat buf;
563 if (bfd_stat_arch_elt(abfd, &buf) != 0)
564 fatal("Internal stat error on %s", abfd->filename);
565 size = buf.st_size;
566
567 if (verbose)
568 printf("x - %s\n", abfd->filename);
569
570 bfd_seek(abfd, 0, SEEK_SET);
571
572 ostream = 0;
573 if (size == 0) {
574 /* Seems like an abstraction violation, eh? Well it's OK! */
575 ostream = fopen(abfd->filename, FOPEN_WB);
576 if (!ostream) {
577 perror(abfd->filename);
578 exit(1);
579 }
580 } else
581 while (ncopied < size) {
582 tocopy = size - ncopied;
583 if (tocopy > BUFSIZE)
584 tocopy = BUFSIZE;
585
586 nread = bfd_read(cbuf, 1, tocopy, abfd);
587 if (nread != tocopy)
588 fatal("file %s not a valid archive", abfd->my_archive->filename);
589
590 /* See comment above; this saves disk arm motion */
591 if (!ostream) {
592 /* Seems like an abstraction violation, eh? Well it's OK! */
593 ostream = fopen(abfd->filename, FOPEN_WB);
594 if (!ostream) {
595 perror(abfd->filename);
596 exit(1);
597 }
598 }
599 fwrite(cbuf, 1, nread, ostream);
600 ncopied += tocopy;
601 }
602
603 fclose(ostream);
604 chmod(abfd->filename, buf.st_mode);
605
606 if (preserve_dates) {
607 #ifdef POSIX_UTIME
608 struct utimbuf tb;
609 tb.actime = buf.st_mtime;
610 tb.modtime = buf.st_mtime;
611 utime(abfd->filename, &tb); /* FIXME check result */
612 #else /* ! POSIX_UTIME */
613 #ifdef USE_UTIME
614 long tb[2];
615 tb[0] = buf.st_mtime;
616 tb[1] = buf.st_mtime;
617 utime(abfd->filename, tb); /* FIXME check result */
618 #else /* ! USE_UTIME */
619 struct timeval tv[2];
620 tv[0].tv_sec = buf.st_mtime;
621 tv[0].tv_usec = 0;
622 tv[1].tv_sec = buf.st_mtime;
623 tv[1].tv_usec = 0;
624 utimes(abfd->filename, tv); /* FIXME check result */
625 #endif /* ! USE_UTIME */
626 #endif /* ! POSIX_UTIME */
627 }
628 }
629
630
631 /* Just do it quickly; don't worry about dups, armap, or anything like that */
632
633 static void
634 do_quick_append(archive_filename, files_to_append)
635 char *archive_filename;
636 char **files_to_append;
637
638 {
639 FILE *ofile,
640 *ifile;
641 char buf[BUFSIZE];
642 long tocopy,
643 thistime;
644 bfd *temp;
645 struct stat sbuf;
646 boolean newfile = false;
647 bfd_error = no_error;
648
649 if (stat(archive_filename, &sbuf) != 0) {
650 if (errno != ENOENT)
651 bfd_fatal(archive_filename);
652 newfile = true;
653 }
654
655
656 ofile = fopen(archive_filename, FOPEN_AUB);
657 if (ofile == NULL) {
658 perror(program_name);
659 exit(1);
660 }
661
662 /* bletch */
663 #ifdef GNU960
664 temp = bfd_openr(archive_filename, default_target);
665 #else
666 temp = bfd_openr(archive_filename, NULL);
667 #endif
668 if (temp == NULL) {
669 fprintf (stderr, "%s: ", program_name);
670 bfd_perror(archive_filename);
671 exit(1);
672 }
673 if (newfile == false) {
674 if (bfd_check_format(temp, bfd_archive) != true)
675 fatal("File %s is not an archive.", archive_filename);
676 #ifdef GNU960
677 gnu960_verify_target(temp); /* Exits on failure */
678 #endif
679 }
680 else {
681 fwrite(ARMAG, 1, SARMAG, ofile);
682 if (!silent_create)
683 fprintf(stderr, "%s: creating %s\n", program_name, archive_filename);
684 }
685
686 /* assume it's an achive, go straight to the end, sans $200 */
687 fseek(ofile, 0, 2);
688
689 for (; files_to_append && *files_to_append; ++files_to_append) {
690 struct ar_hdr *hdr = bfd_special_undocumented_glue(temp, *files_to_append);
691 if (hdr == NULL) {
692 fprintf (stderr, "%s: ", program_name);
693 bfd_perror(*files_to_append);
694 exit(1);
695 }
696
697 BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
698
699 ifile = fopen(*files_to_append, FOPEN_RB);
700 if (ifile == NULL)
701 {
702 bfd_perror(program_name);
703 }
704
705 if (stat(*files_to_append, &sbuf) != 0)
706 {
707 fprintf (stderr, "%s: ", program_name);
708 bfd_perror(*files_to_append);
709 }
710
711 tocopy = sbuf.st_size;
712
713 /* XXX should do error-checking! */
714 fwrite(hdr, 1, sizeof(struct ar_hdr), ofile);
715
716
717 while (tocopy > 0) {
718 thistime = tocopy;
719 if (thistime > BUFSIZE)
720 thistime = BUFSIZE;
721 fread(buf, 1, thistime, ifile);
722 fwrite(buf, 1, thistime, ofile);
723 tocopy -= thistime;
724 }
725 fclose(ifile);
726 if ((sbuf.st_size % 2) == 1)
727 putc('\n', ofile);
728 }
729 fclose(ofile);
730 bfd_close(temp);
731 }
732
733
734 void
735 write_archive()
736 {
737 bfd *obfd;
738 int namelen = strlen(inarch->filename);
739 char *new_name = xmalloc(namelen + 6);
740 bfd *contents_head = inarch->next;
741
742 strcpy(new_name, inarch->filename);
743 strcpy(new_name + namelen, "-art");
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, "No entry %s in archive %s!\n",
891 *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, "Duplicate file specified: %s -- skipping.\n", *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, "Can't open file %s\n", *files_to_move);
948 exit(1);
949 }
950 #ifdef GNU960
951 gnu960_verify_target(*after_bfd); /* Exits on failure */
952 #endif
953 (*after_bfd)->next = temp;
954
955 if (verbose) {
956 printf("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
957 *files_to_move);
958 }
959 goto next_file;
960 }
961 current_ptr = &(current->next);
962 }
963
964 /* It isn't in there, so add to end */
965
966 after_bfd = get_pos_bfd(&inarch->next, pos_end);
967 temp = *after_bfd;
968 *after_bfd = bfd_openr(*files_to_move, NULL);
969 if (*after_bfd == (bfd *) NULL) {
970 fprintf(stderr, "Can't open file %s\n", *files_to_move);
971 exit(1);
972 }
973 #ifdef GNU960
974 gnu960_verify_target(*after_bfd); /* Exits on failure */
975 #endif
976 if (verbose) {
977 printf("c - %s\n", *files_to_move);
978 }
979
980 (*after_bfd)->next = temp;
981
982 next_file:;
983
984 files_to_move++;
985 }
986
987
988 write_archive();
989 }
990
991 static void
992 ranlib_only(archname)
993 char *archname;
994 {
995 write_armap = 1;
996 open_inarch(archname);
997 write_archive();
998 exit(0);
999 }
1000
1001
1002
1003 /* Things which are interesting to map over all or some of the files: */
1004
1005 static void
1006 print_descr(abfd)
1007 bfd *abfd;
1008 {
1009 print_arelt_descr(stdout,abfd, verbose);
1010 }
This page took 0.048436 seconds and 5 git commands to generate.