1 /* ar.c - Archive modify and extract.
2 Copyright 1991, 1992 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
31 #include "../bfd/libbfd.h"
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 bfd
*inarch
; /* The input arch we're manipulating */
88 /* This flag distinguishes between ar and ranlib:
89 1 means this is 'ranlib'; 0 means this is 'ar'.
90 -1 means if we should use argv[0] to decide. */
92 /* Nonzero means don't warn about creating the archive file if necessary. */
93 int silent_create
= 0;
94 /* Nonzero means describe each action performed. */
96 /* Nonzero means preserve dates of members when extracting them. */
97 int preserve_dates
= 0;
99 Nonzero means don't replace existing members whose dates are more recent
100 than the corresponding files.
104 /* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
105 member). -1 means we've been explicitly asked to not write a symbol table;
106 +1 means we've been explictly asked to write it;
108 Traditionally, the default in BSD has been to not write the table.
109 However, for Posix.2 compliance the default is now to write a symbol table
110 if any of the members are object files. */
114 Nonzero means it's the name of an existing member; position new or moved
115 files with respect to this one.
117 char *posname
= NULL
;
119 Sez how to use `posname': pos_before means position before that member.
120 pos_after means position after that member. pos_end means always at end.
121 pos_default means default appropriately. For the latter two, `posname'
125 pos_default
, pos_before
, pos_after
, pos_end
126 } postype
= pos_default
;
132 interactive
= isatty(fileno(stdin
)) ;
137 If count is 0, then function is called once on each entry. if nonzero,
138 count is the length of the files chain; function is called on each entry
139 whose name matches one in files
142 DEFUN(map_over_members
,(function
, files
, count
),
143 void (*function
) () AND
150 for (head
= inarch
->next
; head
; head
= head
->next
)
155 This may appear to be a baroque way of accomplishing what we want.
156 however we have to iterate over the filenames in order to notice where
157 a filename is requested but does not exist in the archive. Ditto
158 mapping over each file each time -- we want to hack multiple
162 for (; count
> 0; files
++, count
--) {
163 boolean found
= false;
164 for (head
= inarch
->next
; head
; head
= head
->next
)
166 if (head
->filename
== NULL
)
168 /* Some archive formats don't get the filenames filled in
169 'till the elements are opened */
171 bfd_stat_arch_elt(head
, &buf
);
173 if ((head
->filename
!= NULL
) &&
174 (!strcmp(*files
, head
->filename
))) {
180 fprintf(stderr
, "no entry %s in archive\n", *files
);
185 boolean operation_alters_arch
= false;
187 extern char *program_version
;
192 printf ("GNU %s version %s\n", program_name
, program_version
);
201 Usage: %s [-]{dmpqrtx}[abcilosuvV] [member-name] archive-file file...\n\
202 %s -M [<mri-script]\n",
203 program_name
, program_name
);
206 Usage: %s [-vV] archive\n", program_name
);
211 The option parsing should be in its own function. It will be when I have
222 none
= 0, delete, replace
, print_table
,
223 print_files
, extract
, move
, quick_append
227 char *inarch_filename
;
234 program_name
= argv
[0];
236 temp
= strrchr(program_name
, '/');
237 if (temp
== (char *) NULL
)
238 temp
= program_name
; /* shouldn't happen, but... */
241 if (is_ranlib
> 0 || (is_ranlib
< 0 && strcmp(temp
, "ranlib") == 0)) {
243 if (argc
< 2 || argc
> 3)
246 if (strcmp(argv
[1], "-V") == 0 || strcmp(argv
[1], "-v") == 0)
248 ranlib_only(arg_ptr
);
253 if (argc
== 2 && strcmp(argv
[1],"-M") == 0) {
264 ++arg_ptr
; /* compatibility */
266 while ((c
= *arg_ptr
++) != '\0') {
275 if (operation
!= none
)
276 fatal("two different operation options specified");
280 operation_alters_arch
= true;
284 operation_alters_arch
= true;
287 operation
= print_files
;
290 operation
= quick_append
;
291 operation_alters_arch
= true;
295 operation_alters_arch
= true;
298 operation
= print_table
;
328 postype
= pos_before
;
331 postype
= pos_before
;
337 fprintf(stderr
, "%s: illegal option -- %c", program_name
, c
);
352 if ((operation
== none
|| operation
== print_table
)
354 ranlib_only(argv
[2]);
356 if (operation
== none
)
357 fatal("no operation specified");
359 if (newer_only
&& operation
!= replace
)
360 fatal("`u' is only meaningful with the `r' option.");
364 if (postype
!= pos_default
)
365 posname
= argv
[arg_index
++];
367 inarch_filename
= argv
[arg_index
++];
369 files
= arg_index
< argc
? argv
+ arg_index
: NULL
;
371 if (operation
== quick_append
)
373 /* Note that quick appending to a non-existent archive creates it,
374 even if there are no files to append. */
375 do_quick_append(inarch_filename
, files
);
379 open_inarch(inarch_filename
);
384 map_over_members(print_descr
, files
, argc
- 3);
388 map_over_members(print_contents
, files
, argc
- 3);
392 map_over_members(extract_file
, files
, argc
- 3);
397 delete_members(files
);
406 if (files
!= NULL
|| write_armap
> 0)
407 replace_members(files
);
410 /* Shouldn't happen! */
412 fprintf(stderr
, "%s: internal error -- this option not implemented\n",
421 char *normalize(file
)
424 char * filename
= strrchr(file
, '/');
425 if (filename
!= (char *)NULL
) {
435 open_inarch(archive_filename
)
436 char *archive_filename
;
441 bfd_error
= no_error
;
443 if (stat(archive_filename
, &sbuf
) != 0) {
447 /* KLUDGE ALERT! Temporary fix until I figger why
448 * stat() is wrong ... think it's buried in GO32's IDT
452 bfd_fatal(archive_filename
);
455 if (!operation_alters_arch
) {
456 fprintf (stderr
, "%s: ", program_name
);
457 perror (archive_filename
);
462 /* This routine is one way to forcibly create the archive. */
464 do_quick_append(archive_filename
, 0);
467 inarch
= bfd_openr(archive_filename
, NULL
);
468 if (inarch
== NULL
) {
472 fprintf (stderr
, "%s: ", program_name
);
473 bfd_perror(archive_filename
);
477 if (bfd_check_format(inarch
, bfd_archive
) != true)
478 fatal("%s is not an archive", archive_filename
);
479 last_one
= &(inarch
->next
);
480 /* Read all the contents right away, regardless. */
481 for (next_one
= bfd_openr_next_archived_file(inarch
, NULL
);
483 next_one
= bfd_openr_next_archived_file(inarch
, next_one
)) {
484 *last_one
= next_one
;
485 last_one
= &next_one
->next
;
487 *last_one
= (bfd
*) NULL
;
488 if (bfd_error
!= no_more_archived_files
)
504 if (bfd_stat_arch_elt(abfd
, &buf
) != 0)
505 fatal("internal stat error on %s", abfd
->filename
);
508 printf("\n<member %s>\n\n", abfd
->filename
);
510 bfd_seek(abfd
, 0, SEEK_SET
);
513 while (ncopied
< size
) {
516 int tocopy
= size
- ncopied
;
517 if (tocopy
> BUFSIZE
)
520 nread
= bfd_read(cbuf
, 1, tocopy
, abfd
); /* oops -- broke
524 fatal("%s is not a valid archive", abfd
->my_archive
->filename
);
525 fwrite(cbuf
, 1, nread
, stdout
);
532 Extract a member of the archive into its own file.
534 We defer opening the new file until after we have read a BUFSIZ chunk of the
535 old one, since we know we have just read the archive header for the old
536 one. Since most members are shorter than BUFSIZ, this means we will read
537 the old header, read the old data, write a new inode for the new file, and
538 write the new data, and be done. This 'optimization' is what comes from
539 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
554 if (bfd_stat_arch_elt(abfd
, &buf
) != 0)
555 fatal("internal stat error on %s", abfd
->filename
);
559 printf("x - %s\n", abfd
->filename
);
561 bfd_seek(abfd
, 0, SEEK_SET
);
565 /* Seems like an abstraction violation, eh? Well it's OK! */
566 ostream
= fopen(abfd
->filename
, FOPEN_WB
);
568 perror(abfd
->filename
);
572 while (ncopied
< size
) {
573 tocopy
= size
- ncopied
;
574 if (tocopy
> BUFSIZE
)
577 nread
= bfd_read(cbuf
, 1, tocopy
, abfd
);
579 fatal("%s is not a valid archive", abfd
->my_archive
->filename
);
581 /* See comment above; this saves disk arm motion */
583 /* Seems like an abstraction violation, eh? Well it's OK! */
584 ostream
= fopen(abfd
->filename
, FOPEN_WB
);
586 perror(abfd
->filename
);
590 fwrite(cbuf
, 1, nread
, ostream
);
595 chmod(abfd
->filename
, buf
.st_mode
);
597 if (preserve_dates
) {
600 tb
.actime
= buf
.st_mtime
;
601 tb
.modtime
= buf
.st_mtime
;
602 utime(abfd
->filename
, &tb
); /* FIXME check result */
603 #else /* ! POSIX_UTIME */
606 tb
[0] = buf
.st_mtime
;
607 tb
[1] = buf
.st_mtime
;
608 utime(abfd
->filename
, tb
); /* FIXME check result */
609 #else /* ! USE_UTIME */
610 struct timeval tv
[2];
611 tv
[0].tv_sec
= buf
.st_mtime
;
613 tv
[1].tv_sec
= buf
.st_mtime
;
615 utimes(abfd
->filename
, tv
); /* FIXME check result */
616 #endif /* ! USE_UTIME */
617 #endif /* ! POSIX_UTIME */
622 /* Just do it quickly; don't worry about dups, armap, or anything like that */
625 do_quick_append(archive_filename
, files_to_append
)
626 char *archive_filename
;
627 char **files_to_append
;
637 boolean newfile
= false;
638 bfd_error
= no_error
;
640 if (stat(archive_filename
, &sbuf
) != 0) {
644 /* KLUDGE ALERT! Temporary fix until I figger why
645 * stat() is wrong ... think it's buried in GO32's IDT
650 bfd_fatal(archive_filename
);
657 ofile
= fopen(archive_filename
, FOPEN_AUB
);
659 perror(program_name
);
663 temp
= bfd_openr(archive_filename
, NULL
);
665 fprintf (stderr
, "%s: ", program_name
);
666 bfd_perror(archive_filename
);
669 if (newfile
== false) {
670 if (bfd_check_format(temp
, bfd_archive
) != true)
671 fatal("%s is not an archive", archive_filename
);
674 fwrite(ARMAG
, 1, SARMAG
, ofile
);
676 fprintf(stderr
, "%s: creating %s\n",
677 program_name
, archive_filename
);
680 /* assume it's an achive, go straight to the end, sans $200 */
683 for (; files_to_append
&& *files_to_append
; ++files_to_append
) {
684 struct ar_hdr
*hdr
= bfd_special_undocumented_glue(temp
, *files_to_append
);
686 fprintf (stderr
, "%s: ", program_name
);
687 bfd_perror(*files_to_append
);
691 BFD_SEND(temp
, _bfd_truncate_arname
, (temp
, *files_to_append
, (char *) hdr
));
693 ifile
= fopen(*files_to_append
, FOPEN_RB
);
696 bfd_perror(program_name
);
699 if (stat(*files_to_append
, &sbuf
) != 0)
701 fprintf (stderr
, "%s: ", program_name
);
702 bfd_perror(*files_to_append
);
705 tocopy
= sbuf
.st_size
;
707 /* XXX should do error-checking! */
708 fwrite(hdr
, 1, sizeof(struct ar_hdr
), ofile
);
713 if (thistime
> BUFSIZE
)
715 fread(buf
, 1, thistime
, ifile
);
716 fwrite(buf
, 1, thistime
, ofile
);
720 if ((sbuf
.st_size
% 2) == 1)
732 int namelen
= strlen(inarch
->filename
);
733 char *new_name
= xmalloc(namelen
+ EXT_NAME_LEN
);
734 bfd
*contents_head
= inarch
->next
;
736 strcpy(new_name
, inarch
->filename
);
738 #ifdef __GO32__ /* avoid long .extensions for MS-DOS */
739 strcpy(new_name
+ namelen
, "-a");
741 strcpy(new_name
+ namelen
, "-art");
744 obfd
= bfd_openw(new_name
,
745 /* FIXME: violates abstraction; need a better protocol */
746 (inarch
->xvec
? bfd_get_target(inarch
) : NULL
));
749 bfd_fatal(inarch
->filename
);
751 bfd_set_format(obfd
, bfd_archive
);
753 /* Request writing the archive symbol table unless we've
754 been explicitly requested not to. */
755 obfd
->has_armap
= write_armap
>= 0;
757 if (bfd_set_archive_head(obfd
, contents_head
) != true)
758 bfd_fatal(inarch
->filename
);
760 if (!bfd_close(obfd
))
761 bfd_fatal(inarch
->filename
);
763 /* We don't care if this fails, we might be creating the
765 (void) unlink(inarch
->filename
);
767 if (rename(new_name
, inarch
->filename
) != 0)
768 bfd_fatal(inarch
->filename
);
774 returns a pointer to the pointer to the entry which should be rplacd'd
775 into when altering. default_pos should be how to interpret pos_default,
776 and should be a pos value.
780 get_pos_bfd(contents
, default_pos
)
782 enum pos default_pos
;
784 bfd
**after_bfd
= contents
;
785 enum pos realpos
= (postype
== pos_default
? default_pos
: postype
);
787 if (realpos
== pos_end
) {
789 after_bfd
= &((*after_bfd
)->next
);
792 for ( ; *after_bfd
; after_bfd
= &(*after_bfd
)->next
)
793 if (!strcmp((*after_bfd
)->filename
, posname
)) {
794 if (realpos
== pos_after
)
795 after_bfd
= &(*after_bfd
)->next
;
804 delete_members(files_to_delete
)
805 char **files_to_delete
;
807 bfd
**current_ptr_ptr
;
809 boolean something_changed
= false;
810 for (; *files_to_delete
!= NULL
; ++files_to_delete
) {
812 In a.out systems, the armap is optional. It's also called
813 __.SYMDEF. So if the user asked to delete it, we should remember
814 that fact. This isn't quite right for COFF systems (where
815 __.SYMDEF might be regular member), but it's very unlikely
816 to be a problem. FIXME */
818 if (!strcmp(*files_to_delete
, "__.SYMDEF")) {
819 inarch
->has_armap
= false;
825 current_ptr_ptr
= &(inarch
->next
);
826 while (*current_ptr_ptr
) {
827 if (strcmp(*files_to_delete
, (*current_ptr_ptr
)->filename
) == 0) {
829 something_changed
= true;
833 *current_ptr_ptr
= ((*current_ptr_ptr
)->next
);
838 current_ptr_ptr
= &((*current_ptr_ptr
)->next
);
842 if (verbose
&& found
== false) {
843 printf("No member named `%s'\n", *files_to_delete
);
849 if (something_changed
== true) {
855 /* Reposition existing members within an archive */
858 move_members(files_to_move
)
859 char **files_to_move
;
861 bfd
**after_bfd
; /* New entries go after this one */
862 bfd
**current_ptr_ptr
; /* cdr pointer into contents */
867 for (; *files_to_move
; ++files_to_move
) {
868 current_ptr_ptr
= &(inarch
->next
);
869 while (*current_ptr_ptr
) {
870 bfd
*current_ptr
= *current_ptr_ptr
;
871 if (strcmp(normalize(*files_to_move
), current_ptr
->filename
) == 0) {
873 Move this file to the end of the list - first cut from
876 *current_ptr_ptr
= current_ptr
->next
;
878 /* Now glue to end */
879 after_bfd
= get_pos_bfd(&inarch
->next
, pos_end
);
880 *after_bfd
= current_ptr
;
881 current_ptr
->next
= (bfd
*) NULL
;
884 printf("m - %s\n", *files_to_move
);
888 current_ptr_ptr
= &((*current_ptr_ptr
)->next
);
890 fprintf(stderr
, "%s: no entry %s in archive %s!\n",
891 program_name
, *files_to_move
, inarch
->filename
);
900 /* Ought to default to replacing in place, but this is existing practice! */
903 replace_members(files_to_move
)
904 char **files_to_move
;
906 bfd
**after_bfd
; /* New entries go after this one */
911 while (files_to_move
&& *files_to_move
) {
912 current_ptr
= &inarch
->next
;
913 while (*current_ptr
) {
914 current
= *current_ptr
;
916 if (!strcmp(normalize(*files_to_move
), current
->filename
)) {
921 if (current
->arelt_data
== NULL
) {
922 /* This can only happen if you specify a file on the
923 command line more than once. */
924 fprintf (stderr
, "%s: duplicate file specified: %s -- skipping\n", program_name
, *files_to_move
);
928 if (stat(*files_to_move
, &fsbuf
) != 0) {
930 bfd_fatal(*files_to_move
);
933 if (bfd_stat_arch_elt(current
, &asbuf
) != 0)
934 fatal("internal stat error on %s", current
->filename
);
936 if (fsbuf
.st_mtime
<= asbuf
.st_mtime
)
940 /* snip out this entry from the chain */
941 *current_ptr
= current
->next
;
943 after_bfd
= get_pos_bfd(&inarch
->next
, pos_end
);
945 *after_bfd
= bfd_openr(*files_to_move
, NULL
);
946 if (*after_bfd
== (bfd
*) NULL
) {
947 fprintf(stderr
, "%s: ", program_name
);
948 bfd_perror (*files_to_move
);
951 (*after_bfd
)->next
= temp
;
954 printf("%c - %s\n", (postype
== pos_after
? 'r' : 'a'),
959 current_ptr
= &(current
->next
);
962 /* It isn't in there, so add to end */
964 after_bfd
= get_pos_bfd(&inarch
->next
, pos_end
);
966 *after_bfd
= bfd_openr(*files_to_move
, NULL
);
967 if (*after_bfd
== (bfd
*) NULL
) {
968 fprintf(stderr
, "%s: ", program_name
);
969 bfd_perror (*files_to_move
);
973 printf("c - %s\n", *files_to_move
);
976 (*after_bfd
)->next
= temp
;
988 ranlib_only(archname
)
992 open_inarch(archname
);
999 /* Things which are interesting to map over all or some of the files: */
1005 print_arelt_descr(stdout
,abfd
, verbose
);