]> Git Repo - binutils.git/blobdiff - binutils/ar.c
misc fixes
[binutils.git] / binutils / ar.c
index 9a8a5281be09565f3735dfaf6f80d7ca4d6a0009..c77abb97bb81447ec1bd7b29470a252e824d4851 100644 (file)
@@ -1,7 +1,22 @@
+/* ar.c - Archive modify and extract.
+   Copyright 1991, 1992 Free Software Foundation, Inc.
 
+This file is part of GNU Binutils.
 
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
-/* ar.c - Archive modify and extract. */
 /*
    Bugs: should use getopt the way tar does (complete w/optional -) and
    should have long options too. GNU ar used to check file against filesystem
    when name truncated. No way to specify pos_end. Error messages should be
    more consistant.
 */
-#include "sysdep.h"
 #include "bfd.h"
-#include "ar.h"
+#include "sysdep.h"
+#include "bucomm.h"
+#include "aout/ar.h"
+#include "../bfd/libbfd.h"
+#include "arsup.h"
 #include <stdio.h>
+#ifdef POSIX_UTIME
+#include <utime.h>
+#else /* ! POSIX_UTIME */
+#ifdef USE_UTIME
+#include <time.h>
+#else /* ! USE_UTIME */
 #include <sys/time.h>
+#endif /* ! USE_UTIME */
+#endif /* ! POSIX_UTIME */
 #include <errno.h>
+#ifndef errno
+extern int errno;
+#endif
 #define BUFSIZE 8192
-/* Not great to have these here.  Should they be exported or not? */
-PROTO(size_t, bfd_read, (void *ptr, size_t size, size_t nitems, bfd * abfd));
-PROTO(size_t, bfd_write, (void *ptr, size_t size, size_t nitems, bfd * abfd));
-/* PROTO (void, open_inarch, (char *archive_filename)); */
-#ifdef __STDC__
-static void     open_inarch(char *archive_filename);
-#else
-static void     open_inarch();
-#endif                         /* __STDC__ */
-
-PROTO(void, map_over_members, (void (*function) (), char **files, int count));
-PROTO(void, print_contents, (bfd * member));
-PROTO(void, extract_file, (bfd * abfd));
-PROTO(void, delete_members, (char **files_to_delete));
-PROTO(void, do_quick_append, (char *archive_filename, char **files_to_append));
-PROTO(void, move_members, (char **files_to_move));
-PROTO(void, replace_members, (char **files_to_replace));
-PROTO(void, print_descr, (bfd * abfd));
-PROTO(void, ranlib_only, (char *archname));
+
+/* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
+
+struct ar_hdr *
+bfd_special_undocumented_glue PARAMS ((bfd *abfd, char *filename));
+
+/* Forward declarations */
+
+static void
+print_contents PARAMS ((bfd * member));
+
+static void
+delete_members PARAMS ((char **files_to_delete));
+
+static void
+do_quick_append PARAMS ((char *archive_filename, char **files_to_append));
+
+static void
+move_members PARAMS ((char **files_to_move));
+
+static void
+replace_members PARAMS ((char **files_to_replace));
+
+static void
+print_descr PARAMS ((bfd * abfd));
+
+static void
+ranlib_only PARAMS ((char *archname));
 
 /** Globals and flags */
 
 char           *program_name = NULL;
-bfd             bogus_archive;
 bfd            *inarch;                /* The input arch we're manipulating */
 
+int mri_mode;
+/* This flag distinguishes between ar and ranlib:
+   1 means this is 'ranlib'; 0 means this is 'ar'.
+   -1 means if we should use argv[0] to decide. */
+extern int is_ranlib;
 /* Nonzero means don't warn about creating the archive file if necessary.  */
 int             silent_create = 0;
 /* Nonzero means describe each action performed.  */
@@ -53,13 +95,16 @@ int             preserve_dates = 0;
    than the corresponding files.
 */
 int             newer_only = 0;
