Allow output files to overwrite input files (bug #21280). Thanks to
[pspp-builds.git] / src / data / por-file-reader.c
index 9977158ee1991a0687304ba70c2e8ab94b85a3ce..668a8429d5839d9f8fb810009ef50d24d25eb169 100644 (file)
@@ -35,7 +35,6 @@
 #include <data/missing-values.h>
 #include <data/value-labels.h>
 #include <data/variable.h>
-#include <libpspp/alloc.h>
 #include <libpspp/compiler.h>
 #include <libpspp/hash.h>
 #include <libpspp/message.h>
@@ -43,6 +42,8 @@
 #include <libpspp/pool.h>
 #include <libpspp/str.h>
 
+#include "xalloc.h"
+
 #include "gettext.h"
 #define _(msgid) gettext (msgid)
 
@@ -64,6 +65,7 @@ struct pfm_reader
     jmp_buf bail_out;           /* longjmp() target for error handling. */
 
     struct file_handle *fh;     /* File handle. */
+    struct fh_lock *lock;       /* Read lock for file. */
     FILE *file;                        /* File stream. */
     int line_length;            /* Number of characters so far on this line. */
     char cc;                   /* Current character. */
@@ -156,8 +158,8 @@ close_reader (struct pfm_reader *r)
       r->file = NULL;
     }
 
-  if (r->fh != NULL)
-    fh_close (r->fh, "portable file", "rs");
+  fh_unlock (r->lock);
+  fh_unref (r->fh);
 
   ok = r->ok;
   pool_destroy (r->pool);
@@ -240,15 +242,14 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   struct pfm_reader *volatile r = NULL;
 
   *dict = dict_create ();
-  if (!fh_open (fh, FH_REF_FILE, "portable file", "rs"))
-    goto error;
 
   /* Create and initialize reader. */
   pool = pool_create ();
   r = pool_alloc (pool, sizeof *r);
   r->pool = pool;
-  r->fh = fh;
-  r->file = fn_open (fh_get_file_name (r->fh), "rb");
+  r->fh = fh_ref (fh);
+  r->lock = NULL;
+  r->file = NULL;
   r->line_length = 0;
   r->weight_index = -1;
   r->trans = NULL;
@@ -256,11 +257,16 @@ pfm_open_reader (struct file_handle *fh, struct dictionary **dict,
   r->widths = NULL;
   r->value_cnt = 0;
   r->ok = true;
-
   if (setjmp (r->bail_out))
     goto error;
 
-  /* Check that file open succeeded. */
+  /* Lock file. */
+  r->lock = fh_lock (fh, FH_REF_FILE, "portable file", FH_ACC_READ, false);
+  if (r->lock == NULL)
+    goto error;
+
+  /* Open file. */
+  r->file = fn_open (fh_get_file_name (r->fh), "rb");
   if (r->file == NULL)
     {
       msg (ME, _("An error occurred while opening \"%s\" for reading "
@@ -514,9 +520,9 @@ read_version_data (struct pfm_reader *r, struct pfm_read_info *info)
 
   /* Validate file. */
   if (strlen (date) != 8)
-    error (r, _("Bad date string length %d."), (int) strlen (date));
+    error (r, _("Bad date string length %zu."), strlen (date));
   if (strlen (time) != 6)
-    error (r, _("Bad time string length %d."), (int) strlen (time));
+    error (r, _("Bad time string length %zu."), strlen (time));
 
   /* Save file info. */
   if (info != NULL)