[1/3] bfd_fopen: read from stdin if filename == NULL

Message ID 20180213092559.56981-2-ahmad@a3f.at
State Superseded
Headers show
Series
  • binutils: read from stdin if input file is -
Related show

Commit Message

Ahmad Fatoum Feb. 13, 2018, 9:25 a.m.
This is done by slurping stdin into a temporary file.
---
 bfd/bfd-in2.h |  3 +++
 bfd/bfd.c     |  3 +++
 bfd/opncls.c  | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++-------
 3 files changed, 65 insertions(+), 7 deletions(-)

-- 
2.16.1

Patch

diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h
index 42991e7848..597c2226bc 100644
--- a/bfd/bfd-in2.h
+++ b/bfd/bfd-in2.h
@@ -6769,6 +6769,9 @@  struct bfd
   /* The filename the application opened the BFD with.  */
   const char *filename;
 
+  /* If non-NULL, name of a temporary file that can be removed on destruction.  */
+  const char *temp_filename;
+
   /* A pointer to the target jump table.  */
   const struct bfd_target *xvec;
 
diff --git a/bfd/bfd.c b/bfd/bfd.c
index 985c825c69..8fe07468e5 100644
--- a/bfd/bfd.c
+++ b/bfd/bfd.c
@@ -62,6 +62,9 @@  CODE_FRAGMENT
 .  {* The filename the application opened the BFD with.  *}
 .  const char *filename;
 .
+.  {* If non-NULL, name of a temporary file that can be removed on destruction.  *}
+.  const char *temp_filename;
+.
 .  {* A pointer to the target jump table.  *}
 .  const struct bfd_target *xvec;
 .
diff --git a/bfd/opncls.c b/bfd/opncls.c
index 16b568c8ab..5861cc2bd8 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -63,6 +63,8 @@  _bfd_new_bfd (void)
   if (nbfd == NULL)
     return NULL;
 
+  nbfd->temp_filename = NULL;
+
   if (bfd_use_reserved_id)
     {
       nbfd->id = --bfd_reserved_id_counter;
@@ -128,6 +130,11 @@  _bfd_delete_bfd (bfd *abfd)
 
   if (abfd->filename)
     free ((char *) abfd->filename);
+  if (abfd->temp_filename)
+    {
+      remove (abfd->temp_filename);
+      XDELETEVEC ((char *) abfd->temp_filename);
+    }
   free (abfd->arelt_data);
   free (abfd);
 }
@@ -173,8 +180,9 @@  DESCRIPTION
 	Open the file @var{filename} with the target @var{target}.
 	Return a pointer to the created BFD.  If @var{fd} is not -1,
 	then <<fdopen>> is used to open the file; otherwise, <<fopen>>
-	is used.  @var{mode} is passed directly to <<fopen>> or
-	<<fdopen>>.
+	is used. If @var{filename} is <<NULL>>, standard input is read
+	into a temporary file which is then opened.
+	@var{mode} is passed directly to <<fopen>> or <<fdopen>>.
 
 	Calls <<bfd_find_target>>, so @var{target} is interpreted as by
 	that function.
@@ -216,12 +224,53 @@  bfd_fopen (const char *filename, const char *target, const char *mode, int fd)
 
 #ifdef HAVE_FDOPEN
   if (fd != -1)
-    nbfd->iostream = fdopen (fd, mode);
+    {
+      nbfd->iostream = fdopen (fd, mode);
+    }
   else
 #endif
-    nbfd->iostream = _bfd_real_fopen (filename, mode);
+    {
+      if (filename)
+        {
+          nbfd->iostream = _bfd_real_fopen (filename, mode);
+        }
+      else /* slurp in stdin */
+        {
+          FILE *fp;
+          size_t nbytes;
+          char buffer[256];
+          nbfd->temp_filename = make_temp_file (NULL);
+          fp = _bfd_real_fopen (nbfd->temp_filename, "w");
+          if (!fp)
+            goto fopen_fail;
+
+          while ((nbytes = fread (buffer, 1, sizeof (buffer), stdin)) > 0)
+            {
+              if (fwrite (buffer, 1, nbytes, fp) != nbytes)
+                break;
+            }
+
+          if (ferror (fp) || ferror (stdin))
+            {
+              bfd_set_input_error (nbfd, bfd_error_on_input);
+              fclose (fp);
+              _bfd_delete_bfd (nbfd);
+              return NULL;
+            }
+
+          filename = "<stdin>";
+          nbfd->iostream = _bfd_real_fopen (nbfd->temp_filename, mode);
+          fclose (fp);
+          if (remove (nbfd->temp_filename) == 0)
+            {
+              XDELETEVEC ((char *) nbfd->temp_filename);
+              nbfd->temp_filename = NULL;
+            }
+        }
+    }
   if (nbfd->iostream == NULL)
     {
+     fopen_fail:
       bfd_set_error (bfd_error_system_call);
       _bfd_delete_bfd (nbfd);
       return NULL;
@@ -269,7 +318,9 @@  SYNOPSIS
 
 DESCRIPTION
 	Open the file @var{filename} (using <<fopen>>) with the target
-	@var{target}.  Return a pointer to the created BFD.
+	@var{target}. If @var{filename} is <<NULL>>, standard input is
+	read into a temporary file which is then openend.
+	Return a pointer to the created BFD.
 
 	Calls <<bfd_find_target>>, so @var{target} is interpreted as by
 	that function.
@@ -304,8 +355,9 @@  SYNOPSIS
 
 DESCRIPTION
 	<<bfd_fdopenr>> is to <<bfd_fopenr>> much like <<fdopen>> is to
-	<<fopen>>.  It opens a BFD on a file already described by the
-	@var{fd} supplied.
+	<<fopen>>.  If @var{filename} is <<NULL>>, standard input is
+	read into a temporary file which is then openend.
+	It opens a BFD on a file already described by the @var{fd} supplied.
 
 	When the file is later <<bfd_close>>d, the file descriptor will
 	be closed.  If the caller desires that this file descriptor be