-/* write a __.SYMDEF member into the modified archive.  */
-boolean         write_armap = false;
-/*
-   Nonzero means don't update __.SYMDEF unless command line explicitly
-   requested it
-*/
-int             ignore_symdef = 0;
+
+/* Controls the writing of an archive symbol table (in BSD: a __.SYMDEF
+   member).  -1 means we've been explicitly asked to not write a symbol table;
+   +1 means we've been explictly asked to write it;
+   0 is the default.
+   Traditionally, the default in BSD has been to not write the table.
+   However, for Posix.2 compliance the default is now to write a symbol table
+   if any of the members are object files. */
+int write_armap = 0;
+
 /*
    Nonzero means it's the name of an existing member; position new or moved
    files with respect to this one.
@@ -75,6 +120,103 @@ enum pos {
     pos_default, pos_before, pos_after, pos_end
 }               postype = pos_default;
 
+#ifdef GNU960
+       char *default_target;
+
+       void
+       gnu960_verify_target(abfd)
+       bfd *abfd;
+       {
+           if ( abfd->format == bfd_unknown ){
+               bfd_check_format(abfd, bfd_object);
+               /* Don't really care if it's an object --
+                * just want to get the correct xvec.
+                */
+           }
+           if ( !BFD_COFF_FILE_P(abfd) ){
+               fatal( "'%s' not a COFF file -- operation aborted",
+                                                       abfd->filename );
+           }
+       }
+#endif
+
+int interactive = 0;
+void
+DEFUN_VOID(mri_emul)
+{
+  interactive = isatty(fileno(stdin)) ;
+  yyparse();
+}
+
+/*
+   If count is 0, then function is called once on each entry. if nonzero,
+   count is the length of the files chain; function is called on each entry
+   whose name matches one in files
+*/
+void
+DEFUN(map_over_members,(function, files, count),
+      void            (*function) () AND
+      char          **files AND
+      int             count)
+{
+  bfd            *head;
+
+  if (count == 0) {
+    for (head = inarch->next; head; head = head->next)
+     function(head);
+    return;
+  }
+  /*
+    This may appear to be a baroque way of accomplishing what we want.
+    however we have to iterate over the filenames in order to notice where
+    a filename is requested but does not exist in the archive.  Ditto
+    mapping over each file each time -- we want to hack multiple
+    references.
+    */
+
+  for (; count > 0; files++, count--) {
+    boolean         found = false;
+    for (head = inarch->next; head; head = head->next)
+    {
+      if (head->filename == NULL)
+      {
+       /* Some archive formats don't get the filenames filled in
+          'till the elements are opened */
+       struct stat buf;
+       bfd_stat_arch_elt(head, &buf);
+      }
+      if ((head->filename != NULL) &&
+         (!strcmp(*files, head->filename))) {
+       found = true;
+       function(head);
+      }
+    }
+    if (!found)
+     fprintf(stderr, "No entry %s in archive.\n", *files);
+  }
+}
+
+
+boolean operation_alters_arch = false;
+
+extern char *program_version;
+
+void
+do_show_version ()
+{
+  printf ("%s version %s\n", program_name, program_version);
+}
+
+void
+usage ()
+{
+  fprintf(stderr, "ar %s\n\
+Usage: %s [-]{dmpqrtx}[abcilosuv] [member-name] archive-file file...\n\
+       %s -M [<mri-script]\n",
+         program_version, program_name, program_name);
+  exit(1);
+}
+
 /*
    The option parsing should be in its own function.  It will be when I have
    getopt working.
@@ -84,185 +226,210 @@ main(argc, argv)
     int             argc;
     char          **argv;
 {
-    char           *arg_ptr;
-    char            c;
-    enum {
-       none = 0, delete, replace, print_table,
-       print_files, extract, move, quick_append
-    }               operation = none;
-    int             arg_index;
-    char          **files;
-    char           *inarch_filename;
-    char           *temp;
-    program_name = argv[0];
-
-
-    temp = strrchr(program_name, '/');
-    if (temp == (char *) NULL)
-       temp = program_name;    /* shouldn't happen, but... */
-    else
-       ++temp;
-    if (!strcmp(temp, "ranlib")) {
-       if (argc < 2)
-           fatal("Too few command arguments.");
-       ranlib_only(argv[1]);
-    }
-
+  char           *arg_ptr;
+  char            c;
+  enum {
+    none = 0, delete, replace, print_table,
+    print_files, extract, move, quick_append
+  }               operation = none;
+  int             arg_index;
+  char          **files;
+  char           *inarch_filename;
+  char           *temp;
+  int           show_version;
+
+  bfd_init();
+  show_version = 0;
+#ifdef GNU960
+  check_v960( argc, argv );
+  default_target = bfd_make_targ_name(BFD_COFF_FORMAT,HOST_BYTE_ORDER_BIG_P);
+#endif
 
