wdiff-bugs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[wdiff-bugs] [PATCH] Non-seekable input [Savannah bug #25883]


From: Martin von Gagern
Subject: [wdiff-bugs] [PATCH] Non-seekable input [Savannah bug #25883]
Date: Thu, 02 Apr 2009 09:42:01 +0200
User-agent: Thunderbird 2.0.0.21 (X11/20090321)

Hi!

This is a copy of https://savannah.gnu.org/bugs/index.php?25883 as it
seems that bugs posted in the savannah tracker are not automatically
sent to this list as well.

I tend to use shell process substitutions a lot with diff. However, when
I try to do the same with wdiff, I loose output without any indication
that anything might have gone wrong. To test this, try the following:
wdiff <(echo here foo there) <(echo here bar there)

The primary cause of this is that this kind of input is not seekable.
wdiff already contains some code to copy input to a temporary file, but
it uses that method only for stdin.

The attached patch checks whether or not a stream is seekable, and
copies it to a temporary buffer if not. With this patch in place, the
above command produces the expected output. As an added benefit, in
cases where stdin is seekable, unnecessary buffering is avoided, though
this case is probably rare.

Greetings,
 Martin von Gagern
Index: src/wdiff.c
===================================================================
--- src/wdiff.c.orig
+++ src/wdiff.c
@@ -606,14 +606,33 @@ split_file_into_words (SIDE *side)
 {
   struct stat stat_buffer;     /* for checking if file is directory */
   int fd;                /* for file descriptors returned by mkstemp */
+  FILE *input;          /* used when copying from non-seekable input */
 
   /* Open files.  */
 
   if (side->filename == NULL)
     {
+      side->file = stdin;
+    }
+  else
+    {
+      /* Check and diagnose if the file name is a directory.  Or else,
+        prepare the file for reading.  */
+
+      if (stat (side->filename, &stat_buffer) != 0)
+       error (EXIT_FAILURE, errno, "%s", side->filename);
+      if ((stat_buffer.st_mode & S_IFMT) == S_IFDIR)
+       error (EXIT_FAILURE, 0, _("Directories not supported"));
+      side->file = fopen (side->filename, "r");
+      if (side->file == NULL)
+       error (EXIT_FAILURE, errno, "%s", side->filename);
+    }
 
-      /* Select a file name, use it for opening a temporary file and
-        unlink it right away.  Then, copy the whole standard input on
+  if (fseek(side->file, 0L, SEEK_CUR) != 0)
+    {
+      /* Non-seekable input, e.g. stdin or shell process substitution.
+        Select a file name, use it for opening a temporary file and
+        unlink it right away.  Then, copy the whole input to
         this temporary local file.  Once done, prepare it for reading.
         We do not need the file name itself anymore.  */
 
@@ -622,28 +641,16 @@ split_file_into_words (SIDE *side)
       if ((fd = mkstemp (side->temp_name)) == -1)
         error (EXIT_FAILURE, errno, "%s", side->temp_name);
 
+      input = side->file;
       side->file = fdopen (fd, "w+");
       if (side->file == NULL)
        error (EXIT_FAILURE, errno, "%s", side->temp_name);
       if (unlink (side->temp_name) != 0)
        error (EXIT_FAILURE, errno, "%s", side->temp_name);
-      while (side->character = getchar (), side->character != EOF)
+      while (side->character = getc (input), side->character != EOF)
        putc (side->character, side->file);
       rewind (side->file);
-    }
-  else
-    {
-
-      /* Check and diagnose if the file name is a directory.  Or else,
-        prepare the file for reading.  */
 
-      if (stat (side->filename, &stat_buffer) != 0)
-       error (EXIT_FAILURE, errno, "%s", side->filename);
-      if ((stat_buffer.st_mode & S_IFMT) == S_IFDIR)
-       error (EXIT_FAILURE, 0, _("Directories not supported"));
-      side->file = fopen (side->filename, "r");
-      if (side->file == NULL)
-       error (EXIT_FAILURE, errno, "%s", side->filename);
     }
   side->character = getc (side->file);
   side->position = 0;

reply via email to

[Prev in Thread] Current Thread [Next in Thread]