#include "bfd.h"
#include "sysdep.h"
#include "libiberty.h"
+#include "progress.h"
#include "bucomm.h"
#include "aout/ar.h"
#include "libbfd.h"
/* Forward declarations */
+static const char *
+normalize PARAMS ((const char *, bfd *));
+
+static void
+remove_output PARAMS ((void));
+
static void
map_over_members PARAMS ((bfd *, void (*)(bfd *), char **, int));
pos_default, pos_before, pos_after, pos_end
} postype = pos_default;
+/* Whether to truncate names of files stored in the archive. */
+static boolean ar_truncate = false;
+
int interactive = 0;
void
if (count == 0)
{
for (head = arch->next; head; head = head->next)
- function (head);
+ {
+ PROGRESS (1);
+ function (head);
+ }
return;
}
/* This may appear to be a baroque way of accomplishing what we want.
for (; count > 0; files++, count--)
{
boolean found = false;
+
for (head = arch->next; head; head = head->next)
{
+ PROGRESS (1);
if (head->filename == NULL)
{
/* Some archive formats don't get the filenames filled in
do_show_version ()
{
printf ("GNU %s version %s\n", program_name, program_version);
- exit (0);
+ xexit (0);
}
void
else
fprintf (stderr, "\
Usage: %s [-vV] archive\n", program_name);
- exit (1);
+ list_supported_targets (program_name, stderr);
+ xexit (1);
+}
+
+/* Normalize a file name specified on the command line into a file
+ name which we will use in an archive. */
+
+static const char *
+normalize (file, abfd)
+ const char *file;
+ bfd *abfd;
+{
+ const char *filename;
+
+ filename = strrchr (file, '/');
+ if (filename != (char *) NULL)
+ filename++;
+ else
+ filename = file;
+
+ if (ar_truncate
+ && abfd != NULL
+ && strlen (filename) > abfd->xvec->ar_max_namelen)
+ {
+ char *s;
+
+ /* Space leak. */
+ s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
+ memcpy (s, filename, abfd->xvec->ar_max_namelen);
+ s[abfd->xvec->ar_max_namelen] = '\0';
+ filename = s;
+ }
+
+ return filename;
+}
+
+/* Remove any output file. This is only called via xatexit. */
+
+static char *output_filename = NULL;
+static FILE *output_file = NULL;
+static bfd *output_bfd = NULL;
+
+static void
+remove_output ()
+{
+ if (output_filename != NULL)
+ {
+ if (output_bfd != NULL && output_bfd->iostream != NULL)
+ fclose ((FILE *) (output_bfd->iostream));
+ if (output_file != NULL)
+ fclose (output_file);
+ unlink (output_filename);
+ }
}
/* The option parsing should be in its own function.
program_name = argv[0];
xmalloc_set_program_name (program_name);
+ START_PROGRESS (program_name, 0);
+
bfd_init ();
show_version = 0;
+ xatexit (remove_output);
+
temp = strrchr (program_name, '/');
if (temp == (char *) NULL)
temp = program_name; /* shouldn't happen, but... */
ranlib_touch (argv[arg_index]);
++arg_index;
}
- exit (0);
+ xexit (0);
}
else
is_ranlib = 0;
if (argc == 2 && strcmp (argv[1], "-M") == 0)
{
mri_emul ();
- exit (0);
+ xexit (0);
}
if (argc < 2)
case 'M':
mri_mode = 1;
break;
+ case 'f':
+ ar_truncate = true;
+ break;
default:
fprintf (stderr, "%s: illegal option -- %c\n", program_name, c);
usage ();
{
bfd *arch;
+ /* We can't write an armap when using ar q, so just do ar r
+ instead. */
+ if (operation == quick_append && write_armap)
+ operation = replace;
+
if ((operation == none || operation == print_table)
&& write_armap == 1)
{
ranlib_only (argv[2]);
- exit (0);
+ xexit (0);
}
if (operation == none)
files = arg_index < argc ? argv + arg_index : NULL;
+ /* We can't do a quick append if we need to construct an
+ extended name table, because do_quick_append won't be able to
+ rebuild the name table. Unfortunately, at this point we
+ don't actually know the maximum name length permitted by this
+ object file format. So, we guess. FIXME. */
+ if (operation == quick_append && ! ar_truncate)
+ {
+ char **chk;
+
+ for (chk = files; chk != NULL && *chk != '\0'; chk++)
+ {
+ if (strlen (normalize (*chk, (bfd *) NULL)) > 14)
+ {
+ operation = replace;
+ break;
+ }
+ }
+ }
+
if (operation == quick_append)
{
/* Note that quick appending to a non-existent archive creates it,
even if there are no files to append. */
do_quick_append (inarch_filename, files);
- exit (0);
+ xexit (0);
}
arch = open_inarch (inarch_filename);
default:
fprintf (stderr, "%s: internal error -- this option not implemented\n",
program_name);
- exit (1);
+ xexit (1);
}
}
- return 0;
-}
-static char *
-normalize (file)
- char *file;
-{
- char *filename = strrchr (file, '/');
- if (filename != (char *) NULL)
- {
- filename++;
- }
- else
- {
- filename = file;
- }
- return filename;
+ END_PROGRESS (program_name);
+
+ xexit (0);
+ return 0;
}
bfd *
next_one;
next_one = bfd_openr_next_archived_file (arch, next_one))
{
+ PROGRESS (1);
*last_one = next_one;
last_one = &next_one->next;
}
bfd *abfd;
{
int ncopied = 0;
+ char *cbuf = xmalloc (BUFSIZE);
struct stat buf;
long size;
if (bfd_stat_arch_elt (abfd, &buf) != 0)
size = buf.st_size;
while (ncopied < size)
{
- char cbuf[BUFSIZE];
+
int nread;
int tocopy = size - ncopied;
if (tocopy > BUFSIZE)
fwrite (cbuf, 1, nread, stdout);
ncopied += tocopy;
}
+ free (cbuf);
}
/* Extract a member of the archive into its own file.
bfd *abfd;
{
FILE *ostream;
- char cbuf[BUFSIZE];
+ char *cbuf = xmalloc (BUFSIZE);
int nread, tocopy;
int ncopied = 0;
long size;
if (size == 0)
{
/* Seems like an abstraction violation, eh? Well it's OK! */
+ output_filename = bfd_get_filename (abfd);
+
ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
if (!ostream)
{
perror (bfd_get_filename (abfd));
- exit (1);
+ xexit (1);
}
+
+ output_file = ostream;
}
else
while (ncopied < size)
if (!ostream)
{
/* Seems like an abstraction violation, eh? Well it's OK! */
+ output_filename = bfd_get_filename (abfd);
+
ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
if (!ostream)
{
perror (bfd_get_filename (abfd));
- exit (1);
+ xexit (1);
}
+
+ output_file = ostream;
}
fwrite (cbuf, 1, nread, ostream);
ncopied += tocopy;
}
fclose (ostream);
+
+ output_file = NULL;
+ output_filename = NULL;
+
chmod (bfd_get_filename (abfd), buf.st_mode);
if (preserve_dates)
#endif /* ! USE_UTIME */
#endif /* ! POSIX_UTIME */
}
+free (cbuf);
}
/* Just do it quickly; don't worry about dups, armap, or anything like that */
char **files_to_append;
{
FILE *ofile, *ifile;
- char buf[BUFSIZE];
+ char *buf = xmalloc (BUFSIZE);
long tocopy, thistime;
bfd *temp;
struct stat sbuf;
if (ofile == NULL)
{
perror (program_name);
- exit (1);
+ xexit (1);
}
temp = bfd_openr (archive_filename, NULL);
program_name, archive_filename);
}
+ if (ar_truncate)
+ temp->flags |= BFD_TRADITIONAL_FORMAT;
+
/* assume it's an achive, go straight to the end, sans $200 */
fseek (ofile, 0, 2);
}
fclose (ofile);
bfd_close (temp);
+ free (buf);
}
bfd *iarch;
{
bfd *obfd;
- int namelen = strlen (bfd_get_filename (iarch));
- char *old_name = xmalloc (namelen + 1);
- char *new_name = xmalloc (namelen + EXT_NAME_LEN);
+ char *old_name, *new_name;
bfd *contents_head = iarch->next;
+ old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
strcpy (old_name, bfd_get_filename (iarch));
- strcpy (new_name, bfd_get_filename (iarch));
+ new_name = make_tempname (old_name);
-#ifdef __GO32__ /* avoid long .extensions for MS-DOS */
- strcpy (new_name + namelen, "-a");
-#else
- strcpy (new_name + namelen, "-art");
-#endif
+ output_filename = new_name;
obfd = bfd_openw (new_name, bfd_get_target (iarch));
if (obfd == NULL)
bfd_fatal (old_name);
+ output_bfd = obfd;
+
bfd_set_format (obfd, bfd_archive);
/* Request writing the archive symbol table unless we've
been explicitly requested not to. */
obfd->has_armap = write_armap >= 0;
+ if (ar_truncate)
+ {
+ /* This should really use bfd_set_file_flags, but that rejects
+ archives. */
+ obfd->flags |= BFD_TRADITIONAL_FORMAT;
+ }
+
if (bfd_set_archive_head (obfd, contents_head) != true)
bfd_fatal (old_name);
if (!bfd_close (obfd))
bfd_fatal (old_name);
+ output_bfd = NULL;
+ output_filename = NULL;
+
/* We don't care if this fails; we might be creating the archive. */
bfd_close (iarch);
unlink (old_name);
while (*current_ptr_ptr)
{
bfd *current_ptr = *current_ptr_ptr;
- if (strcmp (normalize (*files_to_move), current_ptr->filename) == 0)
+ if (strcmp (normalize (*files_to_move, arch),
+ current_ptr->filename) == 0)
{
/* Move this file to the end of the list - first cut from
where it is. */
}
fprintf (stderr, "%s: no entry %s in archive %s!\n",
program_name, *files_to_move, arch->filename);
- exit (1);
+ xexit (1);
next_file:;
}
{
current = *current_ptr;
- if (!strcmp (normalize (*files_to_move), current->filename))
+ if (!strcmp (normalize (*files_to_move, arch),
+ normalize (current->filename, arch)))
{
if (newer_only)
{
if (verbose)
{
- printf ("%c - %s\n", (postype == pos_after ? 'r' : 'a'),
- *files_to_move);
+ printf ("r - %s\n", *files_to_move);
}
goto next_file;
}
}
if (verbose)
{
- printf ("c - %s\n", *files_to_move);
+ printf ("a - %s\n", *files_to_move);
}
(*after_bfd)->next = temp;
write_armap = 1;
arch = open_inarch (archname);
if (arch == NULL)
- exit (1);
+ xexit (1);
write_archive (arch);
}
|| ! bfd_check_format (arch, bfd_archive))
bfd_fatal (archname);
+ if (! bfd_has_map (arch))
+ fatal ("%s: no archive map to update", archname);
+
bfd_update_armap_timestamp (arch);
if (! bfd_close (arch))