-    if (argc < 3)
-       fatal("Too few command arguments.");
+  program_name = argv[0];
 
+  temp = strrchr(program_name, '/');
+  if (temp == (char *) NULL)
+   temp = program_name;                /* shouldn't happen, but... */
+  else
+   ++temp;
+  if (is_ranlib > 0 || (is_ranlib < 0 && strcmp(temp, "ranlib") == 0)) {
+    if (argc < 2)
+      usage ();
     arg_ptr = argv[1];
+    if (strcmp(argv[1], "-V") == 0 || strcmp(argv[1], "-v") == 0) {
+      do_show_version();
+      if (argc == 2)
+       exit(0);
+      arg_ptr = argv[2];
+    }
+    ranlib_only(arg_ptr);
+  }
 
-    if (*arg_ptr == '-')
-       ++arg_ptr;              /* compatibility */
-
-    while (c = *arg_ptr++) {
-       switch (c) {
-       case 'd':
-       case 'm':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 't':
-       case 'x':
-           if (operation != none)
-               fatal("two different operation switches specified");
-           switch (c) {
-           case 'd':
-               operation = delete;
-               break;
-           case 'm':
-               operation = move;
-               break;
-           case 'p':
-               operation = print_files;
-               break;
-           case 'q':
-               operation = quick_append;
-               break;
-           case 'r':
-               operation = replace;
-               break;
-           case 't':
-               operation = print_table;
-               break;
-           case 'x':
-               operation = extract;
-               break;
-           }
-       case 'l':
-           break;
-       case 'c':
-           silent_create = 1;
-           break;
-       case 'o':
-           preserve_dates = 1;
-           break;
-       case 's':
-           write_armap = true;
-           break;
-       case 'u':
-           newer_only = 1;
-           break;
-       case 'v':
-           verbose = 1;
-           break;
-       case 'a':
-           postype = pos_after;
-           break;
-       case 'b':
-           postype = pos_before;
-           break;
-       case 'i':
-           postype = pos_before;
-           break;
-       default:
-           fatal("invalid option %c", c);
-       }
+  if (argc == 2 && strcmp(argv[1],"-M") == 0) {
+    mri_emul();
+    exit(0);
+  }
+
+  if (argc < 2)
+    usage ();
+
+  arg_ptr = argv[1];
+
+  if (*arg_ptr == '-')
+   ++arg_ptr;                  /* compatibility */
+
+  while (c = *arg_ptr++) {
+    switch (c) {
+     case 'd':
+     case 'm':
+     case 'p':
+     case 'q':
+     case 'r':
+     case 't':
+     case 'x':
+      if (operation != none)
+       fatal("two different operation switches specified");
+      switch (c) {
+       case 'd':
+       operation = delete;
+       operation_alters_arch = true;
+       break;
+       case 'm':
+       operation = move;
+       operation_alters_arch = true;
+       break;
+       case 'p':
+       operation = print_files;
+       break;
+       case 'q':
+       operation = quick_append;
+       operation_alters_arch = true;
+       break;
+       case 'r':
+       operation = replace;
+       operation_alters_arch = true;
+       break;
+       case 't':
+       operation = print_table;
+       break;
+       case 'x':
+       operation = extract;
+       break;
+      }
+     case 'l':
+      break;
+     case 'c':
+      silent_create = 1;
+      break;
+     case 'o':
+      preserve_dates = 1;
+      break;
+     case 'V':
+      show_version = true;
+      break;
+     case 's':
+      write_armap = 1;
+      break;
+     case 'u':
+      newer_only = 1;
+      break;
+     case 'v':
+      verbose = 1;
+      break;
+     case 'a':
+      postype = pos_after;
+      break;
+     case 'b':
+      postype = pos_before;
+      break;
+     case 'i':
+      postype = pos_before;
+      break;
+     case 'M':
+
+      mri_mode = 1;
+      break;
+     default:
+      fatal("invalid option %c", c);
     }
+  }
 
-    if (operation == none && write_armap)
-       ranlib_only(argv[2]);
+  if (show_version)
+     do_show_version();
+
+  if (argc < 3)
+    if (show_version)
+       exit(0);
+    else
+      usage ();
+
+  if (mri_mode) {
+    mri_emul();
+  }
+  else {
+    if ((operation == none || operation == print_table) 
+       && write_armap == 1)
+     ranlib_only(argv[2]);
 
     if (operation == none)
-       fatal("no operation specified");
+     fatal("no operation specified");
 
     if (newer_only && operation != replace)
-       fatal("'u' only meaningful with 'r' option.");
+     fatal("'u' only meaningful with 'r' option.");
 
     arg_index = 2;
 
     if (postype != pos_default)
-       posname = argv[arg_index++];
+     posname = argv[arg_index++];
 
     inarch_filename = argv[arg_index++];
 
-    if (arg_index < argc) {
-       files = argv + arg_index;
-       while (arg_index < argc)
-           if (!strcmp(argv[arg_index++], "__.SYMDEF")) {
-               ignore_symdef = 1;
-               break;
-           }
-    }
-    else
-       files = NULL;
+    files = arg_index < argc ? argv + arg_index : NULL;
 
     if (operation == quick_append) {
-       if (files != NULL)
-           do_quick_append(inarch_filename, files);
-       exit(0);
+      if (files != NULL)
+       do_quick_append(inarch_filename, files);
+      exit(0);
     }
 
 
     open_inarch(inarch_filename);
-    /*
-       If we have no archive, and we've been asked to replace then create one
-    */
-
-    if (operation == replace &&
-       inarch == &bogus_archive) {
-       silent_create = 1;
-       do_quick_append(inarch_filename, 0);
-       open_inarch(inarch_filename);
-    }
 
     switch (operation) {
 
-    case print_table:
-       map_over_members(print_descr, files, argc - 3);
-       break;
+     case print_table:
+      map_over_members(print_descr, files, argc - 3);
+      break;
 
-    case print_files:
-       map_over_members(print_contents, files, argc - 3);
-       break;
+     case print_files:
+      map_over_members(print_contents, files, argc - 3);
+      break;
 
-    case extract:
-       map_over_members(extract_file, files, argc - 3);
-       break;
+     case extract:
+      map_over_members(extract_file, files, argc - 3);
+      break;
 
-    case delete:
-       if (files != NULL)
-           delete_members(files);
-       break;
+     case delete:
+      if (files != NULL)
+       delete_members(files);
+      break;
 
-    case move:
-       if (files != NULL)
-           move_members(files);
-       break;
+     case move:
+      if (files != NULL)
+       move_members(files);
+      break;
 
-    case replace:
-       if (files != NULL || write_armap)
-           replace_members(files);
-       break;
+     case replace:
+      if (files != NULL || write_armap > 0)
+       replace_members(files);
+      break;
 
-       /* Shouldn't happen! */
-    default:
-       fprintf(stderr, "Sorry; this option not implemented.\n");
+      /* Shouldn't happen! */
+     default:
+      fprintf(stderr, "Sorry; this option not implemented.\n");
     }
-
-    return (0);
+  }
+  return (0);
 }                              /* main() */
 
 static
