fbuf: New data structure for buffered file I/O.
[pspp] / src / data / make-file.c
index 78875746f24ea2ff99860c5af75825da78e60fe4..a5b68051ac4d6a6c431a9bded84e02a707a29bff 100644 (file)
@@ -193,13 +193,12 @@ static void free_replace_file (struct replace_file *);
 static void unlink_replace_files (void);
 
 struct replace_file *
-replace_file_start (const struct file_handle *fh, const char *mode,
-                    mode_t permissions, FILE **fp)
+replace_file_start_fd (const struct file_handle *fh,
+                       bool binary, mode_t permissions, int *fd)
 {
   static bool registered;
   struct TS_stat s;
   struct replace_file *rf;
-  int fd;
   int saved_errno = errno;
 
   const char *file_name = fh_get_file_name (fh);
@@ -211,8 +210,8 @@ replace_file_start (const struct file_handle *fh, const char *mode,
   if (Tstat (Tfile_name, &s) == 0 && !S_ISREG (s.st_mode))
     {
       /* Open file descriptor. */
-      fd = Topen (Tfile_name, O_WRONLY);
-      if (fd < 0)
+      *fd = Topen (Tfile_name, O_WRONLY);
+      if (*fd < 0)
         {
          saved_errno = errno;
           msg (ME, _("Opening %s for writing: %s."),
@@ -221,18 +220,6 @@ replace_file_start (const struct file_handle *fh, const char *mode,
           return NULL;
         }
 
-      /* Open file as stream. */
-      *fp = fdopen (fd, mode);
-      if (*fp == NULL)
-        {
-         saved_errno = errno;
-         msg (ME, _("Opening stream for %s: %s."),
-               file_name, strerror (saved_errno));
-          close (fd);
-         free (Tfile_name);
-          return NULL;
-        }
-
       rf = xzalloc (sizeof *rf);
       rf->file_name = NULL;
       rf->tmp_name = Tfile_name;
@@ -266,8 +253,9 @@ replace_file_start (const struct file_handle *fh, const char *mode,
       rf->tmp_name = convert_to_filename_encoding (rf->tmp_name_verbatim, strlen (rf->tmp_name_verbatim), fh_get_file_name_encoding (fh));
 
       /* Create file by that name. */
-      fd = Topen (rf->tmp_name, O_WRONLY | O_CREAT | O_EXCL | O_BINARY, permissions);
-      if (fd >= 0)
+      int flags = O_WRONLY | O_CREAT | O_EXCL | (binary ? O_BINARY : O_TEXT);
+      *fd = Topen (rf->tmp_name, flags, permissions);
+      if (*fd >= 0)
         break;
       if (errno != EEXIST)
         {
@@ -279,29 +267,50 @@ replace_file_start (const struct file_handle *fh, const char *mode,
     }
 
 
+  /* Register file for deletion. */
+  ll_push_head (&all_files, &rf->ll);
+  unblock_fatal_signals ();
+
+  return rf;
+
+ error:
+  unblock_fatal_signals ();
+  free_replace_file (rf);
+  *fd = -1;
+  errno = saved_errno;
+  return NULL;
+}
+
+struct replace_file *
+replace_file_start (const struct file_handle *fh, bool binary,
+                    mode_t permissions, FILE **fp)
+{
+  struct replace_file *rf;
+  int fd;
+
+  /* Open fd. */
+  rf = replace_file_start_fd (fh, binary, permissions, &fd);
+  if (!rf)
+    goto error;
+
   /* Open file as stream. */
-  *fp = fdopen (fd, mode);
+  *fp = fdopen (fd, binary ? "wb" : "w");
   if (*fp == NULL)
     {
-      saved_errno = errno;
+      int error = errno;
       msg (ME, _("Opening stream for temporary file %s: %s."),
-           rf->tmp_name_verbatim, strerror (saved_errno));
+           rf->tmp_name_verbatim, strerror (error));
       close (fd);
-      Tunlink (rf->tmp_name);
+      replace_file_abort (rf);
+      errno = error;
+
       goto error;
     }
 
-  /* Register file for deletion. */
-  ll_push_head (&all_files, &rf->ll);
-  unblock_fatal_signals ();
-
   return rf;
 
- error:
-  unblock_fatal_signals ();
-  free_replace_file (rf);
+error:
   *fp = NULL;
-  errno = saved_errno;
   return NULL;
 }