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
29 #include "libiberty.h"
37 #else /* ! POSIX_UTIME */
40 #else /* ! USE_UTIME */
42 #endif /* ! USE_UTIME */
43 #endif /* ! POSIX_UTIME */
51 #define EXT_NAME_LEN 3 /* bufflen of addition to name if it's MS-DOS */
53 #define EXT_NAME_LEN 6 /* ditto for *NIX */
56 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */
59 bfd_special_undocumented_glue PARAMS ((bfd * abfd, char *filename));
61 /* Forward declarations */
64 map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int));
67 print_contents PARAMS ((bfd * member));
70 delete_members PARAMS ((bfd *, char **files_to_delete));
73 do_quick_append PARAMS ((const char *archive_filename,
74 char **files_to_append));
77 move_members PARAMS ((bfd *, char **files_to_move));
80 replace_members PARAMS ((bfd *, char **files_to_replace));
83 print_descr PARAMS ((bfd * abfd));
86 write_archive PARAMS ((bfd *));
89 ranlib_only PARAMS ((const char *archname));
92 ranlib_touch PARAMS ((const char *archname));
94 /** Globals and flags */
98 /* This flag distinguishes between ar and ranlib:
99 1 means this is 'ranlib'; 0 means this is 'ar'.
100 -1 means if we should use argv[0] to decide. */
101 extern int is_ranlib;
103 /* Nonzero means don't warn about creating the archive file if necessary. */
104 int silent_create = 0;
106 /* Nonzero means describe each action performed. */
109 /* Nonzero means preserve dates of members when extracting them. */
110 int preserve_dates = 0;
112 /* Nonzero means don't replace existing members whose dates are more recent
113 than the corresponding files. */
116 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
117 member). -1 means we've been explicitly asked to not write a symbol table;
118 +1 means we've been explictly asked to write it;
120 Traditionally, the default in BSD has been to not write the table.
121 However, for POSIX.2 compliance the default is now to write a symbol table
122 if any of the members are object files. */
125 /* Nonzero means it's the name of an existing member; position new or moved
126 files with respect to this one. */
127 char *posname = NULL;
129 /* Sez how to use `posname': pos_before means position before that member.
130 pos_after means position after that member. pos_end means always at end.
131 pos_default means default appropriately. For the latter two, `posname'
132 should also be zero. */
135 pos_default, pos_before, pos_after, pos_end
136 } postype = pos_default;
143 interactive = isatty (fileno (stdin));
147 /* If COUNT is 0, then FUNCTION is called once on each entry. If nonzero,
148 COUNT is the length of the FILES chain; FUNCTION is called on each entry
149 whose name matches one in FILES. */
152 map_over_members (arch, function, files, count)
154 void (*function) PARAMS ((bfd *));
162 for (head = arch->next; head; head = head->next)
166 /* This may appear to be a baroque way of accomplishing what we want.
167 However we have to iterate over the filenames in order to notice where
168 a filename is requested but does not exist in the archive. Ditto
169 mapping over each file each time -- we want to hack multiple
172 for (; count > 0; files++, count--)
174 boolean found = false;
175 for (head = arch->next; head; head = head->next)
177 if (head->filename == NULL)
179 /* Some archive formats don't get the filenames filled in
180 until the elements are opened. */
182 bfd_stat_arch_elt (head, &buf);
184 if ((head->filename != NULL) &&
185 (!strcmp (*files, head->filename)))
192 fprintf (stderr, "no entry %s in archive\n", *files);
196 boolean operation_alters_arch = false;
198 extern char *program_version;
203 printf ("GNU %s version %s\n", program_name, program_version);
212 Usage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\
213 %s -M [<mri-script]\n",
214 program_name, program_name);
217 Usage: %s [-vV] archive\n", program_name);
221 /* The option parsing should be in its own function.
222 It will be when I have getopt working. */
233 none = 0, delete, replace, print_table,
234 print_files, extract, move, quick_append
238 char *inarch_filename;
242 program_name = argv[0];
243 xmalloc_set_program_name (program_name);
248 temp = strrchr (program_name, '/');
249 if (temp == (char *) NULL)
250 temp = program_name; /* shouldn't happen, but... */
253 if (is_ranlib > 0 || (is_ranlib < 0 && strcmp (temp, "ranlib") == 0))
255 boolean touch = false;
260 if (strcmp (argv[1], "-V") == 0
261 || strcmp (argv[1], "-v") == 0
262 || strncmp (argv[1], "--v", 3) == 0)
265 if (strcmp (argv[1], "-t") == 0)
270 while (arg_index < argc)
273 ranlib_only (argv[arg_index]);
275 ranlib_touch (argv[arg_index]);
283 if (argc == 2 && strcmp (argv[1], "-M") == 0)
295 ++arg_ptr; /* compatibility */
297 while ((c = *arg_ptr++) != '\0')
308 if (operation != none)
309 fatal ("two different operation options specified");
314 operation_alters_arch = true;
318 operation_alters_arch = true;
321 operation = print_files;
324 operation = quick_append;
325 operation_alters_arch = true;
329 operation_alters_arch = true;
332 operation = print_table;
362 postype = pos_before;
365 postype = pos_before;
371 fprintf (stderr, "%s: illegal option -- %c\n", program_name, c);
390 if ((operation == none || operation == print_table)
393 ranlib_only (argv[2]);
397 if (operation == none)
398 fatal ("no operation specified");
400 if (newer_only && operation != replace)
401 fatal ("`u' is only meaningful with the `r' option.");
405 if (postype != pos_default)
406 posname = argv[arg_index++];
408 inarch_filename = argv[arg_index++];
410 files = arg_index < argc ? argv + arg_index : NULL;
412 if (operation == quick_append)
414 /* Note that quick appending to a non-existent archive creates it,
415 even if there are no files to append. */
416 do_quick_append (inarch_filename, files);
420 arch = open_inarch (inarch_filename);
425 map_over_members (arch, print_descr, files, argc - 3);
429 map_over_members (arch, print_contents, files, argc - 3);
433 map_over_members (arch, extract_file, files, argc - 3);
438 delete_members (arch, files);
443 move_members (arch, files);
447 if (files != NULL || write_armap > 0)
448 replace_members (arch, files);
451 /* Shouldn't happen! */
453 fprintf (stderr, "%s: internal error -- this option not implemented\n",
465 char *filename = strrchr (file, '/');
466 if (filename != (char *) NULL)
478 open_inarch (archive_filename)
479 const char *archive_filename;
486 bfd_set_error (bfd_error_no_error);
488 if (stat (archive_filename, &sbuf) != 0)
493 /* KLUDGE ALERT! Temporary fix until I figger why
494 * stat() is wrong ... think it's buried in GO32's IDT
498 bfd_fatal (archive_filename);
501 if (!operation_alters_arch)
503 fprintf (stderr, "%s: ", program_name);
504 perror (archive_filename);
509 /* This routine is one way to forcibly create the archive. */
511 do_quick_append (archive_filename, 0);
514 arch = bfd_openr (archive_filename, NULL);
518 bfd_fatal (archive_filename);
521 if (bfd_check_format (arch, bfd_archive) != true)
522 fatal ("%s is not an archive", archive_filename);
523 last_one = &(arch->next);
524 /* Read all the contents right away, regardless. */
525 for (next_one = bfd_openr_next_archived_file (arch, NULL);
527 next_one = bfd_openr_next_archived_file (arch, next_one))
529 *last_one = next_one;
530 last_one = &next_one->next;
532 *last_one = (bfd *) NULL;
533 if (bfd_get_error () != bfd_error_no_more_archived_files)
539 print_contents (abfd)
545 if (bfd_stat_arch_elt (abfd, &buf) != 0)
546 fatal ("internal stat error on %s", bfd_get_filename (abfd));
549 printf ("\n<member %s>\n\n", bfd_get_filename (abfd));
551 bfd_seek (abfd, 0, SEEK_SET);
554 while (ncopied < size)
558 int tocopy = size - ncopied;
559 if (tocopy > BUFSIZE)
562 nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
565 fatal ("%s is not a valid archive",
566 bfd_get_filename (bfd_my_archive (abfd)));
567 fwrite (cbuf, 1, nread, stdout);
572 /* Extract a member of the archive into its own file.
574 We defer opening the new file until after we have read a BUFSIZ chunk of the
575 old one, since we know we have just read the archive header for the old
576 one. Since most members are shorter than BUFSIZ, this means we will read
577 the old header, read the old data, write a new inode for the new file, and
578 write the new data, and be done. This 'optimization' is what comes from
579 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
592 if (bfd_stat_arch_elt (abfd, &buf) != 0)
593 fatal ("internal stat error on %s", bfd_get_filename (abfd));
597 printf ("x - %s\n", bfd_get_filename (abfd));
599 bfd_seek (abfd, 0, SEEK_SET);
604 /* Seems like an abstraction violation, eh? Well it's OK! */
605 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
608 perror (bfd_get_filename (abfd));
613 while (ncopied < size)
615 tocopy = size - ncopied;
616 if (tocopy > BUFSIZE)
619 nread = bfd_read (cbuf, 1, tocopy, abfd);
621 fatal ("%s is not a valid archive",
622 bfd_get_filename (bfd_my_archive (abfd)));
624 /* See comment above; this saves disk arm motion */
627 /* Seems like an abstraction violation, eh? Well it's OK! */
628 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
631 perror (bfd_get_filename (abfd));
635 fwrite (cbuf, 1, nread, ostream);
640 chmod (bfd_get_filename (abfd), buf.st_mode);
646 tb.actime = buf.st_mtime;
647 tb.modtime = buf.st_mtime;
648 utime (bfd_get_filename (abfd), &tb); /* FIXME check result */
649 #else /* ! POSIX_UTIME */
652 tb[0] = buf.st_mtime;
653 tb[1] = buf.st_mtime;
654 utime (bfd_get_filename (abfd), tb); /* FIXME check result */
655 #else /* ! USE_UTIME */
656 struct timeval tv[2];
657 tv[0].tv_sec = buf.st_mtime;
659 tv[1].tv_sec = buf.st_mtime;
661 utimes (bfd_get_filename (abfd), tv); /* FIXME check result */
662 #endif /* ! USE_UTIME */
663 #endif /* ! POSIX_UTIME */
667 /* Just do it quickly; don't worry about dups, armap, or anything like that */
670 do_quick_append (archive_filename, files_to_append)
671 const char *archive_filename;
672 char **files_to_append;
676 long tocopy, thistime;
679 boolean newfile = false;
680 bfd_set_error (bfd_error_no_error);
682 if (stat (archive_filename, &sbuf) != 0)
687 /* KLUDGE ALERT! Temporary fix until I figger why
688 * stat() is wrong ... think it's buried in GO32's IDT
693 bfd_fatal (archive_filename);
699 ofile = fopen (archive_filename, FOPEN_AUB);
702 perror (program_name);
706 temp = bfd_openr (archive_filename, NULL);
709 bfd_fatal (archive_filename);
711 if (newfile == false)
713 if (bfd_check_format (temp, bfd_archive) != true)
714 fatal ("%s is not an archive", archive_filename);
718 fwrite (ARMAG, 1, SARMAG, ofile);
720 fprintf (stderr, "%s: creating %s\n",
721 program_name, archive_filename);
724 /* assume it's an achive, go straight to the end, sans $200 */
727 for (; files_to_append && *files_to_append; ++files_to_append)
729 struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
732 bfd_fatal (*files_to_append);
735 BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
737 ifile = fopen (*files_to_append, FOPEN_RB);
740 bfd_nonfatal (*files_to_append);
743 if (stat (*files_to_append, &sbuf) != 0)
745 bfd_nonfatal (*files_to_append);
748 tocopy = sbuf.st_size;
750 /* XXX should do error-checking! */
751 fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
756 if (thistime > BUFSIZE)
758 fread (buf, 1, thistime, ifile);
759 fwrite (buf, 1, thistime, ofile);
763 if ((sbuf.st_size % 2) == 1)
764 putc ('\012', ofile);
772 write_archive (iarch)
776 int namelen = strlen (bfd_get_filename (iarch));
777 char *old_name = xmalloc (namelen + 1);
778 char *new_name = xmalloc (namelen + EXT_NAME_LEN);
779 bfd *contents_head = iarch->next;
781 strcpy (old_name, bfd_get_filename (iarch));
782 strcpy (new_name, bfd_get_filename (iarch));
784 #ifdef __GO32__ /* avoid long .extensions for MS-DOS */
785 strcpy (new_name + namelen, "-a");
787 strcpy (new_name + namelen, "-art");
790 obfd = bfd_openw (new_name, bfd_get_target (iarch));
793 bfd_fatal (old_name);
795 bfd_set_format (obfd, bfd_archive);
797 /* Request writing the archive symbol table unless we've
798 been explicitly requested not to. */
799 obfd->has_armap = write_armap >= 0;
801 if (bfd_set_archive_head (obfd, contents_head) != true)
802 bfd_fatal (old_name);
804 if (!bfd_close (obfd))
805 bfd_fatal (old_name);
807 /* We don't care if this fails; we might be creating the archive. */
811 if (rename (new_name, old_name) != 0)
812 bfd_fatal (old_name);
815 /* Return a pointer to the pointer to the entry which should be rplacd'd
816 into when altering. DEFAULT_POS should be how to interpret pos_default,
817 and should be a pos value. */
820 get_pos_bfd (contents, default_pos)
822 enum pos default_pos;
824 bfd **after_bfd = contents;
825 enum pos realpos = (postype == pos_default ? default_pos : postype);
827 if (realpos == pos_end)
830 after_bfd = &((*after_bfd)->next);
834 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
835 if (!strcmp ((*after_bfd)->filename, posname))
837 if (realpos == pos_after)
838 after_bfd = &(*after_bfd)->next;
846 delete_members (arch, files_to_delete)
848 char **files_to_delete;
850 bfd **current_ptr_ptr;
852 boolean something_changed = false;
853 for (; *files_to_delete != NULL; ++files_to_delete)
855 /* In a.out systems, the armap is optional. It's also called
856 __.SYMDEF. So if the user asked to delete it, we should remember
857 that fact. This isn't quite right for COFF systems (where
858 __.SYMDEF might be regular member), but it's very unlikely
859 to be a problem. FIXME */
861 if (!strcmp (*files_to_delete, "__.SYMDEF"))
863 arch->has_armap = false;
869 current_ptr_ptr = &(arch->next);
870 while (*current_ptr_ptr)
872 if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
875 something_changed = true;
879 *current_ptr_ptr = ((*current_ptr_ptr)->next);
884 current_ptr_ptr = &((*current_ptr_ptr)->next);
888 if (verbose && found == false)
890 printf ("No member named `%s'\n", *files_to_delete);
896 if (something_changed == true)
898 write_archive (arch);
903 /* Reposition existing members within an archive */
906 move_members (arch, files_to_move)
908 char **files_to_move;
910 bfd **after_bfd; /* New entries go after this one */
911 bfd **current_ptr_ptr; /* cdr pointer into contents */
913 for (; *files_to_move; ++files_to_move)
915 current_ptr_ptr = &(arch->next);
916 while (*current_ptr_ptr)
918 bfd *current_ptr = *current_ptr_ptr;
919 if (strcmp (normalize (*files_to_move), current_ptr->filename) == 0)
921 /* Move this file to the end of the list - first cut from
924 *current_ptr_ptr = current_ptr->next;
926 /* Now glue to end */
927 after_bfd = get_pos_bfd (&arch->next, pos_end);
929 *after_bfd = current_ptr;
930 current_ptr->next = link;
933 printf ("m - %s\n", *files_to_move);
938 current_ptr_ptr = &((*current_ptr_ptr)->next);
940 fprintf (stderr, "%s: no entry %s in archive %s!\n",
941 program_name, *files_to_move, arch->filename);
946 write_archive (arch);
949 /* Ought to default to replacing in place, but this is existing practice! */
952 replace_members (arch, files_to_move)
954 char **files_to_move;
956 bfd **after_bfd; /* New entries go after this one */
961 while (files_to_move && *files_to_move)
963 current_ptr = &arch->next;
966 current = *current_ptr;
968 if (!strcmp (normalize (*files_to_move), current->filename))
972 struct stat fsbuf, asbuf;
974 if (current->arelt_data == NULL)
976 /* This can only happen if you specify a file on the
977 command line more than once. */
979 "%s: duplicate file specified: %s -- skipping\n",
980 program_name, *files_to_move);
984 if (stat (*files_to_move, &fsbuf) != 0)
987 bfd_fatal (*files_to_move);
990 if (bfd_stat_arch_elt (current, &asbuf) != 0)
991 fatal ("internal stat error on %s", current->filename);
993 if (fsbuf.st_mtime <= asbuf.st_mtime)
997 /* snip out this entry from the chain */
998 *current_ptr = current->next;
1000 after_bfd = get_pos_bfd (&arch->next, pos_end);
1002 *after_bfd = bfd_openr (*files_to_move, NULL);
1003 if (*after_bfd == (bfd *) NULL)
1005 bfd_fatal (*files_to_move);
1007 (*after_bfd)->next = temp;
1011 printf ("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
1016 current_ptr = &(current->next);
1019 /* It isn't in there, so add to end */
1021 after_bfd = get_pos_bfd (&arch->next, pos_end);
1023 *after_bfd = bfd_openr (*files_to_move, NULL);
1024 if (*after_bfd == (bfd *) NULL)
1026 bfd_fatal (*files_to_move);
1030 printf ("c - %s\n", *files_to_move);
1033 (*after_bfd)->next = temp;
1040 write_archive (arch);
1044 ranlib_only (archname)
1045 const char *archname;
1050 arch = open_inarch (archname);
1053 write_archive (arch);
1056 /* Update the timestamp of the symbol map of an archive. */
1059 ranlib_touch (archname)
1060 const char *archname;
1063 /* I don't think updating works on go32. */
1064 ranlib_only (archname);
1069 f = open (archname, O_RDWR, 0);
1072 bfd_set_error (bfd_error_system_call);
1073 bfd_fatal (archname);
1076 arch = bfd_fdopenr (archname, (const char *) NULL, f);
1078 || ! bfd_check_format (arch, bfd_archive))
1079 bfd_fatal (archname);
1081 bfd_update_armap_timestamp (arch);
1083 if (! bfd_close (arch))
1084 bfd_fatal (archname);
1088 /* Things which are interesting to map over all or some of the files: */
1094 print_arelt_descr (stdout, abfd, verbose);