@@ -279,7 +446,7 @@ char *file;
     return filename;
 }
 
-static void
+int 
 open_inarch(archive_filename)
     char           *archive_filename;
 {
@@ -290,94 +457,53 @@ open_inarch(archive_filename)
     if (stat(archive_filename, &sbuf) != 0) {
        if (errno != ENOENT)
            bfd_fatal(archive_filename);
-       if (!silent_create)
-           fprintf(stderr,
-                   "%s: creating %s\n", program_name, archive_filename);
-
-       inarch = &bogus_archive;
-       inarch->filename = archive_filename;
-       inarch->has_armap = true;
-
+       if (!operation_alters_arch) {
+         fprintf (stderr, "%s: %s not found.\n", program_name,
+                  archive_filename);
+         maybequit();
+         return 0;
+       }       
+
+       /* This routine is one way to forcibly create the archive. */
+       do_quick_append(archive_filename, 0);
     }
-    else {
-       inarch = bfd_openr(archive_filename, NULL);
-       if (inarch == NULL) {
-    bloser:
-           bfd_perror(archive_filename);
-           exit(1);
-       }
-
-       if (bfd_check_format(inarch, bfd_archive) != true)
-           fatal("File %s is not an archive.", archive_filename);
-       last_one = &(inarch->next);
-       /* Read all the contents right away, regardless. */
-       for (next_one = bfd_openr_next_archived_file(inarch, NULL);
-            next_one;
-            next_one = bfd_openr_next_archived_file(inarch, next_one)) {
-           *last_one = next_one;
-           last_one = &next_one->next;
-       }
-       *last_one = (bfd *) NULL;
-       if (bfd_error != no_more_archived_files)
-           goto bloser;
-    }
-}
-
-
 
