Update FSF address
[deliverable/binutils-gdb.git] / binutils / ar.c
index b85d62ecf0d7ba26fd543c04a1be5e5f038230a0..e8b03790522628c51dfadafa2676f168dc5aa5ee 100644 (file)
@@ -1,6 +1,6 @@
 /* ar.c - Archive modify and extract.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003
+   2001, 2002, 2003, 2004, 2005
    Free Software Foundation, Inc.
 
    This file is part of GNU Binutils.
@@ -17,7 +17,7 @@
 
    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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.  */
 \f
 /*
    Bugs: should use getopt the way tar does (complete w/optional -) and
@@ -65,11 +65,6 @@ static void map_over_members (bfd *, void (*)(bfd *), char **, int);
 static void print_contents (bfd * member);
 static void delete_members (bfd *, char **files_to_delete);
 
-#if 0
-static void do_quick_append
-  (const char *archive_filename, char **files_to_append);
-#endif
-
 static void move_members (bfd *, char **files_to_move);
 static void replace_members
   (bfd *, char **files_to_replace, bfd_boolean quick);
@@ -81,7 +76,7 @@ static void usage (int);
 \f
 /** Globals and flags */
 
-int mri_mode;
+static int mri_mode;
 
 /* This flag distinguishes between ar and ranlib:
    1 means this is 'ranlib'; 0 means this is 'ar'.
@@ -328,7 +323,7 @@ remove_output (void)
        bfd_cache_close (output_bfd);
       if (output_file != NULL)
        fclose (output_file);
-      unlink (output_filename);
+      unlink_if_ordinary (output_filename);
     }
 }
 
@@ -353,6 +348,7 @@ main (int argc, char **argv)
   char *inarch_filename;
   int show_version;
   int i;
+  int do_posix = 0;
 
 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
   setlocale (LC_MESSAGES, "");
@@ -459,107 +455,125 @@ main (int argc, char **argv)
   if (argc < 2)
     usage (0);
 
-  arg_ptr = argv[1];
+  arg_index = 1;
+  arg_ptr = argv[arg_index];
 
   if (*arg_ptr == '-')
-    ++arg_ptr;                 /* compatibility */
+    {
+      /* When the first option starts with '-' we support POSIX-compatible
+        option parsing.  */
+      do_posix = 1;
+      ++arg_ptr;                       /* compatibility */
+    }
 
