pspp-cvs
[Top][All Lists]
Advanced

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

[Pspp-cvs] pspp src/data/ChangeLog src/data/file-name.c sr...


From: Ben Pfaff
Subject: [Pspp-cvs] pspp src/data/ChangeLog src/data/file-name.c sr...
Date: Tue, 09 Oct 2007 03:50:21 +0000

CVSROOT:        /cvsroot/pspp
Module name:    pspp
Changes by:     Ben Pfaff <blp> 07/10/09 03:50:21

Modified files:
        src/data       : ChangeLog file-name.c file-name.h 
                         por-file-writer.c sys-file-writer.c 
        tests          : ChangeLog automake.mk 
Added files:
        tests/bugs     : overwrite-input-file.sh 

Log message:
        Fix bug #21280.  Thanks to John Darrington for review.
        
        * automake.mk: Add new file.
        
        * bugs/overwrite-input-file.sh: New test.
        
        * file-name.c (create_stream): New function.
        
        * por-file-writer.c (pfm_open_writer): Use fh_open to open the
        file handle before creating the file, to ensure that we don't
        truncate a file that we're reading.  Make code easier to read by
        using create_stream.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/ChangeLog?cvsroot=pspp&r1=1.162&r2=1.163
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/file-name.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/file-name.h?cvsroot=pspp&r1=1.10&r2=1.11
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/por-file-writer.c?cvsroot=pspp&r1=1.17&r2=1.18
http://cvs.savannah.gnu.org/viewcvs/pspp/src/data/sys-file-writer.c?cvsroot=pspp&r1=1.31&r2=1.32
http://cvs.savannah.gnu.org/viewcvs/pspp/tests/ChangeLog?cvsroot=pspp&r1=1.111&r2=1.112
http://cvs.savannah.gnu.org/viewcvs/pspp/tests/automake.mk?cvsroot=pspp&r1=1.40&r2=1.41
http://cvs.savannah.gnu.org/viewcvs/pspp/tests/bugs/overwrite-input-file.sh?cvsroot=pspp&rev=1.1

Patches:
Index: src/data/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/ChangeLog,v
retrieving revision 1.162
retrieving revision 1.163
diff -u -b -r1.162 -r1.163
--- src/data/ChangeLog  2 Oct 2007 04:13:07 -0000       1.162
+++ src/data/ChangeLog  9 Oct 2007 03:50:20 -0000       1.163
@@ -1,3 +1,16 @@
+2007-10-08  Ben Pfaff  <address@hidden>
+
+       Fix bug #21280.  Thanks to John Darrington for review.
+
+       * file-name.c (create_stream): New function.
+
+       * por-file-writer.c (pfm_open_writer): Use fh_open to open the
+       file handle before creating the file, to ensure that we don't
+       truncate a file that we're reading.  Make code easier to read by
+       using create_stream.
+
+       * sys-file-write.c (sfm_open_writer): Ditto.
+
 2007-10-01  Ben Pfaff  <address@hidden>
 
        Fix bug #21192.  Thanks to John Darrington for review.

Index: src/data/file-name.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/file-name.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/data/file-name.c        16 Aug 2007 06:30:23 -0000      1.17
+++ src/data/file-name.c        9 Oct 2007 03:50:20 -0000       1.18
@@ -20,8 +20,10 @@
 
 #include <ctype.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #include "intprops.h"
 #include "minmax.h"
@@ -320,6 +322,30 @@
     return fclose (f);
 }
 
+/* Creates a new file named FN with the given PERMISSIONS bits,
+   and returns a stream for it or a null pointer on failure.
+   MODE should be "w" or "wb". */
+FILE *
+create_stream (const char *fn, const char *mode, mode_t permissions)
+{
+  int fd;
+  FILE *stream;
+
+  fd = open (fn, O_WRONLY | O_CREAT | O_TRUNC, permissions);
+  if (fd < 0)
+    return NULL;
+
+  stream = fdopen (fd, mode);
+  if (stream == NULL)
+    {
+      int save_errno = errno;
+      close (fd);
+      errno = save_errno;
+    }
+
+  return stream;
+}
+
 #if !(defined _WIN32 || defined __WIN32__)
 /* A file's identity. */
 struct file_identity

