fbuf: New data structure for buffered file I/O.
[pspp] / src / language / data-io / data-writer.c
index 5270db0e8119f86236ba5e64e68a510b8cf6840c..2e03218f69c287bcc418b5d13c6864e4ccd77791 100644 (file)
@@ -1,5 +1,5 @@
 /* PSPP - a program for statistical analysis.
-   Copyright (C) 1997-2004, 2006, 2010, 2011, 2012 Free Software Foundation, Inc.
+   Copyright (C) 1997-2004, 2006, 2010, 2011, 2012, 2013 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -49,8 +49,10 @@ struct dfm_writer
     FILE *file;                 /* Associated file. */
     struct replace_file *rf;    /* Atomic file replacement support. */
     char *encoding;             /* Encoding. */
+    enum fh_line_ends line_ends; /* Line ends for text files. */
 
     int unit;                   /* Unit width, in bytes. */
+    char cr[MAX_UNIT];          /* \r in encoding, 'unit' bytes long. */
     char lf[MAX_UNIT];          /* \n in encoding, 'unit' bytes long. */
     char spaces[32];            /* 32 bytes worth of ' ' in encoding. */
   };
@@ -90,10 +92,11 @@ dfm_open_writer (struct file_handle *fh, const char *encoding)
   w = xmalloc (sizeof *w);
   w->fh = fh_ref (fh);
   w->lock = lock;
-  w->rf = replace_file_start (fh_get_file_name (w->fh), "wb", 0666,
-                              &w->file, NULL);
+  w->rf = replace_file_start (w->fh, true, 0666, &w->file);
   w->encoding = xstrdup (encoding);
+  w->line_ends = fh_get_line_ends (fh);
   w->unit = ei.unit;
+  memcpy (w->cr, ei.cr, sizeof w->cr);
   memcpy (w->lf, ei.lf, sizeof w->lf);
   for (ofs = 0; ofs + ei.unit <= sizeof w->spaces; ofs += ei.unit)
     memcpy (&w->spaces[ofs], ei.space, ei.unit);
@@ -111,7 +114,7 @@ dfm_open_writer (struct file_handle *fh, const char *encoding)
   return w;
 }
 
-/* Returns false if an I/O error occurred on WRITER, true otherwise. */
+/* Returns true if an I/O error occurred on WRITER, false otherwise. */
 bool
 dfm_write_error (const struct dfm_writer *writer)
 {
@@ -134,6 +137,8 @@ dfm_put_record (struct dfm_writer *w, const char *rec, size_t len)
     {
     case FH_MODE_TEXT:
       fwrite (rec, len, 1, w->file);
+      if (w->line_ends == FH_END_CRLF)
+        fwrite (w->cr, w->unit, 1, w->file);
       fwrite (w->lf, w->unit, 1, w->file);
       break;
 
@@ -213,7 +218,7 @@ dfm_close_writer (struct dfm_writer *w)
   if (w->file != NULL)
     {
       const char *file_name = fh_get_file_name (w->fh);
-      ok = !dfm_write_error (w) && !fn_close (file_name, w->file);
+      ok = !dfm_write_error (w) && !fn_close (w->fh, w->file);
 
       if (!ok)
         msg (ME, _("I/O error occurred writing data file `%s'."), file_name);