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