This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ar --output support


https://sourceware.org/ml/binutils/2019-10/msg00186.html

> > There is a proposal https://reviews.llvm.org/D69418 that adds --output
> > to llvm-ar. --output specifies the output directory for the x (extract)
> > operation. Does GNU ar want to do the same?
>
> Yes.  It would be very helpful for users if both versions of the tool
> behaved in the same way and supported the same options.
>
> Are you volunteering to submit a patch to add this behaviour ?
>
> (I ask because I am lazy/busy and if you are willing to do the work
> then that would be grand.  But if not, then I will take on the task
> myself).
From 3ac9fced9ef5a4bca2cb8e2a0888240e9a93919e Mon Sep 17 00:00:00 2001
From: Fangrui Song <maskray@google.com>
Date: Fri, 25 Oct 2019 10:49:40 -0700
Subject: [PATCH] ar --output support

--output specifies the directory that files are extracted to.
---
 binutils/ChangeLog         |  8 ++++++
 binutils/ar.c              | 50 +++++++++++++++++++++++++++-----------
 binutils/doc/binutils.texi |  7 +++++-
 3 files changed, 50 insertions(+), 15 deletions(-)

diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 224ebeb04e..bff3c9a104 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,11 @@
+2019-10-25  Fangrui Song  <maskray@google.com>
+
+	* ar.c (output_directory): New variable.
+	(decode_options): Handle --output.
+	(extract_file): Handle output_directory.
+	* doc/binutils.texi: Mention --output can extract files to a specified
+	directory.
+
 2019-10-25  Nick Clifton  <nickc@redhat.com>
 
 	* objcopy.c (struct merged_note_section): New structure.  Used to
diff --git a/binutils/ar.c b/binutils/ar.c
index 38c54c9fa8..43c49b7af6 100644
--- a/binutils/ar.c
+++ b/binutils/ar.c
@@ -25,6 +25,7 @@
 
 #include "sysdep.h"
 #include "bfd.h"
+#include "libbfd.h"
 #include "libiberty.h"
 #include "progress.h"
 #include "getopt.h"
@@ -141,6 +142,8 @@ static int show_version = 0;
 
 static int show_help = 0;
 
+static const char *output_directory = NULL;
+
 #if BFD_SUPPORTS_PLUGINS
 static const char *plugin_target = "plugin";
 #else
@@ -149,12 +152,14 @@ static const char *plugin_target = NULL;
 
 static const char *target = NULL;
 
+#define OPTION_OUTPUT 200
 #define OPTION_PLUGIN 201
 #define OPTION_TARGET 202
 
 static struct option long_options[] =
 {
   {"help", no_argument, &show_help, 1},
+  {"output", required_argument, NULL, OPTION_OUTPUT},
   {"plugin", required_argument, NULL, OPTION_PLUGIN},
   {"target", required_argument, NULL, OPTION_TARGET},
   {"version", no_argument, &show_version, 1},
@@ -581,6 +586,9 @@ decode_options (int argc, char **argv)
         case 'U':
           deterministic = FALSE;
           break;
+        case OPTION_OUTPUT:
+          output_directory = optarg;
+          break;
 	case OPTION_PLUGIN:
 #if BFD_SUPPORTS_PLUGINS
 	  bfd_plugin_set_plugin (optarg);
@@ -1050,6 +1058,19 @@ print_contents (bfd *abfd)
   free (cbuf);
 }
 
+static char *
+make_extracted_filename (bfd *abfd)
+{
+  const char *filename = bfd_get_filename (abfd);
+  if (!output_directory)
+    return strdup (filename);
+  char *pathbuf
+      = (char *)bfd_malloc (strlen (output_directory) + strlen (filename) + 2);
+  if (pathbuf)
+    sprintf (pathbuf, "%s/%s", output_directory, filename);
+  return pathbuf;
+}
+
 /* Extract a member of the archive into its own file.
 
    We defer opening the new file until after we have read a BUFSIZ chunk of the
@@ -1094,14 +1115,14 @@ extract_file (bfd *abfd)
   if (size == 0)
     {
       /* Seems like an abstraction violation, eh?  Well it's OK! */
-      output_filename = bfd_get_filename (abfd);
+      output_filename = make_extracted_filename (abfd);
 
-      ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
-      if (ostream == NULL)
-	{
-	  perror (bfd_get_filename (abfd));
+      if (output_filename == NULL
+          || (ostream = fopen (output_filename, FOPEN_WB)) == NULL)
+        {
+          perror (bfd_get_filename (abfd));
 	  xexit (1);
-	}
+        }
 
       output_file = ostream;
     }
@@ -1122,16 +1143,16 @@ extract_file (bfd *abfd)
 	if (ostream == NULL)
 	  {
 	    /* Seems like an abstraction violation, eh?  Well it's OK! */
-	    output_filename = bfd_get_filename (abfd);
+            output_filename = make_extracted_filename (abfd);
 
-	    ostream = fopen (bfd_get_filename (abfd), FOPEN_WB);
-	    if (ostream == NULL)
-	      {
-		perror (bfd_get_filename (abfd));
-		xexit (1);
-	      }
+            if (output_filename == NULL
+                || (ostream = fopen (output_filename, FOPEN_WB)) == NULL)
+              {
+                perror (bfd_get_filename (abfd));
+                xexit (1);
+              }
 
-	    output_file = ostream;
+            output_file = ostream;
 	  }
 
 	/* fwrite in mingw32 may return int instead of bfd_size_type. Cast
@@ -1146,6 +1167,7 @@ extract_file (bfd *abfd)
     fclose (ostream);
 
   output_file = NULL;
+  free ((char *)output_filename);
   output_filename = NULL;
 
   chmod (bfd_get_filename (abfd), buf.st_mode);
diff --git a/binutils/doc/binutils.texi b/binutils/doc/binutils.texi
index 2edd7e1aa1..c27405585d 100644
--- a/binutils/doc/binutils.texi
+++ b/binutils/doc/binutils.texi
@@ -169,7 +169,7 @@ in the section entitled ``GNU Free Documentation License''.
 @c man title ar create, modify, and extract from archives
 
 @smallexample
-ar [-]@var{p}[@var{mod}] [@option{--plugin} @var{name}] [@option{--target} @var{bfdname}] [@var{relpos}] [@var{count}] @var{archive} [@var{member}@dots{}]
+ar [-]@var{p}[@var{mod}] [@option{--output} @var{directory}] [@option{--plugin} @var{name}] [@option{--target} @var{bfdname}] [@var{relpos}] [@var{count}] @var{archive} [@var{member}@dots{}]
 ar -M [ <mri-script ]
 @end smallexample
 
@@ -550,6 +550,11 @@ default for @sc{gnu} @command{ar}.  @command{ar} does not support any
 of the other @samp{-X} options; in particular, it does not support
 @option{-X32} which is the default for AIX @command{ar}.
 
+@item --output @var{directory}
+@cindex output directory
+The optional command-line switch @option{--output @var{name}} causes
+@command{ar} to extract files to @var{directory}.
+
 @item --plugin @var{name}
 @cindex plugins
 The optional command-line switch @option{--plugin @var{name}} causes
-- 
2.20.0


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]