Provisional fix for bug #18692 and bug #20161. Reviewed by John
authorBen Pfaff <blp@gnu.org>
Mon, 30 Jul 2007 17:07:50 +0000 (17:07 +0000)
committerBen Pfaff <blp@gnu.org>
Mon, 30 Jul 2007 17:07:50 +0000 (17:07 +0000)
Darrington.

doc/language.texi
src/data/ChangeLog
src/data/file-name.c
src/data/por-file-reader.c

index d71ecc8a3868d73a4f27d9fa3bdc70edbd6b5cb7..398f7642318ede8f973bac881479c718775ba5a2 100644 (file)
@@ -1331,6 +1331,14 @@ file, or scratch file.  Most often, a file handle is specified as the
 name of a file as a string, that is, enclosed within @samp{'} or
 @samp{"}.
 
+A file name string that begins or ends with @samp{|} is treated as the
+name of a command to pipe data to or from.  You can use this feature
+to read data over the network using a program such as @samp{curl}
+(e.g.@: @code{GET '|curl -s -S http://example.com/mydata.sav'}), to
+read compressed data from a file using a program such as @samp{zcat}
+(e.g.@: @code{GET '|zcat mydata.sav.gz'}), and for many other
+purposes.
+
 PSPP also supports declaring named file handles with the @cmd{FILE
 HANDLE} command.  This command associates an identifier of your choice
 (the file handle's name) with a file.  Later, the file handle name can
index 553b753ef66cc0de98717dafb58b731b445d6ded..c404d820e53253a40a987bc55328928b25de3b9a 100644 (file)
@@ -1,3 +1,19 @@
+2007-07-29  Ben Pfaff  <blp@gnu.org>
+
+       Provisional fix for bug #18692 and bug #20161.  Reviewed by John
+       Darrington.
+
+       * file-name.c (fn_open): Only pass "r" or "w" to popen as mode
+       argument (never "rb" or "wb") because SUSv3 says that only those
+       modes are defined, and glibc in fact rejects other modes.
+
+       Open portable files with fn_open so that they can be read from
+       pipes.  Fix missing fh_close call to go along with fh_open.
+       Report an error if the file close reports an error.
+       * por-file-reader.c (close_reader): New function.
+       (por_file_casereader_destroy): Use close_reader.
+       (pfm_open_reader): Open file with fn_open.
+
 2007-07-28  Ben Pfaff  <blp@gnu.org>
 
        Make PSPP able to read all the portable files I could find on the
index 23d7ee0889f2c75460e8d479eb177b7acc2f75d9..cfe91932414e0c4bec928c89cb6efebd043f93ae 100644 (file)
@@ -267,7 +267,7 @@ fn_open (const char *fn, const char *mode)
       if (get_safer_mode ())
        return safety_violation (fn);
 
-      return popen (&fn[1], mode);
+      return popen (&fn[1], mode[0] == 'r' ? "r" : "w");
     }
   else if (*fn && fn[strlen (fn) - 1] == '|')
     {
@@ -281,7 +281,7 @@ fn_open (const char *fn, const char *mode)
       memcpy (s, fn, strlen (fn) - 1);
       s[strlen (fn) - 1] = 0;
 
-      f = popen (s, mode);
+      f = popen (s, mode[0] == 'r' ? "r" : "w");
 
       local_free (s);
 
index e82e136167b9a06c006be699dd2929a03ddaf4b0..8e6099f5d8ec5bed03ed9d19aca7b2ce32ac6b34 100644 (file)
@@ -30,6 +30,7 @@
 #include <data/casereader.h>
 #include <data/dictionary.h>
 #include <data/file-handle-def.h>
+#include <data/file-name.h>
 #include <data/format.h>
 #include <data/missing-values.h>
 #include <data/value-labels.h>
@@ -136,12 +137,42 @@ warning (struct pfm_reader *r, const char *msg, ...)
   msg_emit (&m);
 }
 
+/* Close and destroy R.
+   Returns false if an error was detected on R, true otherwise. */
+static bool
+close_reader (struct pfm_reader *r)
+{
+  bool ok;
+  if (r == NULL)
+    return true;
+
+  if (r->file)
+    {
+      if (fn_close (fh_get_file_name (r->fh), r->file) == EOF)
+        {
+          msg (ME, _("Error closing portable file \"%s\": %s."),
+               fh_get_file_name (r->fh), strerror (errno));
+          r->ok = false;
+        }
+      r->file = NULL;
+    }
+
+  if (r->fh != NULL)
+    fh_close (r->fh, "portable file", "rs");
+
+  ok = r->ok;
+  pool_destroy (r->pool);
+
+  return ok;
+}
+
 /* Closes portable file reader R, after we're done with it. */
 static void
-por_file_casereader_destroy (struct casereader *reader UNUSED, void *r_)
+por_file_casereader_destroy (struct casereader *reader, void *r_)
 {
   struct pfm_reader *r = r_;
-  pool_destroy (r->pool);
+  if (!close_reader (r))
+    casereader_force_error (reader);
 }
 
 /* Read a single character into cur_char.  */
@@ -217,10 +248,8 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   pool = pool_create ();
   r = pool_alloc (pool, sizeof *r);
   r->pool = pool;
-  if (setjmp (r->bail_out))
-    goto error;
   r->fh = fh;
-  r->file = pool_fopen (r->pool, fh_get_file_name (r->fh), "rb");
+  r->file = fn_open (fh_get_file_name (r->fh), "rb");
   r->line_length = 0;
   r->weight_index = -1;
   r->trans = NULL;
@@ -229,7 +258,10 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   r->value_cnt = 0;
   r->ok = true;
 
-  /* Check that file open succeeded, prime reading. */
+  if (setjmp (r->bail_out))
+    goto error;
+
+  /* Check that file open succeeded. */
   if (r->file == NULL)
     {
       msg (ME, _("An error occurred while opening \"%s\" for reading "
@@ -260,7 +292,7 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
                                        &por_file_casereader_class, r);
 
  error:
-  pool_destroy (r->pool);
+  close_reader (r);
   dict_destroy (*dict);
   *dict = NULL;
   return NULL;