* ar.c (print_contents): Don't internationalize strings without words.
[deliverable/binutils-gdb.git] / binutils / ar.c
index 720ced73e9828c269f5302a8e777150bc2c6545e..a08a991290a5426ff69b08aded871525347e4d85 100644 (file)
@@ -1,13 +1,13 @@
 /* ar.c - Archive modify and extract.
    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    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
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
@@ -17,7 +17,8 @@
 
    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., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, 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
 #include "arsup.h"
 #include "filenames.h"
 #include "binemul.h"
+#include "plugin.h"
 #include <sys/stat.h>
 
 #ifdef __GO32___
-#define EXT_NAME_LEN 3         /* bufflen of addition to name if it's MS-DOS */
+#define EXT_NAME_LEN 3         /* Bufflen of addition to name if it's MS-DOS.  */
 #else
-#define EXT_NAME_LEN 6         /* ditto for *NIX */
+#define EXT_NAME_LEN 6         /* Ditto for *NIX.  */
 #endif
 
-/* We need to open files in binary modes on system where that makes a
-   difference.  */
-#ifndef O_BINARY
-#define O_BINARY 0
-#endif
-
-/* Kludge declaration from BFD!  This is ugly!  FIXME!  XXX */
-
-struct ar_hdr *
-  bfd_special_undocumented_glue (bfd * abfd, const char *filename);
-
-/* Static declarations */
+/* Static declarations.  */
 
 static void mri_emul (void);
 static const char *normalize (const char *, bfd *);
@@ -73,7 +64,7 @@ static int  ranlib_only (const char *archname);
 static int  ranlib_touch (const char *archname);
 static void usage (int);
 \f
-/** Globals and flags */
+/** Globals and flags */
 
 static int mri_mode;
 
@@ -104,6 +95,11 @@ int newer_only = 0;
    if any of the members are object files.  */
 int write_armap = 0;
 
+/* Operate in deterministic mode: write zero for timestamps, uids,
+   and gids for archive members and the archive symbol table, and write
+   consistent file modes.  */
+int deterministic = 0;
+
 /* Nonzero means it's the name of an existing member; position new or moved
    files with respect to this one.  */
 char *posname = NULL;
@@ -133,6 +129,11 @@ static bfd_boolean ar_truncate = FALSE;
    program.  */
 static bfd_boolean full_pathname = FALSE;
 
+/* Whether to create a "thin" archive (symbol index only -- no files).  */
+static bfd_boolean make_thin_archive = FALSE;
+
+static const char *plugin_target = NULL;
+
 int interactive = 0;
 
 static void