Index: src/data/file-name.h
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/file-name.h,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -b -r1.10 -r1.11
--- src/data/file-name.h        7 Jul 2007 06:14:08 -0000       1.10
+++ src/data/file-name.h        9 Oct 2007 03:50:20 -0000       1.11
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdbool.h>
 #include <libpspp/str.h>
+#include <sys/types.h>
 
 /* Search path for configuration files. */
 extern const char *config_path;
@@ -43,6 +44,8 @@
 FILE *fn_open (const char *fn, const char *mode);
 int fn_close (const char *fn, FILE *file);
 
+FILE *create_stream (const char *fn, const char *mode, mode_t permissions);
+
 struct file_identity *fn_get_identity (const char *file_name);
 void fn_free_identity (struct file_identity *);
 int fn_compare_file_identities (const struct file_identity *,

Index: src/data/por-file-writer.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/por-file-writer.c,v
retrieving revision 1.17
retrieving revision 1.18
diff -u -b -r1.17 -r1.18
--- src/data/por-file-writer.c  13 Aug 2007 00:41:35 -0000      1.17
+++ src/data/por-file-writer.c  9 Oct 2007 03:50:20 -0000       1.18
@@ -19,20 +19,19 @@
 
 #include <ctype.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <float.h>
 #include <math.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <time.h>
-#include <unistd.h>
 
 #include <data/case.h>
 #include <data/casewriter-provider.h>
 #include <data/casewriter.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/short-names.h>
@@ -109,30 +108,31 @@
 {
   struct pfm_writer *w = NULL;
   mode_t mode;
-  int fd;
+  FILE *file;
   size_t i;
 
+  /* Open file handle. */
+  if (!fh_open (fh, FH_REF_FILE, "portable file", "we"))
+    return NULL;
+
   /* Create file. */
   mode = S_IRUSR | S_IRGRP | S_IROTH;
   if (opts.create_writeable)
     mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-  fd = open (fh_get_file_name (fh), O_WRONLY | O_CREAT | O_TRUNC, mode);
-  if (fd < 0)
-    goto open_error;
-
-  /* Open file handle. */
-  if (!fh_open (fh, FH_REF_FILE, "portable file", "we"))
-    goto error;
+  file = create_stream (fh_get_file_name (fh), "w", mode);
+  if (file == NULL)
+    {
+      fh_close (fh, "portable file", "we");
+      msg (ME, _("An error occurred while opening \"%s\" for writing "
+                 "as a portable file: %s."),
+           fh_get_file_name (fh), strerror (errno));
+      return NULL;
+    }
 
   /* Initialize data structures. */
   w = xmalloc (sizeof *w);
   w->fh = fh;
-  w->file = fdopen (fd, "w");
-  if (w->file == NULL)
-    {
-      close (fd);
-      goto open_error;
-    }
+  w->file = file;
 
   w->lc = 0;
   w->var_cnt = 0;
@@ -165,19 +165,12 @@
     write_documents (w, dict);
   buf_write (w, "F", 1);
   if (ferror (w->file))
-    goto error;
-  return casewriter_create (dict_get_next_value_idx (dict),
-                            &por_file_casewriter_class, w);
-
- error:
+    {
   close_writer (w);
   return NULL;
-
- open_error:
-  msg (ME, _("An error occurred while opening \"%s\" for writing "
-             "as a portable file: %s."),
-       fh_get_file_name (fh), strerror (errno));
-  goto error;
+    }
+  return casewriter_create (dict_get_next_value_idx (dict),
+                            &por_file_casewriter_class, w);
 }
 
 /* Write NBYTES starting at BUF to the portable file represented by

Index: src/data/sys-file-writer.c
===================================================================
RCS file: /cvsroot/pspp/pspp/src/data/sys-file-writer.c,v
retrieving revision 1.31
retrieving revision 1.32
diff -u -b -r1.31 -r1.32
--- src/data/sys-file-writer.c  13 Aug 2007 00:41:35 -0000      1.31
+++ src/data/sys-file-writer.c  9 Oct 2007 03:50:20 -0000       1.32
@@ -21,12 +21,10 @@
 
 #include <ctype.h>
 #include <errno.h>
-#include <fcntl.h>
 #include <stdint.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <time.h>
-#include <unistd.h>
 
 #include <libpspp/alloc.h>
 #include <libpspp/float-format.h>
@@ -42,6 +40,7 @@
 #include <data/casewriter.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/settings.h>
@@ -152,7 +151,7 @@
 {
   struct sfm_writer *w = NULL;
   mode_t mode;
-  int fd;
+  FILE *file;
   int idx;
   int i;
 
@@ -164,22 +163,27 @@
       opts.version = 3;
     }
 
-  /* Create file. */
+  /* Open file handle as an exclusive writer. */
+  if (!fh_open (fh, FH_REF_FILE, "system file", "we"))
+    return NULL;
+
+  /* Create the file on disk. */
   mode = S_IRUSR | S_IRGRP | S_IROTH;
   if (opts.create_writeable)
     mode |= S_IWUSR | S_IWGRP | S_IWOTH;
-  fd = open (fh_get_file_name (fh), O_WRONLY | O_CREAT | O_TRUNC, mode);
-  if (fd < 0)
-    goto open_error;
-
-  /* Open file handle. */
-  if (!fh_open (fh, FH_REF_FILE, "system file", "we"))
-    goto error;
+  file = create_stream (fh_get_file_name (fh), "w", mode);
+  if (file == NULL)
+    {
+      msg (ME, _("Error opening \"%s\" for writing as a system file: %s."),
+           fh_get_file_name (fh), strerror (errno));
+      fh_close (fh, "system file", "we");
+      return NULL;
+    }
 
   /* Create and initialize writer. */
   w = xmalloc (sizeof *w);
   w->fh = fh;
-  w->file = fdopen (fd, "w");
+  w->file = file;
 
   w->compress = opts.compress;
   w->case_cnt = 0;
@@ -193,13 +197,6 @@
   w->segment_cnt = sfm_dictionary_to_sfm_vars (d, &w->sfm_vars,
                                                &w->sfm_var_cnt);
 
-  /* Check that file create succeeded. */
-  if (w->file == NULL)
-    {
-      close (fd);
-      goto open_error;
-    }
-
   /* Write the file header. */
   write_header (w, d);
 
@@ -236,19 +233,13 @@
   write_int (w, 0);
 
   if (write_error (w))
-    goto error;
-
-  return casewriter_create (dict_get_next_value_idx (d),
-                            &sys_file_casewriter_class, w);
-
- error:
+    {
   close_writer (w);
   return NULL;
+    }
 
- open_error:
-  msg (ME, _("Error opening \"%s\" for writing as a system file: %s."),
-       fh_get_file_name (fh), strerror (errno));
-  goto error;
+  return casewriter_create (dict_get_next_value_idx (d),
+                            &sys_file_casewriter_class, w);
 }
 
 /* Returns value of X truncated to two least-significant digits. */

