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 */
49 /* Kludge declaration from BFD! This is ugly! FIXME! XXX */
52 bfd_special_undocumented_glue
PARAMS ((bfd
*abfd
, char *filename
));
54 /* Forward declarations */
57 print_contents
PARAMS ((bfd
* member
));
60 delete_members
PARAMS ((char **files_to_delete
));
63 do_quick_append
PARAMS ((char *archive_filename
, char **files_to_append
));
66 move_members
PARAMS ((char **files_to_move
));
69 replace_members
PARAMS ((char **files_to_replace
));
72 print_descr
PARAMS ((bfd
* abfd
));
75 ranlib_only
PARAMS ((char *archname
));
77 /** Globals and flags */
79 char *program_name
= NULL
;
80 bfd
*inarch
; /* The input arch we're manipulating */
83 /* This flag distinguishes between ar and ranlib:
84 1 means this is 'ranlib'; 0 means this is 'ar'.
85 -1 means if we should use argv[0] to decide. */
87 /* Nonzero means don't warn about creating the archive file if necessary. */
88 int silent_create
= 0;
89 /* Nonzero means describe each action performed. */
91 /* Nonzero means preserve dates of members when extracting them. */
92 int preserve_dates
= 0;
94 Nonzero means don't replace existing members whose dates are more recent
95 than the corresponding files.
98 /* write a __.SYMDEF member into the modified archive. */
99 boolean write_armap
= false;
101 Nonzero means don't update __.SYMDEF unless command line explicitly
104 int ignore_symdef
= 0;
106 Nonzero means it's the name of an existing member; position new or moved
107 files with respect to this one.
109 char *posname
= NULL
;
111 Sez how to use `posname': pos_before means position before that member.
112 pos_after means position after that member. pos_end means always at end.
113 pos_default means default appropriately. For the latter two, `posname'
117 pos_default
, pos_before
, pos_after
, pos_end
118 } postype
= pos_default
;
121 char *default_target
;
124 gnu960_verify_target(abfd
)
127 if ( abfd
->format
== bfd_unknown
){
128 bfd_check_format(abfd
, bfd_object
);
129 /* Don't really care if it's an object --
130 * just want to get the correct xvec.
133 if ( !BFD_COFF_FILE_P(abfd
) ){
134 fatal( "'%s' not a COFF file -- operation aborted",
144 interactive
= isatty(fileno(stdin
)) ;
149 If count is 0, then function is called once on each entry. if nonzero,
150 count is the length of the files chain; function is called on each entry
151 whose name matches one in files
154 DEFUN(map_over_members
,(function
, files
, count
),
155 void (*function
) () AND
162 for (head
= inarch
->next
; head
; head
= head
->next
)
167 This may appear to be a baroque way of accomplishing what we want.
168 however we have to iterate over the filenames in order to notice where
169 a filename is requested but does not exist in the archive. Ditto
170 mapping over each file each time -- we want to hack multiple
174 for (; count
> 0; files
++, count
--) {
175 boolean found
= false;
176 for (head
= inarch
->next
; head
; head
= head
->next
)
178 if (head
->filename
== NULL
)
180 /* Some archive formats don't get the filenames filled in
181 'till the elements are opened */
183 bfd_stat_arch_elt(head
, &buf
);
185 if ((head
->filename
!= NULL
) &&
186 (!strcmp(*files
, head
->filename
))) {
192 fprintf(stderr
, "No entry %s in archive.\n", *files
);
197 boolean operation_alters_arch
= false;
202 extern char *program_version
;
203 printf ("%s version %s\n", program_name
, program_version
);
207 The option parsing should be in its own function. It will be when I have
218 none
= 0, delete, replace
, print_table
,
219 print_files
, extract
, move
, quick_append
223 char *inarch_filename
;
230 check_v960( argc
, argv
);
231 default_target
= bfd_make_targ_name(BFD_COFF_FORMAT
,HOST_BYTE_ORDER_BIG_P
);
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 fatal("Too few command arguments.");
245 if (strcmp(argv
[1], "-V") == 0 || strcmp(argv
[1], "-v") == 0) {
251 ranlib_only(arg_ptr
);
254 if (argc
== 2 && strcmp(argv
[1],"-M") == 0) {
260 fatal("Too few command arguments.");
265 ++arg_ptr
; /* compatibility */
267 while (c
= *arg_ptr
++) {
276 if (operation
!= none
)
277 fatal("two different operation switches specified");
281 operation_alters_arch
= true;
285 operation_alters_arch
= true;
288 operation
= print_files
;
291 operation
= quick_append
;
292 operation_alters_arch
= true;
296 operation_alters_arch
= true;
299 operation
= print_table
;
329 postype
= pos_before
;
332 postype
= pos_before
;
339 fatal("invalid option %c", c
);
350 fatal("Too few command arguments.");
356 if ((operation
== none
|| operation
== print_table
)
357 && write_armap
== true)
358 ranlib_only(argv
[2]);
360 if (operation
== none
)
361 fatal("no operation specified");
363 if (newer_only
&& operation
!= replace
)
364 fatal("'u' only meaningful with 'r' option.");
368 if (postype
!= pos_default
)
369 posname
= argv
[arg_index
++];
371 inarch_filename
= argv
[arg_index
++];
373 if (arg_index
< argc
) {
374 files
= argv
+ arg_index
;
375 while (arg_index
< argc
)
376 if (!strcmp(argv
[arg_index
++], "__.SYMDEF")) {
384 if (operation
== quick_append
) {
386 do_quick_append(inarch_filename
, files
);
391 open_inarch(inarch_filename
);
396 map_over_members(print_descr
, files
, argc
- 3);
400 map_over_members(print_contents
, files
, argc
- 3);
404 map_over_members(extract_file
, files
, argc
- 3);
409 delete_members(files
);
418 if (files
!= NULL
|| write_armap
)
419 replace_members(files
);
422 /* Shouldn't happen! */
424 fprintf(stderr
, "Sorry; this option not implemented.\n");
431 char *normalize(file
)
434 char * filename
= strrchr(file
, '/');
435 if (filename
!= (char *)NULL
) {
445 open_inarch(archive_filename
)
446 char *archive_filename
;
451 bfd_error
= no_error
;
452 if (stat(archive_filename
, &sbuf
) != 0) {
454 bfd_fatal(archive_filename
);
455 if (!operation_alters_arch
) {
456 fprintf (stderr
, "%s: %s not found.\n", program_name
,
462 /* This routine is one way to forcibly create the archive. */
463 do_quick_append(archive_filename
, 0);
467 inarch
= bfd_openr(archive_filename
, default_target
);
469 inarch
= bfd_openr(archive_filename
, NULL
);
471 if (inarch
== NULL
) {
473 bfd_perror(archive_filename
);
477 if (bfd_check_format(inarch
, bfd_archive
) != true)
478 fatal("File %s is not an archive.", archive_filename
);
480 gnu960_verify_target(inarch
); /* Exits on failure */
482 last_one
= &(inarch
->next
);
483 /* Read all the contents right away, regardless. */
484 for (next_one
= bfd_openr_next_archived_file(inarch
, NULL
);
486 next_one
= bfd_openr_next_archived_file(inarch
, next_one
)) {
487 *last_one
= next_one
;
488 last_one
= &next_one
->next
;
490 *last_one
= (bfd
*) NULL
;
491 if (bfd_error
!= no_more_archived_files
)
507 if (bfd_stat_arch_elt(abfd
, &buf
) != 0)
508 fatal("Internal stat error on %s", abfd
->filename
);
511 printf("\n<member %s>\n\n", abfd
->filename
);
513 bfd_seek(abfd
, 0, SEEK_SET
);
516 while (ncopied
< size
) {
519 int tocopy
= size
- ncopied
;
520 if (tocopy
> BUFSIZE
)
523 nread
= bfd_read(cbuf
, 1, tocopy
, abfd
); /* oops -- broke
527 fatal("file %s not a valid archive", abfd
->my_archive
->filename
);
528 fwrite(cbuf
, 1, nread
, stdout
);
535 Extract a member of the archive into its own file.
537 We defer opening the new file until after we have read a BUFSIZ chunk of the
538 old one, since we know we have just read the archive header for the old
539 one. Since most members are shorter than BUFSIZ, this means we will read
540 the old header, read the old data, write a new inode for the new file, and
541 write the new data, and be done. This 'optimization' is what comes from
542 sitting next to a bare disk and hearing it every time it seeks. -- Gnu
557 if (bfd_stat_arch_elt(abfd
, &buf
) != 0)
558 fatal("Internal stat error on %s", abfd
->filename
);
562 printf("x - %s\n", abfd
->filename
);
564 bfd_seek(abfd
, 0, SEEK_SET
);
568 /* Seems like an abstraction violation, eh? Well it's OK! */
569 ostream
= fopen(abfd
->filename
, FOPEN_WB
);
571 perror(abfd
->filename
);
575 while (ncopied
< size
) {
576 tocopy
= size
- ncopied
;
577 if (tocopy
> BUFSIZE
)
580 nread
= bfd_read(cbuf
, 1, tocopy
, abfd
);
582 fatal("file %s not a valid archive", abfd
->my_archive
->filename
);
584 /* See comment above; this saves disk arm motion */
586 /* Seems like an abstraction violation, eh? Well it's OK! */
587 ostream
= fopen(abfd
->filename
, FOPEN_WB
);
589 perror(abfd
->filename
);
593 fwrite(cbuf
, 1, nread
, ostream
);
598 chmod(abfd
->filename
, buf
.st_mode
);
600 if (preserve_dates
) {
603 tb
.actime
= buf
.st_mtime
;
604 tb
.modtime
= buf
.st_mtime
;
605 utime(abfd
->filename
, tb
); /* FIXME check result */
606 #else /* ! POSIX_UTIME */
609 tb
[0] = buf
.st_mtime
;
610 tb
[1] = buf
.st_mtime
;
611 utime(abfd
->filename
, tb
); /* FIXME check result */
612 #else /* ! USE_UTIME */
613 struct timeval tv
[2];
614 tv
[0].tv_sec
= buf
.st_mtime
;
616 tv
[1].tv_sec
= buf
.st_mtime
;
618 utimes(abfd
->filename
, tv
); /* FIXME check result */
619 #endif /* ! USE_UTIME */
620 #endif /* ! POSIX_UTIME */
625 /* Just do it quickly; don't worry about dups, armap, or anything like that */
628 do_quick_append(archive_filename
, files_to_append
)
629 char *archive_filename
;
630 char **files_to_append
;
640 boolean newfile
= false;
641 bfd_error
= no_error
;
643 if (stat(archive_filename
, &sbuf
) != 0) {
645 bfd_fatal(archive_filename
);
650 ofile
= fopen(archive_filename
, FOPEN_AUB
);
652 perror(program_name
);
658 temp
= bfd_openr(archive_filename
, default_target
);
660 temp
= bfd_openr(archive_filename
, NULL
);
663 bfd_perror(archive_filename
);
666 if (newfile
== false) {
667 if (bfd_check_format(temp
, bfd_archive
) != true)
668 fatal("File %s is not an archive.", archive_filename
);
670 gnu960_verify_target(temp
); /* Exits on failure */
674 fwrite(ARMAG
, 1, SARMAG
, ofile
);
676 fprintf(stderr
, "%s: creating %s\n", program_name
, archive_filename
);
679 /* assume it's an achive, go straight to the end, sans $200 */
682 for (; files_to_append
&& *files_to_append
; ++files_to_append
) {
683 struct ar_hdr
*hdr
= bfd_special_undocumented_glue(temp
, *files_to_append
);
685 bfd_perror(*files_to_append
);
689 BFD_SEND(temp
, _bfd_truncate_arname
, (temp
, *files_to_append
, (char *) hdr
));
691 ifile
= fopen(*files_to_append
, FOPEN_RB
);
693 bfd_perror(program_name
);
695 if (stat(*files_to_append
, &sbuf
) != 0)
696 bfd_perror(*files_to_append
);
698 tocopy
= sbuf
.st_size
;
700 /* XXX should do error-checking! */
701 fwrite(hdr
, 1, sizeof(struct ar_hdr
), ofile
);
706 if (thistime
> BUFSIZE
)
708 fread(buf
, 1, thistime
, ifile
);
709 fwrite(buf
, 1, thistime
, ofile
);
713 if ((sbuf
.st_size
% 2) == 1)
725 int namelen
= strlen(inarch
->filename
);
726 char *new_name
= xmalloc(namelen
+ 6);
727 bfd
*contents_head
= inarch
->next
;
729 strcpy(new_name
, inarch
->filename
);
730 strcpy(new_name
+ namelen
, "-art");
731 obfd
= bfd_openw(new_name
,
732 /* FIXME: violates abstraction; need a better protocol */
733 (inarch
->xvec
? bfd_get_target(inarch
) : NULL
));
736 bfd_fatal(inarch
->filename
);
738 bfd_set_format(obfd
, bfd_archive
);
739 obfd
->has_armap
= write_armap
;
741 if (bfd_set_archive_head(obfd
, contents_head
) != true)
742 bfd_fatal(inarch
->filename
);
744 if (!bfd_close(obfd
))
745 bfd_fatal(inarch
->filename
);
747 /* We don't care if this fails, we might be creating the
749 (void) unlink(inarch
->filename
);
751 if (rename(new_name
, inarch
->filename
) != 0)
752 bfd_fatal(inarch
->filename
);
758 returns a pointer to the pointer to the entry which should be rplacd'd
759 into when altering. default_pos should be how to interpret pos_default,
760 and should be a pos value.
764 get_pos_bfd(contents
, default_pos
)
766 enum pos default_pos
;
768 bfd
**after_bfd
= contents
;
769 enum pos realpos
= (postype
== pos_default
? default_pos
: postype
);
771 if (realpos
== pos_end
) {
773 after_bfd
= &((*after_bfd
)->next
);
776 for ( ; *after_bfd
; after_bfd
= &(*after_bfd
)->next
)
777 if (!strcmp((*after_bfd
)->filename
, posname
)) {
778 if (realpos
== pos_after
)
779 after_bfd
= &(*after_bfd
)->next
;
788 delete_members(files_to_delete
)
789 char **files_to_delete
;
791 bfd
**current_ptr_ptr
;
793 boolean something_changed
= false;
794 for (; *files_to_delete
!= NULL
; ++files_to_delete
) {
796 In a.out systems, the armap is optional. It's also called
797 __.SYMDEF. So if the user asked to delete it, we should remember
798 that fact. The name is NULL in COFF archives, so using this as a
799 key is as good as anything I suppose
801 if (!strcmp(*files_to_delete
, "__.SYMDEF")) {
802 inarch
->has_armap
= false;
808 current_ptr_ptr
= &(inarch
->next
);
809 while (*current_ptr_ptr
) {
810 if (strcmp(*files_to_delete
, (*current_ptr_ptr
)->filename
) == 0) {
812 something_changed
= true;
816 *current_ptr_ptr
= ((*current_ptr_ptr
)->next
);
821 current_ptr_ptr
= &((*current_ptr_ptr
)->next
);
825 if (verbose
&& found
== false) {
826 printf("No member named `%s'\n", *files_to_delete
);
832 if (something_changed
== true) {
838 /* Reposition existing members within an archive */
841 move_members(files_to_move
)
842 char **files_to_move
;
844 bfd
**after_bfd
; /* New entries go after this one */
845 bfd
**current_ptr_ptr
; /* cdr pointer into contents */
850 for (; *files_to_move
; ++files_to_move
) {
851 current_ptr_ptr
= &(inarch
->next
);
852 while (*current_ptr_ptr
) {
853 bfd
*current_ptr
= *current_ptr_ptr
;
854 if (strcmp(normalize(*files_to_move
), current_ptr
->filename
) == 0) {
856 Move this file to the end of the list - first cut from
859 *current_ptr_ptr
= current_ptr
->next
;
861 /* Now glue to end */
862 after_bfd
= get_pos_bfd(&inarch
->next
, pos_end
);
863 *after_bfd
= current_ptr
;
864 current_ptr
->next
= (bfd
*) NULL
;
867 printf("m - %s\n", *files_to_move
);
871 current_ptr_ptr
= &((*current_ptr_ptr
)->next
);
873 fprintf(stderr
, "No entry %s in archive %s!\n",
874 *files_to_move
, inarch
->filename
);
883 /* Ought to default to replacing in place, but this is existing practice! */
886 replace_members(files_to_move
)
887 char **files_to_move
;
889 bfd
**after_bfd
; /* New entries go after this one */
894 If the first item in the archive is an __.SYMDEF then remove it
897 strcmp(inarch
->next
->filename
, "__.SYMDEF") == 0) {
898 inarch
->next
= inarch
->next
->next
;
903 while (files_to_move
&& *files_to_move
) {
904 current_ptr
= &inarch
->next
;
905 while (*current_ptr
) {
906 current
= *current_ptr
;
908 if (!strcmp(normalize(*files_to_move
), current
->filename
)) {
913 if (current
->arelt_data
== NULL
) {
914 /* This can only happen if you specify a file on the
915 command line more than once. */
916 fprintf (stderr
, "Duplicate file specified: %s -- skipping.\n", *files_to_move
);
920 if (stat(*files_to_move
, &fsbuf
) != 0) {
922 bfd_fatal(*files_to_move
);
925 if (bfd_stat_arch_elt(current
, &asbuf
) != 0)
926 fatal("Internal stat error on %s", current
->filename
);
928 if (fsbuf
.st_mtime
<= asbuf
.st_mtime
)
932 /* snip out this entry from the chain */
933 *current_ptr
= current
->next
;
935 after_bfd
= get_pos_bfd(&inarch
->next
, pos_end
);
937 *after_bfd
= bfd_openr(*files_to_move
, NULL
);
938 if (*after_bfd
== (bfd
*) NULL
) {
939 fprintf(stderr
, "Can't open file %s\n", *files_to_move
);
943 gnu960_verify_target(*after_bfd
); /* Exits on failure */
945 (*after_bfd
)->next
= temp
;
948 printf("%c - %s\n", (postype
== pos_after
? 'r' : 'a'),
953 current_ptr
= &(current
->next
);
956 /* It isn't in there, so add to end */
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
) {
962 fprintf(stderr
, "Can't open file %s\n", *files_to_move
);
966 gnu960_verify_target(*after_bfd
); /* Exits on failure */
969 printf("c - %s\n", *files_to_move
);
972 (*after_bfd
)->next
= temp
;
984 ranlib_only(archname
)
988 open_inarch(archname
);
995 /* Things which are interesting to map over all or some of the files: */
1001 print_arelt_descr(stdout
,abfd
, verbose
);