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