Index: tests/ChangeLog
===================================================================
RCS file: /cvsroot/pspp/pspp/tests/ChangeLog,v
retrieving revision 1.111
retrieving revision 1.112
diff -u -b -r1.111 -r1.112
--- tests/ChangeLog     23 Sep 2007 16:47:28 -0000      1.111
+++ tests/ChangeLog     9 Oct 2007 03:50:20 -0000       1.112
@@ -1,3 +1,11 @@
+2007-10-08  Ben Pfaff  <address@hidden>
+
+       Bug #21280.  Thanks to John Darrington for review.
+
+       * automake.mk: Add new file.
+
+       * bugs/overwrite-input-file.sh: New test.
+
 2007-09-23  Ben Pfaff  <address@hidden>
 
        Bug #21111.  Reviewed by John Darrington.

Index: tests/automake.mk
===================================================================
RCS file: /cvsroot/pspp/pspp/tests/automake.mk,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -b -r1.40 -r1.41
--- tests/automake.mk   23 Sep 2007 16:47:28 -0000      1.40
+++ tests/automake.mk   9 Oct 2007 03:50:20 -0000       1.41
@@ -106,6 +106,7 @@
        tests/bugs/list-overflow.sh \
        tests/bugs/match-files-scratch.sh \
        tests/bugs/multipass.sh \
