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", abfd
->my_archive
->filename
);
532 fwrite (cbuf
, 1, nread
, stdout
);
537 /* Extract a member of the archive into its own file.
539 We defer opening the new file until after we have read a BUFSIZ chunk of the
540 old one, since we know we have just read the archive header for the old
541 one. Since most members are shorter than BUFSIZ, this means we will read
542 the old header, read the old data, write a new inode for the new file, and
543 write the new data, and be done. This 'optimization' is what comes from
544 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", bfd_get_filename (abfd
));
562 printf ("x - %s\n", bfd_get_filename (abfd
));
564 bfd_seek (abfd
, 0, SEEK_SET
);
569 /* Seems like an abstraction violation, eh? Well it's OK! */
570 ostream
= fopen (bfd_get_filename (abfd
), FOPEN_WB
);
573 perror (bfd_get_filename (abfd
));
578 while (ncopied
< size
)
580 tocopy
= size
- ncopied
;
581 if (tocopy
> BUFSIZE
)
584 nread
= bfd_read (cbuf
, 1, tocopy
, abfd
);
586 fatal ("%s is not a valid archive", abfd
->my_archive
->filename
);
588 /* See comment above; this saves disk arm motion */
591 /* Seems like an abstraction violation, eh? Well it's OK! */
592 ostream
= fopen (bfd_get_filename (abfd
), FOPEN_WB
);
595 perror (bfd_get_filename (abfd
));
599 fwrite (cbuf
, 1, nread
, ostream
);
604 chmod (bfd_get_filename (abfd
), buf
.st_mode
);
610 tb
.actime
= buf
.st_mtime
;
611 tb
.modtime
= buf
.st_mtime
;
612 utime (bfd_get_filename (abfd
), &tb
); /* FIXME check result */
613 #else /* ! POSIX_UTIME */
616 tb
[0] = buf
.st_mtime
;
617 tb
[1] = buf
.st_mtime
;
618 utime (bfd_get_filename (abfd
), tb
); /* FIXME check result */
619 #else /* ! USE_UTIME */
620 struct timeval tv
[2];
621 tv
[0].tv_sec
= buf
.st_mtime
;
623 tv
[1].tv_sec
= buf
.st_mtime
;
625 utimes (bfd_get_filename (abfd
), tv
); /* FIXME check result */
626 #endif /* ! USE_UTIME */
627 #endif /* ! POSIX_UTIME */
631 /* Just do it quickly; don't worry about dups, armap, or anything like that */
634 do_quick_append (archive_filename
, files_to_append
)
635 char *archive_filename
;
636 char **files_to_append
;
640 long tocopy
, thistime
;
643 boolean newfile
= false;
644 bfd_error
= no_error
;
646 if (stat (archive_filename
, &sbuf
) != 0)
651 /* KLUDGE ALERT! Temporary fix until I figger why
652 * stat() is wrong ... think it's buried in GO32's IDT
657 bfd_fatal (archive_filename
);
663 ofile
= fopen (archive_filename
, FOPEN_AUB
);
666 perror (program_name
);
670 temp
= bfd_openr (archive_filename
, NULL
);
673 bfd_fatal (archive_filename
);
675 if (newfile
== false)
677 if (bfd_check_format (temp
, bfd_archive
) != true)
678 fatal ("%s is not an archive", archive_filename
);
682 fwrite (ARMAG
, 1, SARMAG
, ofile
);
684 fprintf (stderr
, "%s: creating %s\n",
685 program_name
, archive_filename
);
688 /* assume it's an achive, go straight to the end, sans $200 */
691 for (; files_to_append
&& *files_to_append
; ++files_to_append
)
693 struct ar_hdr
*hdr
= bfd_special_undocumented_glue (temp
, *files_to_append
);
696 bfd_fatal (*files_to_append
);
699 BFD_SEND (temp
, _bfd_truncate_arname
, (temp
, *files_to_append
, (char *) hdr
));
701 ifile
= fopen (*files_to_append
, FOPEN_RB
);
704 bfd_nonfatal (*files_to_append
);
707 if (stat (*files_to_append
, &sbuf
) != 0)
709 bfd_nonfatal (*files_to_append
);
712 tocopy
= sbuf
.st_size
;
714 /* XXX should do error-checking! */
715 fwrite (hdr
, 1, sizeof (struct ar_hdr
), ofile
);
720 if (thistime
> BUFSIZE
)
722 fread (buf
, 1, thistime
, ifile
);
723 fwrite (buf
, 1, thistime
, ofile
);
727 if ((sbuf
.st_size
% 2) == 1)
739 int namelen
= strlen (inarch
->filename
);
740 char *new_name
= xmalloc (namelen
+ EXT_NAME_LEN
);
741 bfd
*contents_head
= inarch
->next
;
743 strcpy (new_name
, inarch
->filename
);
745 #ifdef __GO32__ /* avoid long .extensions for MS-DOS */
746 strcpy (new_name
+ namelen
, "-a");
748 strcpy (new_name
+ namelen
, "-art");
751 obfd
= bfd_openw (new_name
,
752 /* FIXME: violates abstraction; need a better protocol */
753 (inarch
->xvec
? bfd_get_target (inarch
) : NULL
));
756 bfd_fatal (inarch
->filename
);
758 bfd_set_format (obfd
, bfd_archive
);
760 /* Request writing the archive symbol table unless we've
761 been explicitly requested not to. */
762 obfd
->has_armap
= write_armap
>= 0;
764 if (bfd_set_archive_head (obfd
, contents_head
) != true)
765 bfd_fatal (inarch
->filename
);
767 if (!bfd_close (obfd
))
768 bfd_fatal (inarch
->filename
);
770 /* We don't care if this fails; we might be creating the archive. */
771 unlink (inarch
->filename
);
773 if (rename (new_name
, inarch
->filename
) != 0)
774 bfd_fatal (inarch
->filename
);
777 /* Return a pointer to the pointer to the entry which should be rplacd'd
778 into when altering. DEFAULT_POS should be how to interpret pos_default,
779 and should be a pos value. */
782 get_pos_bfd (contents
, default_pos
)
784 enum pos default_pos
;
786 bfd
**after_bfd
= contents
;
787 enum pos realpos
= (postype
== pos_default
? default_pos
: postype
);
789 if (realpos
== pos_end
)
792 after_bfd
= &((*after_bfd
)->next
);
796 for (; *after_bfd
; after_bfd
= &(*after_bfd
)->next
)
797 if (!strcmp ((*after_bfd
)->filename
, posname
))
799 if (realpos
== pos_after
)
800 after_bfd
= &(*after_bfd
)->next
;
808 delete_members (files_to_delete
)
809 char **files_to_delete
;
811 bfd
**current_ptr_ptr
;
813 boolean something_changed
= false;
814 for (; *files_to_delete
!= NULL
; ++files_to_delete
)
816 /* In a.out systems, the armap is optional. It's also called
817 __.SYMDEF. So if the user asked to delete it, we should remember
818 that fact. This isn't quite right for COFF systems (where
819 __.SYMDEF might be regular member), but it's very unlikely
820 to be a problem. FIXME */
822 if (!strcmp (*files_to_delete
, "__.SYMDEF"))
824 inarch
->has_armap
= false;
830 current_ptr_ptr
= &(inarch
->next
);
831 while (*current_ptr_ptr
)
833 if (strcmp (*files_to_delete
, (*current_ptr_ptr
)->filename
) == 0)
836 something_changed
= true;
840 *current_ptr_ptr
= ((*current_ptr_ptr
)->next
);
845 current_ptr_ptr
= &((*current_ptr_ptr
)->next
);
849 if (verbose
&& found
== false)
851 printf ("No member named `%s'\n", *files_to_delete
);
857 if (something_changed
== true)
864 /* Reposition existing members within an archive */
867 move_members (files_to_move
)
868 char **files_to_move
;
870 bfd
**after_bfd
; /* New entries go after this one */
871 bfd
**current_ptr_ptr
; /* cdr pointer into contents */
873 for (; *files_to_move
; ++files_to_move
)
875 current_ptr_ptr
= &(inarch
->next
);
876 while (*current_ptr_ptr
)
878 bfd
*current_ptr
= *current_ptr_ptr
;
879 if (strcmp (normalize (*files_to_move
), current_ptr
->filename
) == 0)
881 /* Move this file to the end of the list - first cut from
883 *current_ptr_ptr
= current_ptr
->next
;
885 /* Now glue to end */
886 after_bfd
= get_pos_bfd (&inarch
->next
, pos_end
);
887 *after_bfd
= current_ptr
;
888 current_ptr
->next
= (bfd
*) NULL
;
891 printf ("m - %s\n", *files_to_move
);
895 current_ptr_ptr
= &((*current_ptr_ptr
)->next
);
897 fprintf (stderr
, "%s: no entry %s in archive %s!\n",
898 program_name
, *files_to_move
, inarch
->filename
);
906 /* Ought to default to replacing in place, but this is existing practice! */
909 replace_members (files_to_move
)
910 char **files_to_move
;
912 bfd
**after_bfd
; /* New entries go after this one */
917 while (files_to_move
&& *files_to_move
)
919 current_ptr
= &inarch
->next
;
922 current
= *current_ptr
;
924 if (!strcmp (normalize (*files_to_move
), current
->filename
))
928 struct stat fsbuf
, asbuf
;
930 if (current
->arelt_data
== NULL
)
932 /* This can only happen if you specify a file on the
933 command line more than once. */
935 "%s: duplicate file specified: %s -- skipping\n",
936 program_name
, *files_to_move
);
940 if (stat (*files_to_move
, &fsbuf
) != 0)
943 bfd_fatal (*files_to_move
);
946 if (bfd_stat_arch_elt (current
, &asbuf
) != 0)
947 fatal ("internal stat error on %s", current
->filename
);
949 if (fsbuf
.st_mtime
<= asbuf
.st_mtime
)
953 /* snip out this entry from the chain */
954 *current_ptr
= current
->next
;
956 after_bfd
= get_pos_bfd (&inarch
->next
, pos_end
);
958 *after_bfd
= bfd_openr (*files_to_move
, NULL
);
959 if (*after_bfd
== (bfd
*) NULL
)
961 bfd_fatal (*files_to_move
);
963 (*after_bfd
)->next
= temp
;
967 printf ("%c - %s\n", (postype
== pos_after
? 'r' : 'a'),
972 current_ptr
= &(current
->next
);
975 /* It isn't in there, so add to end */
977 after_bfd
= get_pos_bfd (&inarch
->next
, pos_end
);
979 *after_bfd
= bfd_openr (*files_to_move
, NULL
);
980 if (*after_bfd
== (bfd
*) NULL
)
982 bfd_fatal (*files_to_move
);
986 printf ("c - %s\n", *files_to_move
);
989 (*after_bfd
)->next
= temp
;
1000 ranlib_only (archname
)
1004 open_inarch (archname
);
1009 /* Things which are interesting to map over all or some of the files: */
1015 print_arelt_descr (stdout
, abfd
, verbose
);