@@ -154,7 +155,7 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
 
   if (count == 0)
     {
-      for (head = arch->next; head; head = head->next)
+      for (head = arch->archive_next; head; head = head->archive_next)
        {
          PROGRESS (1);
          function (head);
@@ -173,18 +174,27 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
       bfd_boolean found = FALSE;
 
       match_count = 0;
-      for (head = arch->next; head; head = head->next)
+      for (head = arch->archive_next; head; head = head->archive_next)
        {
+         const char * filename;
+
          PROGRESS (1);
-         if (head->filename == NULL)
+         filename = head->filename;
+         if (filename == NULL)
            {
              /* Some archive formats don't get the filenames filled in
                 until the elements are opened.  */
              struct stat buf;
              bfd_stat_arch_elt (head, &buf);
            }
-         if ((head->filename != NULL) &&
-             (!FILENAME_CMP (normalize (*files, arch), head->filename)))
+         else if (bfd_is_thin_archive (arch))
+           {
+             /* Thin archives store full pathnames.  Need to normalize.  */
+             filename = normalize (filename, arch);
+           }
+
+         if ((filename != NULL) &&
+             (!FILENAME_CMP (normalize (*files, arch), filename)))
            {
              ++match_count;
              if (counted_name_mode
@@ -199,6 +209,7 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
              function (head);
            }
        }
+
       if (!found)
        /* xgettext:c-format */
        fprintf (stderr, _("no entry %s in archive\n"), *files);
@@ -217,8 +228,14 @@ usage (int help)
   if (! is_ranlib)
     {
       /* xgettext:c-format */
-      fprintf (s, _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n"),
-              program_name);
+      const char * command_line =
+#if BFD_SUPPORTS_PLUGINS
+       _("Usage: %s [emulation options] [--plugin <name>] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n");
+#else
+       _("Usage: %s [emulation options] [-]{dmpqrstx}[abcfilNoPsSuvV] [member-name] [count] archive-file file...\n");
+#endif
+      fprintf (s, command_line, program_name);
+
       /* xgettext:c-format */
       fprintf (s, _("       %s -M [<mri-script]\n"), program_name);
       fprintf (s, _(" commands:\n"));
@@ -227,11 +244,13 @@ usage (int help)
       fprintf (s, _("  p            - print file(s) found in the archive\n"));
       fprintf (s, _("  q[f]         - quick append file(s) to the archive\n"));
       fprintf (s, _("  r[ab][f][u]  - replace existing or insert new file(s) into the archive\n"));
+      fprintf (s, _("  s            - act as ranlib\n"));
       fprintf (s, _("  t            - display contents of archive\n"));
       fprintf (s, _("  x[o]         - extract file(s) from the archive\n"));
       fprintf (s, _(" command specific modifiers:\n"));
       fprintf (s, _("  [a]          - put file(s) after [member-name]\n"));
       fprintf (s, _("  [b]          - put file(s) before [member-name] (same as [i])\n"));
+      fprintf (s, _("  [D]          - use zero for timestamps and uids/gids\n"));
       fprintf (s, _("  [N]          - use instance [count] of name\n"));
       fprintf (s, _("  [f]          - truncate inserted file names\n"));
       fprintf (s, _("  [P]          - use full path names when matching\n"));
@@ -241,10 +260,14 @@ usage (int help)
       fprintf (s, _("  [c]          - do not warn if the library had to be created\n"));
       fprintf (s, _("  [s]          - create an archive index (cf. ranlib)\n"));
       fprintf (s, _("  [S]          - do not build a symbol table\n"));
+      fprintf (s, _("  [T]          - make a thin archive\n"));
       fprintf (s, _("  [v]          - be verbose\n"));
       fprintf (s, _("  [V]          - display the version number\n"));
       fprintf (s, _("  @<file>      - read options from <file>\n"));
+#if BFD_SUPPORTS_PLUGINS
+      fprintf (s, _(" optional:\n"));
+      fprintf (s, _("  --plugin <p> - load the specified plugin\n"));
+#endif
       ar_emul_usage (s);
     }
   else
@@ -253,9 +276,15 @@ usage (int help)
       fprintf (s, _("Usage: %s [options] archive\n"), program_name);
       fprintf (s, _(" Generate an index to speed access to archives\n"));
       fprintf (s, _(" The options are:\n\
-  @<file>                      Read options from <file>\n\
+  @<file>                      Read options from <file>\n"));
+#if BFD_SUPPORTS_PLUGINS
+      fprintf (s, _("\
+  --plugin <name>              Load the specified plugin\n"));
+#endif
+      fprintf (s, _("\
+  -t                           Update the archive's symbol map timestamp\n\
   -h --help                    Print this help message\n\
-  -V --version                 Print version information\n"));
+  -v --version                 Print version information\n"));
     }
 
   list_supported_targets (program_name, s);
@@ -277,21 +306,7 @@ normalize (const char *file, bfd *abfd)
   if (full_pathname)
     return file;
 
-  filename = strrchr (file, '/');
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-  {
-    /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
-    char *bslash = strrchr (file, '\\');
-    if (filename == NULL || (bslash != NULL && bslash > filename))
-      filename = bslash;
-    if (filename == NULL && file[0] != '\0' && file[1] == ':')
-      filename = file + 1;
-  }
-#endif
-  if (filename != (char *) NULL)
-    filename++;
-  else
-    filename = file;
+  filename = lbasename (file);
 
   if (ar_truncate
       && abfd != NULL
@@ -340,7 +355,7 @@ main (int argc, char **argv)
   char c;
   enum
     {
-      none = 0, delete, replace, print_table,
+      none = 0, del, replace, print_table,
       print_files, extract, move, quick_append
     } operation = none;
   int arg_index;
@@ -362,28 +377,16 @@ main (int argc, char **argv)
 
   program_name = argv[0];
   xmalloc_set_program_name (program_name);
+#if BFD_SUPPORTS_PLUGINS
+  bfd_plugin_set_program_name (program_name);
+#endif
 
   expandargv (&argc, &argv);
 
   if (is_ranlib < 0)
     {
-      char *temp;
+      const char *temp = lbasename (program_name);
 
-      temp = strrchr (program_name, '/');
-#ifdef HAVE_DOS_BASED_FILE_SYSTEM
-      {
-       /* We could have foo/bar\\baz, or foo\\bar, or d:bar.  */
-       char *bslash = strrchr (program_name, '\\');
-       if (temp == NULL || (bslash != NULL && bslash > temp))
-         temp = bslash;
-       if (temp == NULL && program_name[0] != '\0' && program_name[1] == ':')
-         temp = program_name + 1;
-      }
-#endif
-      if (temp == NULL)
-       temp = program_name;
-      else
-       ++temp;
       if (strlen (temp) >= 6
          && FILENAME_CMP (temp + strlen (temp) - 6, "ranlib") == 0)
        is_ranlib = 1;
@@ -462,6 +465,24 @@ main (int argc, char **argv)
   arg_index = 1;
   arg_ptr = argv[arg_index];
 
+  if (strcmp (arg_ptr, "--plugin") == 0)
+    {
+#if BFD_SUPPORTS_PLUGINS
+      if (argc < 4)
+       usage (1);
+
+      bfd_plugin_set_plugin (argv[2]);
+
+      arg_index += 2;
+      arg_ptr = argv[arg_index];
+
+      plugin_target = "plugin";
+#else
+      fprintf (stderr, _("sorry - this program has been built without plugin support\n"));
+      xexit (1);
+#endif
+    }
+
   if (*arg_ptr == '-')
     {
       /* When the first option starts with '-' we support POSIX-compatible
@@ -488,7 +509,7 @@ main (int argc, char **argv)
              switch (c)
                {
                case 'd':
-                 operation = delete;
+                 operation = del;
                  operation_alters_arch = TRUE;
                  break;
                case 'm':
@@ -557,6 +578,12 @@ main (int argc, char **argv)
            case 'P':
              full_pathname = TRUE;
              break;
+           case 'T':
+             make_thin_archive = TRUE;
+             break;
+           case 'D':
+             deterministic = TRUE;
+             break;
            default:
              /* xgettext:c-format */
              non_fatal (_("illegal option -- %c"), c);
@@ -607,12 +634,15 @@ main (int argc, char **argv)
       if (newer_only && operation != replace)
        fatal (_("`u' is only meaningful with the `r' option."));
 
+      if (newer_only && deterministic)
+       fatal (_("`u' is not meaningful with the `D' option."));
+
       if (postype != pos_default)
        posname = argv[arg_index++];
 
       if (counted_name_mode)
        {
-         if (operation != extract && operation != delete)
+         if (operation != extract && operation != del)
             fatal (_("`N' is only meaningful with the `x' and `d' options."));
          counted_name_counter = atoi (argv[arg_index++]);
          if (counted_name_counter <= 0)
@@ -627,6 +657,9 @@ main (int argc, char **argv)
       arch = open_inarch (inarch_filename,
                          files == NULL ? (char *) NULL : files[0]);
 
+      if (operation == extract && bfd_is_thin_archive (arch))
+       fatal (_("`x' cannot be used on thin archives."));
+
       switch (operation)
        {
        case print_table:
@@ -641,7 +674,7 @@ main (int argc, char **argv)
          map_over_members (arch, extract_file, files, file_count);
          break;
 
-       case delete:
+       case del:
          if (files != NULL)
            delete_members (arch, files);
          else
@@ -688,7 +721,7 @@ open_inarch (const char *archive_filename, const char *file)
 
   bfd_set_error (bfd_error_no_error);
 
-  target = NULL;
+  target = plugin_target;
 
   if (stat (archive_filename, &sbuf) != 0)
     {
@@ -719,7 +752,7 @@ open_inarch (const char *archive_filename, const char *file)
        {
          bfd *obj;
 
-         obj = bfd_openr (file, NULL);
+         obj = bfd_openr (file, target);
          if (obj != NULL)
            {
              if (bfd_check_format (obj, bfd_object))
@@ -759,7 +792,7 @@ open_inarch (const char *archive_filename, const char *file)
       xexit (1);
     }
 
-  last_one = &(arch->next);
+  last_one = &(arch->archive_next);
   /* Read all the contents right away, regardless.  */
   for (next_one = bfd_openr_next_archived_file (arch, NULL);
        next_one;
@@ -767,7 +800,7 @@ open_inarch (const char *archive_filename, const char *file)
     {
       PROGRESS (1);
       *last_one = next_one;
-      last_one = &next_one->next;
+      last_one = &next_one->archive_next;
     }
   *last_one = (bfd *) NULL;
   if (bfd_get_error () != bfd_error_no_more_archived_files)
@@ -779,7 +812,7 @@ static void
 print_contents (bfd *abfd)
 {
   size_t ncopied = 0;
-  char *cbuf = xmalloc (BUFSIZE);
+  char *cbuf = (char *) xmalloc (BUFSIZE);
   struct stat buf;
   size_t size;
   if (bfd_stat_arch_elt (abfd, &buf) != 0)
@@ -787,8 +820,7 @@ print_contents (bfd *abfd)
     fatal (_("internal stat error on %s"), bfd_get_filename (abfd));
 
   if (verbose)
-    /* xgettext:c-format */
-    printf (_("\n<%s>\n\n"), bfd_get_filename (abfd));
+    printf ("\n<%s>\n\n", bfd_get_filename (abfd));
 
   bfd_seek (abfd, (file_ptr) 0, SEEK_SET);
 
@@ -831,7 +863,7 @@ void
 extract_file (bfd *abfd)
 {
   FILE *ostream;
-  char *cbuf = xmalloc (BUFSIZE);
+  char *cbuf = (char *) xmalloc (BUFSIZE);
   size_t nread, tocopy;
   size_t ncopied = 0;
   size_t size;
@@ -923,15 +955,15 @@ write_archive (bfd *iarch)
 {
   bfd *obfd;
   char *old_name, *new_name;
-  bfd *contents_head = iarch->next;
+  bfd *contents_head = iarch->archive_next;
 
-  old_name = xmalloc (strlen (bfd_get_filename (iarch)) + 1);
+  old_name = (char *) xmalloc (strlen (bfd_get_filename (iarch)) + 1);
   strcpy (old_name, bfd_get_filename (iarch));
   new_name = make_tempname (old_name);
 
   if (new_name == NULL)
     bfd_fatal ("could not create temporary file whilst writing archive");
-  
+
   output_filename = new_name;
 
   obfd = bfd_openw (new_name, bfd_get_target (iarch));
@@ -954,6 +986,12 @@ write_archive (bfd *iarch)
       obfd->flags |= BFD_TRADITIONAL_FORMAT;
     }
 
+  if (deterministic)
+    obfd->flags |= BFD_DETERMINISTIC_OUTPUT;
+
+  if (make_thin_archive || bfd_is_thin_archive (iarch))
+    bfd_is_thin_archive (obfd) = 1;
+
   if (!bfd_set_archive_head (obfd, contents_head))
     bfd_fatal (old_name);
 
@@ -995,15 +1033,15 @@ get_pos_bfd (bfd **contents, enum pos default_pos, const char *default_posname)
   if (realpos == pos_end)
     {
       while (*after_bfd)
-       after_bfd = &((*after_bfd)->next);
+       after_bfd = &((*after_bfd)->archive_next);
     }
   else
     {
-      for (; *after_bfd; after_bfd = &(*after_bfd)->next)
+      for (; *after_bfd; after_bfd = &(*after_bfd)->archive_next)
        if (FILENAME_CMP ((*after_bfd)->filename, realposname) == 0)
          {
            if (realpos == pos_after)
-             after_bfd = &(*after_bfd)->next;
+             after_bfd = &(*after_bfd)->archive_next;
            break;
          }
     }
@@ -1035,7 +1073,7 @@ delete_members (bfd *arch, char **files_to_delete)
 
       found = FALSE;
       match_count = 0;
-      current_ptr_ptr = &(arch->next);
+      current_ptr_ptr = &(arch->archive_next);
       while (*current_ptr_ptr)
        {
          if (FILENAME_CMP (normalize (*files_to_delete, arch),
@@ -1055,12 +1093,12 @@ delete_members (bfd *arch, char **files_to_delete)
                  if (verbose)
                    printf ("d - %s\n",
                            *files_to_delete);
-                 *current_ptr_ptr = ((*current_ptr_ptr)->next);
+                 *current_ptr_ptr = ((*current_ptr_ptr)->archive_next);
                  goto next_file;
                }
            }
 
-         current_ptr_ptr = &((*current_ptr_ptr)->next);
+         current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
        }
 
       if (verbose && !found)
@@ -1089,7 +1127,7 @@ move_members (bfd *arch, char **files_to_move)
 
   for (; *files_to_move; ++files_to_move)
     {
-      current_ptr_ptr = &(arch->next);
+      current_ptr_ptr = &(arch->archive_next);
       while (*current_ptr_ptr)
        {
          bfd *current_ptr = *current_ptr_ptr;
@@ -1098,14 +1136,14 @@ move_members (bfd *arch, char **files_to_move)
            {
              /* Move this file to the end of the list - first cut from
                 where it is.  */
-             bfd *link;
-             *current_ptr_ptr = current_ptr->next;
+             bfd *link_bfd;
+             *current_ptr_ptr = current_ptr->archive_next;
 
              /* Now glue to end */
-             after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
-             link = *after_bfd;
+             after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
+             link_bfd = *after_bfd;
              *after_bfd = current_ptr;
-             current_ptr->next = link;
+             current_ptr->archive_next = link_bfd;
 
              if (verbose)
                printf ("m - %s\n", *files_to_move);
@@ -1113,7 +1151,7 @@ move_members (bfd *arch, char **files_to_move)
              goto next_file;
            }
 
-         current_ptr_ptr = &((*current_ptr_ptr)->next);
+         current_ptr_ptr = &((*current_ptr_ptr)->archive_next);
        }
       /* xgettext:c-format */
       fatal (_("no entry %s in archive %s!"), *files_to_move, arch->filename);
@@ -1138,7 +1176,7 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
     {
       if (! quick)
        {
-         current_ptr = &arch->next;
+         current_ptr = &arch->archive_next;
          while (*current_ptr)
            {
              current = *current_ptr;
@@ -1168,26 +1206,27 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
                        goto next_file;
                    }
 
-                 after_bfd = get_pos_bfd (&arch->next, pos_after,
+                 after_bfd = get_pos_bfd (&arch->archive_next, pos_after,
                                           current->filename);
                  if (ar_emul_replace (after_bfd, *files_to_move,
-                                      verbose))
+                                      plugin_target, verbose))
                    {
                      /* Snip out this entry from the chain.  */
-                     *current_ptr = (*current_ptr)->next;
+                     *current_ptr = (*current_ptr)->archive_next;
                      changed = TRUE;
                    }
 
                  goto next_file;
                }
-             current_ptr = &(current->next);
+             current_ptr = &(current->archive_next);
            }
        }
 
       /* Add to the end of the archive.  */
-      after_bfd = get_pos_bfd (&arch->next, pos_end, NULL);
+      after_bfd = get_pos_bfd (&arch->archive_next, pos_end, NULL);
 
-      if (ar_emul_append (after_bfd, *files_to_move, verbose))
+      if (ar_emul_append (after_bfd, *files_to_move, plugin_target,
+                         verbose, make_thin_archive))
        changed = TRUE;
 
     next_file:;
This page took 0.032671 seconds and 4 git commands to generate.