-/*
-   If count is 0, then function is called once on each entry. if nonzero,
-   count is the length of the files chain; function is called on each entry
-   whose name matches one in files
-*/
-void
-map_over_members(function, files, count)
-    void            (*function) ();
-    char          **files;
-    int             count;
-{
-    bfd            *head;
-
-
-
-
-    if (count == 0) {
-       for (head = inarch->next; head; head = head->next)
-           function(head);
-       return;
+#ifdef GNU960
+    inarch = bfd_openr(archive_filename, default_target);
+#else
+    inarch = bfd_openr(archive_filename, NULL);
+#endif
+    if (inarch == NULL) {
+      bloser:
+        fprintf (stderr, "%s: ", program_name);
+       bfd_perror(archive_filename);
+       exit(1);
     }
-    /*
-       This may appear to be a baroque way of accomplishing what we want.
-       however we have to iterate over the filenames in order to notice where
-       a filename is requested but does not exist in the archive.  Ditto
-       mapping over each file each time -- we want to hack multiple
-       references.
-    */
 
-    for (; count > 0; files++, count--) {
-       boolean         found = false;
-       for (head = inarch->next; head; head = head->next)
-           if ((head->filename != NULL) &&
-               (!strcmp(*files, head->filename))) {
-               found = true;
-               function(head);
-           }
-       if (!found)
-           fprintf(stderr, "No entry %s in archive.\n", *files);
+    if (bfd_check_format(inarch, bfd_archive) != true)
+       fatal("File %s is not an archive.", archive_filename);
+#ifdef GNU960
+    gnu960_verify_target(inarch);      /* Exits on failure */
+#endif
+    last_one = &(inarch->next);
+    /* Read all the contents right away, regardless. */
+    for (next_one = bfd_openr_next_archived_file(inarch, NULL);
+        next_one;
+        next_one = bfd_openr_next_archived_file(inarch, next_one)) {
+       *last_one = next_one;
+       last_one = &next_one->next;
     }
+    *last_one = (bfd *) NULL;
+    if (bfd_error != no_more_archived_files)
+       goto bloser;
+    return 1;
 }
 
 
-/* Things which are interesting to map over all or some of the files: */
 
-void
-print_descr(abfd)
-    bfd            *abfd;
-{
-    print_arelt_descr(abfd, verbose);
-}
 
-void
+
+static void
 print_contents(abfd)
     bfd            *abfd;
 {
@@ -444,6 +570,14 @@ extract_file(abfd)
     bfd_seek(abfd, 0, SEEK_SET);
 
     ostream = 0;
+    if (size == 0) {
+      /* Seems like an abstraction violation, eh?  Well it's OK! */
+      ostream = fopen(abfd->filename, FOPEN_WB);
+      if (!ostream) {
+       perror(abfd->filename);
+       exit(1);
+      }
+    } else
     while (ncopied < size) {
        tocopy = size - ncopied;
        if (tocopy > BUFSIZE)
@@ -456,13 +590,12 @@ extract_file(abfd)
        /* See comment above; this saves disk arm motion */
        if (!ostream) {
            /* Seems like an abstraction violation, eh?  Well it's OK! */
-           ostream = fopen(abfd->filename, "w");
+           ostream = fopen(abfd->filename, FOPEN_WB);
            if (!ostream) {
                perror(abfd->filename);
                exit(1);
            }
        }
-       /* no need to byte-swap; the two formats are presumably compatible(!) */
        fwrite(cbuf, 1, nread, ostream);
        ncopied += tocopy;
     }
@@ -471,30 +604,33 @@ extract_file(abfd)
     chmod(abfd->filename, buf.st_mode);
 
     if (preserve_dates) {
-#ifdef USG
+#ifdef POSIX_UTIME
+        struct utimbuf tb;
+       tb.actime = buf.st_mtime;
+       tb.modtime = buf.st_mtime;
+       utime(abfd->filename, &tb);     /* FIXME check result */
+#else /* ! POSIX_UTIME */
+#ifdef USE_UTIME
        long            tb[2];
        tb[0] = buf.st_mtime;
        tb[1] = buf.st_mtime;
        utime(abfd->filename, tb);      /* FIXME check result */
-#else
+#else /* ! USE_UTIME */
        struct timeval  tv[2];
        tv[0].tv_sec = buf.st_mtime;
        tv[0].tv_usec = 0;
        tv[1].tv_sec = buf.st_mtime;
        tv[1].tv_usec = 0;
        utimes(abfd->filename, tv);     /* FIXME check result */
-#endif
+#endif /* ! USE_UTIME */
+#endif /* ! POSIX_UTIME */
     }
 }
 
 
 /* Just do it quickly; don't worry about dups, armap, or anything like that */
 
-/* This is ugly! XXX */
-
-PROTO(struct ar_hdr *, bfd_special_undocumented_glue, (char *filename));
-
-void
+static void
 do_quick_append(archive_filename, files_to_append)
     char           *archive_filename;
     char          **files_to_append;
@@ -517,21 +653,29 @@ do_quick_append(archive_filename, files_to_append)
     }
 
 
-    ofile = fopen(archive_filename, "a+");
+    ofile = fopen(archive_filename, FOPEN_AUB);
     if (ofile == NULL) {
        perror(program_name);
        exit(1);
     }
 
     /* bletch */
+#ifdef GNU960
+    temp = bfd_openr(archive_filename, default_target);
+#else
     temp = bfd_openr(archive_filename, NULL);
+#endif
     if (temp == NULL) {
+        fprintf (stderr, "%s: ", program_name);
        bfd_perror(archive_filename);
        exit(1);
     }
     if (newfile == false) {
        if (bfd_check_format(temp, bfd_archive) != true)
            fatal("File %s is not an archive.", archive_filename);
+#ifdef GNU960
+       gnu960_verify_target(temp);     /* Exits on failure */
+#endif
     }
     else {
        fwrite(ARMAG, 1, SARMAG, ofile);
@@ -543,20 +687,26 @@ do_quick_append(archive_filename, files_to_append)
     fseek(ofile, 0, 2);
 
     for (; files_to_append && *files_to_append; ++files_to_append) {
-       struct ar_hdr  *hdr = bfd_special_undocumented_glue(*files_to_append);
+       struct ar_hdr  *hdr = bfd_special_undocumented_glue(temp, *files_to_append);
        if (hdr == NULL) {
+           fprintf (stderr, "%s: ", program_name);
            bfd_perror(*files_to_append);
            exit(1);
        }
 
        BFD_SEND(temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
 
-       ifile = fopen(*files_to_append, "r");
+       ifile = fopen(*files_to_append, FOPEN_RB);
        if (ifile == NULL)
+         {
            bfd_perror(program_name);
+         }
 
        if (stat(*files_to_append, &sbuf) != 0)
+         {
+           fprintf (stderr, "%s: ", program_name);
            bfd_perror(*files_to_append);
+         }
 
        tocopy = sbuf.st_size;
 
@@ -585,34 +735,37 @@ void
 write_archive()
 {
     bfd            *obfd;
-    char           *xmalloc();
     int             namelen = strlen(inarch->filename);
     char           *new_name = xmalloc(namelen + 6);
     bfd            *contents_head = inarch->next;
-    if (inarch == &bogus_archive) {
-       /* How can this be ? */
-       return;
-    }
-    else {
 
        strcpy(new_name, inarch->filename);
-       strcpy(new_name + namelen, ".art");
-       obfd = bfd_openw(new_name, bfd_get_target(inarch));
+       strcpy(new_name + namelen, "-art");
+       obfd = bfd_openw(new_name,
+                /* FIXME: violates abstraction; need a better protocol */
+                        (inarch->xvec ? bfd_get_target(inarch) : NULL));
 
        if (obfd == NULL)
            bfd_fatal(inarch->filename);
 
        bfd_set_format(obfd, bfd_archive);
-       obfd->has_armap = write_armap;
+
+       /* Request writing the archive symbol table unless we've
+          been explicitly requested not to. */
+       obfd->has_armap = write_armap >= 0;
 
        if (bfd_set_archive_head(obfd, contents_head) != true)
            bfd_fatal(inarch->filename);
 
        if (!bfd_close(obfd))
            bfd_fatal(inarch->filename);
+
+       /* We don't care if this fails, we might be creating the
+          archive */
+       (void) unlink(inarch->filename);
+
        if (rename(new_name, inarch->filename) != 0)
            bfd_fatal(inarch->filename);
-    }
 }
 
 
@@ -628,36 +781,26 @@ get_pos_bfd(contents, default_pos)
     bfd           **contents;
     enum pos        default_pos;
 {
-    bfd           **after_bfd;
-
+    bfd           **after_bfd = contents;
     enum pos        realpos = (postype == pos_default ? default_pos : postype);
-    switch (realpos) {
 
-    case pos_end:
-       after_bfd = contents;
-       while (*after_bfd) {
+    if (realpos == pos_end) {
+       while (*after_bfd)
            after_bfd = &((*after_bfd)->next);
-       }
-
-       break;
-#if 0
-    case pos_after:
-       for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
-           if (!strcpy(after_bfd->filename, posname))
-               break;
-       break;
-    case pos_before:
-       for (after_bfd = contents; after_bfd; after_bfd = after_bfd->next)
-           if (after_bfd->next && (!strcpy(after_bfd->next->filename, posname)))
+    }
+    else {
+       for ( ; *after_bfd; after_bfd = &(*after_bfd)->next)
+           if (!strcmp((*after_bfd)->filename, posname)) {
+               if (realpos == pos_after)
+                   after_bfd = &(*after_bfd)->next;
                break;
-#endif
+       }
     }
-
     return after_bfd;
 }
 
 
-void
+static void
 delete_members(files_to_delete)
     char          **files_to_delete;
 {
@@ -668,12 +811,13 @@ delete_members(files_to_delete)
        /*
           In a.out systems, the armap is optional.  It's also called
           __.SYMDEF.  So if the user asked to delete it, we should remember
-          that fact. The name is NULL in COFF archives, so using this as a
-          key is as good as anything I suppose
-       */
+          that fact. This isn't quite right for COFF systems (where
+          __.SYMDEF might be regular member), but it's very unlikely
+          to be a problem.  FIXME */
+
        if (!strcmp(*files_to_delete, "__.SYMDEF")) {
            inarch->has_armap = false;
-           write_armap = false;
+           write_armap = -1;
            continue;
        }
 
@@ -710,7 +854,7 @@ next_file:;
 
 /* Reposition existing members within an archive */
 
-void
+static void
 move_members(files_to_move)
     char          **files_to_move;
 {
@@ -755,7 +899,7 @@ next_file:;
 
 /* Ought to default to replacing in place, but this is existing practice! */
 
-void
+static void
 replace_members(files_to_move)
     char          **files_to_move;
 {
@@ -763,15 +907,6 @@ replace_members(files_to_move)
     bfd            *current;
     bfd           **current_ptr;
     bfd            *temp;
-    /*
-       If the first item in the archive is an __.SYMDEF then remove it
-    */
-    if (inarch->next &&
-       strcmp(inarch->next->filename, "__.SYMDEF") == 0) {
-       inarch->next = inarch->next->next;
-    }
-
-
 
     while (files_to_move && *files_to_move) {
        current_ptr = &inarch->next;
@@ -779,11 +914,17 @@ replace_members(files_to_move)
            current = *current_ptr;
            
            if (!strcmp(normalize(*files_to_move), current->filename)) {
-               /* snip out this entry from the chain */
-               *current_ptr = current->next;
                if (newer_only) {
                    struct stat     fsbuf,
                                    asbuf;
+
+                   if (current->arelt_data == NULL) {
+                     /* This can only happen if you specify a file on the
+                        command line more than once. */
+                     fprintf (stderr, "Duplicate file specified: %s -- skipping.\n", *files_to_move);
+                     goto next_file;
+                   }
+
                    if (stat(*files_to_move, &fsbuf) != 0) {
                        if (errno != ENOENT)
                            bfd_fatal(*files_to_move);
@@ -796,6 +937,8 @@ replace_members(files_to_move)
                        goto next_file;
                }
 
+               /* snip out this entry from the chain */
+               *current_ptr = current->next;
 
                after_bfd = get_pos_bfd(&inarch->next, pos_end);
                temp = *after_bfd;
@@ -804,6 +947,9 @@ replace_members(files_to_move)
                    fprintf(stderr, "Can't open file %s\n", *files_to_move);
                    exit(1);
                }
+#ifdef GNU960
+               gnu960_verify_target(*after_bfd);       /* Exits on failure */
+#endif
                (*after_bfd)->next = temp;
 
                if (verbose) {
@@ -824,6 +970,9 @@ replace_members(files_to_move)
            fprintf(stderr, "Can't open file %s\n", *files_to_move);
            exit(1);
        }
+#ifdef GNU960
+       gnu960_verify_target(*after_bfd);       /* Exits on failure */
+#endif
        if (verbose) {
            printf("c - %s\n", *files_to_move);
        }
@@ -839,12 +988,23 @@ next_file:;
     write_archive();
 }
 
-void
+static void
 ranlib_only(archname)
     char           *archname;
 {
-    write_armap = true;
+    write_armap = 1;
     open_inarch(archname);
     write_archive();
     exit(0);
 }
+
+
+
+/* Things which are interesting to map over all or some of the files: */
+
+static void
+print_descr(abfd)
+    bfd            *abfd;
+{
+    print_arelt_descr(stdout,abfd, verbose);
+}
This page took 0.052989 seconds and 4 git commands to generate.