1 /* ar.c - Archive modify and extract.
2 Copyright 1991, 92, 93, 94 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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.
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.
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. */
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
36 #else /* ! POSIX_UTIME */
39 #else /* ! USE_UTIME */
41 #endif /* ! USE_UTIME */
42 #endif /* ! POSIX_UTIME */
50 #define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
52 #define EXT_NAME_LEN 6 /* ditto for *NIX */
55 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */
58 bfd_special_undocumented_glue PARAMS ((bfd * abfd, char *filename));
60 /* Forward declarations */
63 print_contents PARAMS ((bfd * member));
66 delete_members PARAMS ((char **files_to_delete));
69 do_quick_append PARAMS ((char *archive_filename, char **files_to_append));
72 move_members PARAMS ((char **files_to_move));
75 replace_members PARAMS ((char **files_to_replace));
78 print_descr PARAMS ((bfd * abfd));
81 ranlib_only PARAMS ((char *archname));
83 /** Globals and flags */
85 /* The input archive we're manipulating. */
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. */
95 /* Nonzero means don't warn about creating the archive file if necessary. */
96 int silent_create = 0;
98 /* Nonzero means describe each action performed. */
101 /* Nonzero means preserve dates of members when extracting them. */
102 int preserve_dates = 0;
104 /* Nonzero means don't replace existing members whose dates are more recent
105 than the corresponding files. */
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;
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. */
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;
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. */
127 pos_default, pos_before, pos_after, pos_end
128 } postype = pos_default;
135 interactive = isatty (fileno (stdin));
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. */
144 map_over_members (function, files, count)
153 for (head = inarch->next; head; head = head->next)
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
163 for (; count > 0; files++, count--)
165 boolean found = false;
166 for (head = inarch->next; head; head = head->next)
168 if (head->filename == NULL)
170 /* Some archive formats don't get the filenames filled in
171 until the elements are opened. */
173 bfd_stat_arch_elt (head, &buf);
175 if ((head->filename != NULL) &&
176 (!strcmp (*files, head->filename)))
183 fprintf (stderr, "no entry %s in archive\n", *files);
187 boolean operation_alters_arch = false;
189 extern char *program_version;
194 printf ("GNU %s version %s\n", program_name, program_version);
203 Usage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\
204 %s -M [<mri-script]\n",
205 program_name, program_name);
208 Usage: %s [-vV] archive\n", program_name);
212 /* The option parsing should be in its own function.
213 It will be when I have getopt working. */
224 none = 0, delete, replace, print_table,
225 print_files, extract, move, quick_append
229 char *inarch_filename;
233 program_name = argv[0];
234 xmalloc_set_program_name (program_name);
239 temp = strrchr (program_name, '/');
240 if (temp == (char *) NULL)
241 temp = program_name; /* shouldn't happen, but... */
244 if (is_ranlib > 0 || (is_ranlib < 0 && strcmp (temp, "ranlib") == 0))
247 if (argc < 2 || argc > 3)
250 if (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "-v") == 0)
252 ranlib_only (arg_ptr);
257 if (argc == 2 && strcmp (argv[1], "-M") == 0)
269 ++arg_ptr; /* compatibility */
271 while ((c = *arg_ptr++) != '\0')
282 if (operation != none)
283 fatal ("two different operation options specified");
288 operation_alters_arch = true;
292 operation_alters_arch = true;
295 operation = print_files;
298 operation = quick_append;
299 operation_alters_arch = true;
303 operation_alters_arch = true;
306 operation = print_table;
336 postype = pos_before;
339 postype = pos_before;
345 fprintf (stderr, "%s: illegal option -- %c\n", program_name, c);
362 if ((operation == none || operation == print_table)
364 ranlib_only (argv[2]);
366 if (operation == none)
367 fatal ("no operation specified");
369 if (newer_only && operation != replace)
370 fatal ("`u' is only meaningful with the `r' option.");
374 if (postype != pos_default)
375 posname = argv[arg_index++];
377 inarch_filename = argv[arg_index++];
379 files = arg_index < argc ? argv + arg_index : NULL;
381 if (operation == quick_append)
383 /* Note that quick appending to a non-existent archive creates it,
384 even if there are no files to append. */
385 do_quick_append (inarch_filename, files);
389 open_inarch (inarch_filename);
394 map_over_members (print_descr, files, argc - 3);
398 map_over_members (print_contents, files, argc - 3);
402 map_over_members (extract_file, files, argc - 3);
407 delete_members (files);
412 move_members (files);
416 if (files != NULL || write_armap > 0)
417 replace_members (files);
420 /* Shouldn't happen! */
422 fprintf (stderr, "%s: internal error -- this option not implemented\n",
434 char *filename = strrchr (file, '/');
435 if (filename != (char *) NULL)
447 open_inarch (archive_filename)
448 char *archive_filename;
453 bfd_set_error (bfd_error_no_error);
455 if (stat (archive_filename, &sbuf) != 0)
460 /* KLUDGE ALERT! Temporary fix until I figger why
461 * stat() is wrong ... think it's buried in GO32's IDT
465 bfd_fatal (archive_filename);
468 if (!operation_alters_arch)
470 fprintf (stderr, "%s: ", program_name);
471 perror (archive_filename);
476 /* This routine is one way to forcibly create the archive. */
478 do_quick_append (archive_filename, 0);
481 inarch = bfd_openr (archive_filename, NULL);
485 bfd_fatal (archive_filename);
488 if (bfd_check_format (inarch, bfd_archive) != true)
489 fatal ("%s is not an archive", archive_filename);
490 last_one = &(inarch->next);
491 /* Read all the contents right away, regardless. */
492 for (next_one = bfd_openr_next_archived_file (inarch, NULL);
494 next_one = bfd_openr_next_archived_file (inarch, next_one))
496 *last_one = next_one;
497 last_one = &next_one->next;
499 *last_one = (bfd *) NULL;
500 if (bfd_get_error () != bfd_error_no_more_archived_files)
506 print_contents (abfd)
512 if (bfd_stat_arch_elt (abfd, &buf) != 0)
513 fatal ("internal stat error on %s", bfd_get_filename (abfd));
516 printf ("\n<member %s>\n\n", bfd_get_filename (abfd));
518 bfd_seek (abfd, 0, SEEK_SET);
521 while (ncopied < size)
525 int tocopy = size - ncopied;
526 if (tocopy > BUFSIZE)
529 nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
532 fatal ("%s is not a valid archive",
533 bfd_get_filename (bfd_my_archive (abfd)));
534 fwrite (cbuf, 1, nread, stdout);
539 /* Extract a member of the archive into its own file.
541 We defer opening the new file until after we have read a BUFSIZ chunk of the
542 old one, since we know we have just read the archive header for the old
543 one. Since most members are shorter than BUFSIZ, this means we will read
544 the old header, read the old data, write a new inode for the new file, and
545 write the new data, and be done. This 'optimization' is what comes from
546 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
559 if (bfd_stat_arch_elt (abfd, &buf) != 0)
560 fatal ("internal stat error on %s", bfd_get_filename (abfd));
564 printf ("x - %s\n", bfd_get_filename (abfd));
566 bfd_seek (abfd, 0, SEEK_SET);
571 /* Seems like an abstraction violation, eh? Well it's OK! */
572 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
575 perror (bfd_get_filename (abfd));
580 while (ncopied < size)
582 tocopy = size - ncopied;
583 if (tocopy > BUFSIZE)
586 nread = bfd_read (cbuf, 1, tocopy, abfd);
588 fatal ("%s is not a valid archive",
589 bfd_get_filename (bfd_my_archive (abfd)));
591 /* See comment above; this saves disk arm motion */
594 /* Seems like an abstraction violation, eh? Well it's OK! */
595 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
598 perror (bfd_get_filename (abfd));
602 fwrite (cbuf, 1, nread, ostream);
607 chmod (bfd_get_filename (abfd), buf.st_mode);
613 tb.actime = buf.st_mtime;
614 tb.modtime = buf.st_mtime;
615 utime (bfd_get_filename (abfd), &tb); /* FIXME check result */
616 #else /* ! POSIX_UTIME */
619 tb[0] = buf.st_mtime;
620 tb[1] = buf.st_mtime;
621 utime (bfd_get_filename (abfd), tb); /* FIXME check result */
622 #else /* ! USE_UTIME */
623 struct timeval tv[2];
624 tv[0].tv_sec = buf.st_mtime;
626 tv[1].tv_sec = buf.st_mtime;
628 utimes (bfd_get_filename (abfd), tv); /* FIXME check result */
629 #endif /* ! USE_UTIME */
630 #endif /* ! POSIX_UTIME */
634 /* Just do it quickly; don't worry about dups, armap, or anything like that */
637 do_quick_append (archive_filename, files_to_append)
638 char *archive_filename;
639 char **files_to_append;
643 long tocopy, thistime;
646 boolean newfile = false;
647 bfd_set_error (bfd_error_no_error);
649 if (stat (archive_filename, &sbuf) != 0)
654 /* KLUDGE ALERT! Temporary fix until I figger why
655 * stat() is wrong ... think it's buried in GO32's IDT
660 bfd_fatal (archive_filename);
666 ofile = fopen (archive_filename, FOPEN_AUB);
669 perror (program_name);
673 temp = bfd_openr (archive_filename, NULL);
676 bfd_fatal (archive_filename);
678 if (newfile == false)
680 if (bfd_check_format (temp, bfd_archive) != true)
681 fatal ("%s is not an archive", archive_filename);
685 fwrite (ARMAG, 1, SARMAG, ofile);
687 fprintf (stderr, "%s: creating %s\n",
688 program_name, archive_filename);
691 /* assume it's an achive, go straight to the end, sans $200 */
694 for (; files_to_append && *files_to_append; ++files_to_append)
696 struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
699 bfd_fatal (*files_to_append);
702 BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
704 ifile = fopen (*files_to_append, FOPEN_RB);
707 bfd_nonfatal (*files_to_append);
710 if (stat (*files_to_append, &sbuf) != 0)
712 bfd_nonfatal (*files_to_append);
715 tocopy = sbuf.st_size;
717 /* XXX should do error-checking! */
718 fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
723 if (thistime > BUFSIZE)
725 fread (buf, 1, thistime, ifile);
726 fwrite (buf, 1, thistime, ofile);
730 if ((sbuf.st_size % 2) == 1)
731 putc ('\012', ofile);
742 int namelen = strlen (inarch->filename);
743 char *new_name = xmalloc (namelen + EXT_NAME_LEN);
744 bfd *contents_head = inarch->next;
746 strcpy (new_name, inarch->filename);
748 #ifdef __GO32__ /* avoid long .extensions for MS-DOS */
749 strcpy (new_name + namelen, "-a");
751 strcpy (new_name + namelen, "-art");
754 obfd = bfd_openw (new_name,
755 /* FIXME: violates abstraction; need a better protocol */
756 (inarch->xvec ? bfd_get_target (inarch) : NULL));
759 bfd_fatal (inarch->filename);
761 bfd_set_format (obfd, bfd_archive);
763 /* Request writing the archive symbol table unless we've
764 been explicitly requested not to. */
765 obfd->has_armap = write_armap >= 0;
767 if (bfd_set_archive_head (obfd, contents_head) != true)
768 bfd_fatal (inarch->filename);
770 if (!bfd_close (obfd))
771 bfd_fatal (inarch->filename);
773 /* We don't care if this fails; we might be creating the archive. */
774 unlink (inarch->filename);
776 if (rename (new_name, inarch->filename) != 0)
777 bfd_fatal (inarch->filename);
780 /* Return a pointer to the pointer to the entry which should be rplacd'd
781 into when altering. DEFAULT_POS should be how to interpret pos_default,
782 and should be a pos value. */
785 get_pos_bfd (contents, default_pos)
787 enum pos default_pos;
789 bfd **after_bfd = contents;
790 enum pos realpos = (postype == pos_default ? default_pos : postype);
792 if (realpos == pos_end)
795 after_bfd = &((*after_bfd)->next);
799 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
800 if (!strcmp ((*after_bfd)->filename, posname))
802 if (realpos == pos_after)
803 after_bfd = &(*after_bfd)->next;
811 delete_members (files_to_delete)
812 char **files_to_delete;
814 bfd **current_ptr_ptr;
816 boolean something_changed = false;
817 for (; *files_to_delete != NULL; ++files_to_delete)
819 /* In a.out systems, the armap is optional. It's also called
820 __.SYMDEF. So if the user asked to delete it, we should remember
821 that fact. This isn't quite right for COFF systems (where
822 __.SYMDEF might be regular member), but it's very unlikely
823 to be a problem. FIXME */
825 if (!strcmp (*files_to_delete, "__.SYMDEF"))
827 inarch->has_armap = false;
833 current_ptr_ptr = &(inarch->next);
834 while (*current_ptr_ptr)
836 if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
839 something_changed = true;
843 *current_ptr_ptr = ((*current_ptr_ptr)->next);
848 current_ptr_ptr = &((*current_ptr_ptr)->next);
852 if (verbose && found == false)
854 printf ("No member named `%s'\n", *files_to_delete);
860 if (something_changed == true)
867 /* Reposition existing members within an archive */
870 move_members (files_to_move)
871 char **files_to_move;
873 bfd **after_bfd; /* New entries go after this one */
874 bfd **current_ptr_ptr; /* cdr pointer into contents */
876 for (; *files_to_move; ++files_to_move)
878 current_ptr_ptr = &(inarch->next);
879 while (*current_ptr_ptr)
881 bfd *current_ptr = *current_ptr_ptr;
882 if (strcmp (normalize (*files_to_move), current_ptr->filename) == 0)
884 /* Move this file to the end of the list - first cut from
887 *current_ptr_ptr = current_ptr->next;
889 /* Now glue to end */
890 after_bfd = get_pos_bfd (&inarch->next, pos_end);
892 *after_bfd = current_ptr;
893 current_ptr->next = link;
896 printf ("m - %s\n", *files_to_move);
901 current_ptr_ptr = &((*current_ptr_ptr)->next);
903 fprintf (stderr, "%s: no entry %s in archive %s!\n",
904 program_name, *files_to_move, inarch->filename);
912 /* Ought to default to replacing in place, but this is existing practice! */
915 replace_members (files_to_move)
916 char **files_to_move;
918 bfd **after_bfd; /* New entries go after this one */
923 while (files_to_move && *files_to_move)
925 current_ptr = &inarch->next;
928 current = *current_ptr;
930 if (!strcmp (normalize (*files_to_move), current->filename))
934 struct stat fsbuf, asbuf;
936 if (current->arelt_data == NULL)
938 /* This can only happen if you specify a file on the
939 command line more than once. */
941 "%s: duplicate file specified: %s -- skipping\n",
942 program_name, *files_to_move);
946 if (stat (*files_to_move, &fsbuf) != 0)
949 bfd_fatal (*files_to_move);
952 if (bfd_stat_arch_elt (current, &asbuf) != 0)
953 fatal ("internal stat error on %s", current->filename);
955 if (fsbuf.st_mtime <= asbuf.st_mtime)
959 /* snip out this entry from the chain */
960 *current_ptr = current->next;
962 after_bfd = get_pos_bfd (&inarch->next, pos_end);
964 *after_bfd = bfd_openr (*files_to_move, NULL);
965 if (*after_bfd == (bfd *) NULL)
967 bfd_fatal (*files_to_move);
969 (*after_bfd)->next = temp;
973 printf ("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
978 current_ptr = &(current->next);
981 /* It isn't in there, so add to end */
983 after_bfd = get_pos_bfd (&inarch->next, pos_end);
985 *after_bfd = bfd_openr (*files_to_move, NULL);
986 if (*after_bfd == (bfd *) NULL)
988 bfd_fatal (*files_to_move);
992 printf ("c - %s\n", *files_to_move);
995 (*after_bfd)->next = temp;
1006 ranlib_only (archname)
1010 open_inarch (archname);
1015 /* Things which are interesting to map over all or some of the files: */
1021 print_arelt_descr (stdout, abfd, verbose);