gdb/
[deliverable/binutils-gdb.git] / binutils / ar.c
index 8313df5bf39ad269d3e4b688a94e2470729e345a..73ab1d46f023f2464b92f250d6646ff03bb0053a 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
    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 <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 */
+/* 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 +68,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 +99,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 +133,9 @@ 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;
+
 int interactive = 0;
 
 static void
@@ -175,16 +178,25 @@ map_over_members (bfd *arch, void (*function)(bfd *), char **files, int count)
       match_count = 0;
       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 +211,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);
@@ -232,6 +245,7 @@ usage (int help)
       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 +255,11 @@ 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"));
+
       ar_emul_usage (s);
     }
   else
@@ -254,8 +269,9 @@ usage (int help)
       fprintf (s, _(" Generate an index to speed access to archives\n"));
       fprintf (s, _(" The options are:\n\
   @<file>                      Read options from <file>\n\
+  -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);
@@ -282,6 +298,7 @@ normalize (const char *file, bfd *abfd)
   {
     /* 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] == ':')
@@ -300,7 +317,7 @@ normalize (const char *file, bfd *abfd)
       char *s;
 
       /* Space leak.  */
-      s = (char *) xmalloc (abfd->xvec->ar_max_namelen + 1);
+      s = xmalloc (abfd->xvec->ar_max_namelen + 1);
       memcpy (s, filename, abfd->xvec->ar_max_namelen);
       s[abfd->xvec->ar_max_namelen] = '\0';
       filename = s;
@@ -374,6 +391,7 @@ main (int argc, char **argv)
       {
        /* 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] == ':')
@@ -557,6 +575,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,6 +631,9 @@ 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++];
 
@@ -627,6 +654,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:
@@ -931,7 +961,7 @@ write_archive (bfd *iarch)
 
   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 +984,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);
 
@@ -1187,7 +1223,8 @@ replace_members (bfd *arch, char **files_to_move, bfd_boolean quick)
       /* Add to the end of the archive.  */
       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, verbose,
+                          make_thin_archive))
        changed = TRUE;
 
     next_file:;
This page took 0.025592 seconds and 4 git commands to generate.