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;
236 program_name = argv[0];
238 temp = strrchr (program_name, '/');
239 if (temp == (char *) NULL)
240 temp = program_name; /* shouldn't happen, but... */
243 if (is_ranlib > 0 || (is_ranlib < 0 && strcmp (temp, "ranlib") == 0))
246 if (argc < 2 || argc > 3)
249 if (strcmp (argv[1], "-V") == 0 || strcmp (argv[1], "-v") == 0)
251 ranlib_only (arg_ptr);
256 if (argc == 2 && strcmp (argv[1], "-M") == 0)
268 ++arg_ptr; /* compatibility */
270 while ((c = *arg_ptr++) != '\0')
281 if (operation != none)
282 fatal ("two different operation options specified");
287 operation_alters_arch = true;
291 operation_alters_arch = true;
294 operation = print_files;
297 operation = quick_append;
298 operation_alters_arch = true;
302 operation_alters_arch = true;
305 operation = print_table;
335 postype = pos_before;
338 postype = pos_before;
344 fprintf (stderr, "%s: illegal option -- %c\n", program_name, c);
361 if ((operation == none || operation == print_table)
363 ranlib_only (argv[2]);
365 if (operation == none)
366 fatal ("no operation specified");
368 if (newer_only && operation != replace)
369 fatal ("`u' is only meaningful with the `r' option.");
373 if (postype != pos_default)
374 posname = argv[arg_index++];
376 inarch_filename = argv[arg_index++];
378 files = arg_index < argc ? argv + arg_index : NULL;
380 if (operation == quick_append)
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);
388 open_inarch (inarch_filename);
393 map_over_members (print_descr, files, argc - 3);
397 map_over_members (print_contents, files, argc - 3);
401 map_over_members (extract_file, files, argc - 3);
406 delete_members (files);
411 move_members (files);
415 if (files != NULL || write_armap > 0)
416 replace_members (files);
419 /* Shouldn't happen! */
421 fprintf (stderr, "%s: internal error -- this option not implemented\n",
433 char *filename = strrchr (file, '/');
434 if (filename != (char *) NULL)
446 open_inarch (archive_filename)
447 char *archive_filename;
452 bfd_error = no_error;
454 if (stat (archive_filename, &sbuf) != 0)
459 /* KLUDGE ALERT! Temporary fix until I figger why
460 * stat() is wrong ... think it's buried in GO32's IDT
464 bfd_fatal (archive_filename);
467 if (!operation_alters_arch)
469 fprintf (stderr, "%s: ", program_name);
470 perror (archive_filename);
475 /* This routine is one way to forcibly create the archive. */
477 do_quick_append (archive_filename, 0);
480 inarch = bfd_openr (archive_filename, NULL);
484 bfd_fatal (archive_filename);
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);
493 next_one = bfd_openr_next_archived_file (inarch, next_one))
495 *last_one = next_one;
496 last_one = &next_one->next;
498 *last_one = (bfd *) NULL;
499 if (bfd_error != no_more_archived_files)
505 print_contents (abfd)
511 if (bfd_stat_arch_elt (abfd, &buf) != 0)
512 fatal ("internal stat error on %s", bfd_get_filename (abfd));
515 printf ("\n<member %s>\n\n", bfd_get_filename (abfd));
517 bfd_seek (abfd, 0, SEEK_SET);
520 while (ncopied < size)
524 int tocopy = size - ncopied;
525 if (tocopy > BUFSIZE)
528 nread = bfd_read (cbuf, 1, tocopy, abfd); /* oops -- broke
531 fatal ("%s is not a valid archive",
532 bfd_get_filename (bfd_my_archive (abfd)));
533 fwrite (cbuf, 1, nread, stdout);
538 /* Extract a member of the archive into its own file.
540 We defer opening the new file until after we have read a BUFSIZ chunk of the
541 old one, since we know we have just read the archive header for the old
542 one. Since most members are shorter than BUFSIZ, this means we will read
543 the old header, read the old data, write a new inode for the new file, and
544 write the new data, and be done. This 'optimization' is what comes from
545 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
558 if (bfd_stat_arch_elt (abfd, &buf) != 0)
559 fatal ("internal stat error on %s", bfd_get_filename (abfd));
563 printf ("x - %s\n", bfd_get_filename (abfd));
565 bfd_seek (abfd, 0, SEEK_SET);
570 /* Seems like an abstraction violation, eh? Well it's OK! */
571 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
574 perror (bfd_get_filename (abfd));
579 while (ncopied < size)
581 tocopy = size - ncopied;
582 if (tocopy > BUFSIZE)
585 nread = bfd_read (cbuf, 1, tocopy, abfd);
587 fatal ("%s is not a valid archive",
588 bfd_get_filename (bfd_my_archive (abfd)));
590 /* See comment above; this saves disk arm motion */
593 /* Seems like an abstraction violation, eh? Well it's OK! */
594 ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
597 perror (bfd_get_filename (abfd));
601 fwrite (cbuf, 1, nread, ostream);
606 chmod (bfd_get_filename (abfd), buf.st_mode);
612 tb.actime = buf.st_mtime;
613 tb.modtime = buf.st_mtime;
614 utime (bfd_get_filename (abfd), &tb); /* FIXME check result */
615 #else /* ! POSIX_UTIME */
618 tb[0] = buf.st_mtime;
619 tb[1] = buf.st_mtime;
620 utime (bfd_get_filename (abfd), tb); /* FIXME check result */
621 #else /* ! USE_UTIME */
622 struct timeval tv[2];
623 tv[0].tv_sec = buf.st_mtime;
625 tv[1].tv_sec = buf.st_mtime;
627 utimes (bfd_get_filename (abfd), tv); /* FIXME check result */
628 #endif /* ! USE_UTIME */
629 #endif /* ! POSIX_UTIME */
633 /* Just do it quickly; don't worry about dups, armap, or anything like that */
636 do_quick_append (archive_filename, files_to_append)
637 char *archive_filename;
638 char **files_to_append;
642 long tocopy, thistime;
645 boolean newfile = false;
646 bfd_error = no_error;
648 if (stat (archive_filename, &sbuf) != 0)
653 /* KLUDGE ALERT! Temporary fix until I figger why
654 * stat() is wrong ... think it's buried in GO32's IDT
659 bfd_fatal (archive_filename);
665 ofile = fopen (archive_filename, FOPEN_AUB);
668 perror (program_name);
672 temp = bfd_openr (archive_filename, NULL);
675 bfd_fatal (archive_filename);
677 if (newfile == false)
679 if (bfd_check_format (temp, bfd_archive) != true)
680 fatal ("%s is not an archive", archive_filename);
684 fwrite (ARMAG, 1, SARMAG, ofile);
686 fprintf (stderr, "%s: creating %s\n",
687 program_name, archive_filename);
690 /* assume it's an achive, go straight to the end, sans $200 */
693 for (; files_to_append && *files_to_append; ++files_to_append)
695 struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
698 bfd_fatal (*files_to_append);
701 BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
703 ifile = fopen (*files_to_append, FOPEN_RB);
706 bfd_nonfatal (*files_to_append);
709 if (stat (*files_to_append, &sbuf) != 0)
711 bfd_nonfatal (*files_to_append);
714 tocopy = sbuf.st_size;
716 /* XXX should do error-checking! */
717 fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
722 if (thistime > BUFSIZE)
724 fread (buf, 1, thistime, ifile);
725 fwrite (buf, 1, thistime, ofile);
729 if ((sbuf.st_size % 2) == 1)
741 int namelen = strlen (inarch->filename);
742 char *new_name = xmalloc (namelen + EXT_NAME_LEN);
743 bfd *contents_head = inarch->next;
745 strcpy (new_name, inarch->filename);
747 #ifdef __GO32__ /* avoid long .extensions for MS-DOS */
748 strcpy (new_name + namelen, "-a");
750 strcpy (new_name + namelen, "-art");
753 obfd = bfd_openw (new_name,
754 /* FIXME: violates abstraction; need a better protocol */
755 (inarch->xvec ? bfd_get_target (inarch) : NULL));
758 bfd_fatal (inarch->filename);
760 bfd_set_format (obfd, bfd_archive);
762 /* Request writing the archive symbol table unless we've
763 been explicitly requested not to. */
764 obfd->has_armap = write_armap >= 0;
766 if (bfd_set_archive_head (obfd, contents_head) != true)
767 bfd_fatal (inarch->filename);
769 if (!bfd_close (obfd))
770 bfd_fatal (inarch->filename);
772 /* We don't care if this fails; we might be creating the archive. */
773 unlink (inarch->filename);
775 if (rename (new_name, inarch->filename) != 0)
776 bfd_fatal (inarch->filename);
779 /* Return a pointer to the pointer to the entry which should be rplacd'd
780 into when altering. DEFAULT_POS should be how to interpret pos_default,
781 and should be a pos value. */
784 get_pos_bfd (contents, default_pos)
786 enum pos default_pos;
788 bfd **after_bfd = contents;
789 enum pos realpos = (postype == pos_default ? default_pos : postype);
791 if (realpos == pos_end)
794 after_bfd = &((*after_bfd)->next);
798 for (; *after_bfd; after_bfd = &(*after_bfd)->next)
799 if (!strcmp ((*after_bfd)->filename, posname))
801 if (realpos == pos_after)
802 after_bfd = &(*after_bfd)->next;
810 delete_members (files_to_delete)
811 char **files_to_delete;
813 bfd **current_ptr_ptr;
815 boolean something_changed = false;
816 for (; *files_to_delete != NULL; ++files_to_delete)
818 /* In a.out systems, the armap is optional. It's also called
819 __.SYMDEF. So if the user asked to delete it, we should remember
820 that fact. This isn't quite right for COFF systems (where
821 __.SYMDEF might be regular member), but it's very unlikely
822 to be a problem. FIXME */
824 if (!strcmp (*files_to_delete, "__.SYMDEF"))
826 inarch->has_armap = false;
832 current_ptr_ptr = &(inarch->next);
833 while (*current_ptr_ptr)
835 if (strcmp (*files_to_delete, (*current_ptr_ptr)->filename) == 0)
838 something_changed = true;
842 *current_ptr_ptr = ((*current_ptr_ptr)->next);
847 current_ptr_ptr = &((*current_ptr_ptr)->next);
851 if (verbose && found == false)
853 printf ("No member named `%s'\n", *files_to_delete);
859 if (something_changed == true)
866 /* Reposition existing members within an archive */
869 move_members (files_to_move)
870 char **files_to_move;
872 bfd **after_bfd; /* New entries go after this one */
873 bfd **current_ptr_ptr; /* cdr pointer into contents */
875 for (; *files_to_move; ++files_to_move)
877 current_ptr_ptr = &(inarch->next);
878 while (*current_ptr_ptr)
880 bfd *current_ptr = *current_ptr_ptr;
881 if (strcmp (normalize (*files_to_move), current_ptr->filename) == 0)
883 /* Move this file to the end of the list - first cut from
885 *current_ptr_ptr = current_ptr->next;
887 /* Now glue to end */
888 after_bfd = get_pos_bfd (&inarch->next, pos_end);
889 *after_bfd = current_ptr;
890 current_ptr->next = (bfd *) NULL;
893 printf ("m - %s\n", *files_to_move);
897 current_ptr_ptr = &((*current_ptr_ptr)->next);
899 fprintf (stderr, "%s: no entry %s in archive %s!\n",
900 program_name, *files_to_move, inarch->filename);
908 /* Ought to default to replacing in place, but this is existing practice! */
911 replace_members (files_to_move)
912 char **files_to_move;
914 bfd **after_bfd; /* New entries go after this one */
919 while (files_to_move && *files_to_move)
921 current_ptr = &inarch->next;
924 current = *current_ptr;
926 if (!strcmp (normalize (*files_to_move), current->filename))
930 struct stat fsbuf, asbuf;
932 if (current->arelt_data == NULL)
934 /* This can only happen if you specify a file on the
935 command line more than once. */
937 "%s: duplicate file specified: %s -- skipping\n",
938 program_name, *files_to_move);
942 if (stat (*files_to_move, &fsbuf) != 0)
945 bfd_fatal (*files_to_move);
948 if (bfd_stat_arch_elt (current, &asbuf) != 0)
949 fatal ("internal stat error on %s", current->filename);
951 if (fsbuf.st_mtime <= asbuf.st_mtime)
955 /* snip out this entry from the chain */
956 *current_ptr = current->next;
958 after_bfd = get_pos_bfd (&inarch->next, pos_end);
960 *after_bfd = bfd_openr (*files_to_move, NULL);
961 if (*after_bfd == (bfd *) NULL)
963 bfd_fatal (*files_to_move);
965 (*after_bfd)->next = temp;
969 printf ("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
974 current_ptr = &(current->next);
977 /* It isn't in there, so add to end */
979 after_bfd = get_pos_bfd (&inarch->next, pos_end);
981 *after_bfd = bfd_openr (*files_to_move, NULL);
982 if (*after_bfd == (bfd *) NULL)
984 bfd_fatal (*files_to_move);
988 printf ("c - %s\n", *files_to_move);
991 (*after_bfd)->next = temp;
1002 ranlib_only (archname)
1006 open_inarch (archname);
1011 /* Things which are interesting to map over all or some of the files: */
1017 print_arelt_descr (stdout, abfd, verbose);