-  while ((c = *arg_ptr++) != '\0')
+  do
     {
-      switch (c)
+      while ((c = *arg_ptr++) != '\0')
        {
-       case 'd':
-       case 'm':
-       case 'p':
-       case 'q':
-       case 'r':
-       case 't':
-       case 'x':
-         if (operation != none)
-           fatal (_("two different operation options 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;
+             if (operation != none)
+               fatal (_("two different operation options 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 '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;
+           case 'N':
+             counted_name_mode = TRUE;
+             break;
+           case 'f':
+             ar_truncate = TRUE;
+             break;
+           case 'P':
+             full_pathname = TRUE;
+             break;
+           default:
+             /* xgettext:c-format */
+             non_fatal (_("illegal option -- %c"), c);
+             usage (0);
            }
-       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 '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;
-       case 'N':
-         counted_name_mode = TRUE;
-         break;
-       case 'f':
-         ar_truncate = TRUE;
-         break;
-       case 'P':
-         full_pathname = TRUE;
-         break;
-       default:
-         /* xgettext:c-format */
-         non_fatal (_("illegal option -- %c"), c);
-         usage (0);
        }
+
+      /* With POSIX-compatible option parsing continue with the next
+        argument if it starts with '-'.  */
+      if (do_posix && arg_index + 1 < argc && argv[arg_index + 1][0] == '-')
+       arg_ptr = argv[++arg_index] + 1;
+      else
+       do_posix = 0;
     }
+  while (do_posix);
 
   if (show_version)
     print_version ("ar");
 
-  if (argc < 3)
+  ++arg_index;
+  if (arg_index >= argc)
     usage (0);
 
   if (mri_mode)
@@ -570,6 +584,10 @@ main (int argc, char **argv)
     {
       bfd *arch;
 
+      /* We don't use do_quick_append any more.  Too many systems
+        expect ar to always rebuild the symbol table even when q is
+        used.  */
+
       /* We can't write an armap when using ar q, so just do ar r
          instead.  */
       if (operation == quick_append && write_armap)
@@ -578,7 +596,7 @@ main (int argc, char **argv)
       if ((operation == none || operation == print_table)
          && write_armap == 1)
        {
-         ranlib_only (argv[2]);
+         ranlib_only (argv[arg_index]);
          xexit (0);
        }
 
@@ -588,8 +606,6 @@ main (int argc, char **argv)
       if (newer_only && operation != replace)
        fatal (_("`u' is only meaningful with the `r' option."));
 
-      arg_index = 2;
-
       if (postype != pos_default)
        posname = argv[arg_index++];
 
@@ -607,39 +623,6 @@ main (int argc, char **argv)
       files = arg_index < argc ? argv + arg_index : NULL;
       file_count = argc - arg_index;
 
-#if 0
-      /* We don't use do_quick_append any more.  Too many systems
-         expect ar to always rebuild the symbol table even when q is
-         used.  */
-
-      /* 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);
-         xexit (0);
-       }
-#endif
-
       arch = open_inarch (inarch_filename,
                          files == NULL ? (char *) NULL : files[0]);
 
@@ -918,130 +901,16 @@ extract_file (bfd *abfd)
   chmod (bfd_get_filename (abfd), buf.st_mode);
 
   if (preserve_dates)
-    set_times (bfd_get_filename (abfd), &buf);
-
-  free (cbuf);
-}
-
-#if 0
-
-/* We don't use this anymore.  Too many systems expect ar to rebuild
-   the symbol table even when q is used.  */
-
-/* Just do it quickly; don't worry about dups, armap, or anything like that */
-
-static void
-do_quick_append (const char *archive_filename, char **files_to_append)
-{
-  FILE *ofile, *ifile;
-  char *buf = xmalloc (BUFSIZE);
-  long tocopy, thistime;
-  bfd *temp;
-  struct stat sbuf;
-  bfd_boolean newfile = FALSE;
-  bfd_set_error (bfd_error_no_error);
-
-  if (stat (archive_filename, &sbuf) != 0)
-    {
-
-#if !defined(__GO32__) || defined(__DJGPP__)
-
-      /* FIXME: I don't understand why this fragment was ifndef'ed
-        away for __GO32__; perhaps it was in the days of DJGPP v1.x.
-        stat() works just fine in v2.x, so I think this should be
-        removed.  For now, I enable it for DJGPP v2.
-
-        (And yes, I know this is all unused, but somebody, someday,
-        might wish to resurrect this again... -- EZ.  */
-
-/* KLUDGE ALERT! Temporary fix until I figger why
-   stat() is wrong ... think it's buried in GO32's IDT - Jax  */
-
-      if (errno != ENOENT)
-       bfd_fatal (archive_filename);
-#endif
-
-      newfile = TRUE;
-    }
-
-  ofile = fopen (archive_filename, FOPEN_AUB);
-  if (ofile == NULL)
     {
-      perror (program_name);
-      xexit (1);
-    }
-
-  temp = bfd_openr (archive_filename, NULL);
-  if (temp == NULL)
-    {
-      bfd_fatal (archive_filename);
+      /* Set access time to modification time.  Only st_mtime is
+        initialized by bfd_stat_arch_elt.  */
+      buf.st_atime = buf.st_mtime;
+      set_times (bfd_get_filename (abfd), &buf);
     }
-  if (!newfile)
-    {
-      if (!bfd_check_format (temp, bfd_archive))
-       /* xgettext:c-format */
-       fatal (_("%s is not an archive"), archive_filename);
-    }
-  else
-    {
-      fwrite (ARMAG, 1, SARMAG, ofile);
-      if (!silent_create)
-       /* xgettext:c-format */
-       non_fatal (_("creating %s"), archive_filename);
-    }
-
-  if (ar_truncate)
-    temp->flags |= BFD_TRADITIONAL_FORMAT;
-
-  /* assume it's an archive, go straight to the end, sans $200 */
-  fseek (ofile, 0, 2);
-
-  for (; files_to_append && *files_to_append; ++files_to_append)
-    {
-      struct ar_hdr *hdr = bfd_special_undocumented_glue (temp, *files_to_append);
-      if (hdr == NULL)
-       {
-         bfd_fatal (*files_to_append);
-       }
-
-      BFD_SEND (temp, _bfd_truncate_arname, (temp, *files_to_append, (char *) hdr));
-
-      ifile = fopen (*files_to_append, FOPEN_RB);
-      if (ifile == NULL)
-       {
-         bfd_nonfatal (*files_to_append);
-       }
-
-      if (stat (*files_to_append, &sbuf) != 0)
-       {
-         bfd_nonfatal (*files_to_append);
-       }
 
-      tocopy = sbuf.st_size;
-
-      /* XXX should do error-checking! */
-      fwrite (hdr, 1, sizeof (struct ar_hdr), ofile);
-
-      while (tocopy > 0)
-       {
-         thistime = tocopy;
-         if (thistime > BUFSIZE)
-           thistime = BUFSIZE;
-         fread (buf, 1, thistime, ifile);
-         fwrite (buf, 1, thistime, ofile);
-         tocopy -= thistime;
-       }
-      fclose (ifile);
-      if ((sbuf.st_size % 2) == 1)
-       putc ('\012', ofile);
-    }
-  fclose (ofile);
-  bfd_close (temp);
-  free (buf);
+  free (cbuf);
 }
 
-#endif /* 0 */
-
 static void
 write_archive (bfd *iarch)
 {
@@ -1251,7 +1120,7 @@ static void
 replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
 {
   bfd_boolean changed = FALSE;
-  bfd **after_bfd;             /* New entries go after this one */
+  bfd **after_bfd;             /* New entries go after this one */
   bfd *current;
   bfd **current_ptr;
 
@@ -1308,8 +1177,7 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
       /* Add to the end of the archive.  */
       after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
 
-      if (get_file_size (* files_to_move) > 0
-         && ar_emul_append (after_bfd, *files_to_move, verbose))
+      if (ar_emul_append (after_bfd, *files_to_move, verbose))
        changed = TRUE;
 
     next_file:;
This page took 0.029895 seconds and 4 git commands to generate.