+       tests/bugs/overwrite-input-file.sh \
        tests/bugs/random.sh \
        tests/bugs/signals.sh \
        tests/bugs/t-test-with-temp.sh \

Index: tests/bugs/overwrite-input-file.sh
===================================================================
RCS file: tests/bugs/overwrite-input-file.sh
diff -N tests/bugs/overwrite-input-file.sh
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ tests/bugs/overwrite-input-file.sh  9 Oct 2007 03:50:21 -0000       1.1
@@ -0,0 +1,125 @@
+#!/bin/sh
+
+# This program tests for a bug that caused SAVE to the file currently
+# being read with GET to truncate the save file to zero length, and
+# similarly for IMPORT/EXPORT.
+
+
+TEMPDIR=/tmp/pspp-tst-$$
+TESTFILE=$TEMPDIR/`basename $0`.sps
+
+# ensure that top_builddir  are absolute
+if [ -z "$top_builddir" ] ; then top_builddir=. ; fi
+if [ -z "$top_srcdir" ] ; then top_srcdir=. ; fi
+top_builddir=`cd $top_builddir; pwd`
+PSPP=$top_builddir/src/ui/terminal/pspp
+
+# ensure that top_srcdir is absolute
+top_srcdir=`cd $top_srcdir; pwd`
+
+STAT_CONFIG_PATH=$top_srcdir/config
+export STAT_CONFIG_PATH
+
+
+cleanup()
+{
+     cd /
+     rm -rf $TEMPDIR
+}
+
+
+fail()
+{
+    echo $activity
+    echo FAILED
+    cleanup;
+    exit 1;
+}
+
+
+no_result()
+{
+    echo $activity
+    echo NO RESULT;
+    cleanup;
+    exit 2;
+}
+
+pass()
+{
+    cleanup;
+    exit 0;
+}
+
+mkdir -p $TEMPDIR
+
+cd $TEMPDIR
+
+activity="create program 1"
+cat > $TESTFILE <<EOF
+DATA LIST /X 1.
+BEGIN DATA.
+1
+2
+3
+4
+5
+END DATA.
+
+SAVE OUTFILE='foo.sav'.
+EXPORT OUTFILE='foo.por'.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 1"
+$SUPERVISOR $PSPP --testing-mode $TESTFILE
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="check and save copy of output files"
+# Check that the files are nonzero length.
+test -s foo.sav || fail
+test -s foo.por || fail
+# Save copies of them.
+cp foo.sav foo.sav.backup || fail
+cp foo.por foo.por.backup || fail
+
+
+activity="create program 2"
+cat > $TESTFILE <<EOF
+GET 'foo.sav'.
+SAVE OUTFILE='foo.sav'.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 2"
+$SUPERVISOR $PSPP --testing-mode $TESTFILE -e /dev/null
+# This should have failed with an error message.
+if [ $? -eq 0 ] ; then no_result ; fi
+
+
+activity="create program 3"
+cat > $TESTFILE <<EOF
+IMPORT 'foo.por'.
+EXPORT OUTFILE='foo.por'.
+EOF
+if [ $? -ne 0 ] ; then no_result ; fi
+
+
+activity="run program 3"
+$SUPERVISOR $PSPP --testing-mode $TESTFILE -e /dev/null
+# This should have failed with an error message.
+if [ $? -eq 0 ] ; then no_result ; fi
+
+
+activity="compare output 1"
+cmp foo.sav foo.sav.backup
+if [ $? -ne 0 ] ; then fail ; fi
+
+activity="compare output 2"
+cmp foo.por foo.por.backup
+if [ $? -ne 0 ] ; then fail ; fi
+
+pass;




reply via email to

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