#include <data/file-handle-def.h>
#include <data/file-name.h>
#include <data/format.h>
+#include <data/make-file.h>
#include <data/missing-values.h>
#include <data/settings.h>
#include <data/short-names.h>
#include "gettext.h"
#define _(msgid) gettext (msgid)
+#define N_(msgid) (msgid)
/* Compression bias used by PSPP. Values between (1 -
COMPRESSION_BIAS) and (251 - COMPRESSION_BIAS) inclusive can be
struct sfm_writer
{
struct file_handle *fh; /* File handle. */
+ struct fh_lock *lock; /* Mutual exclusion for file. */
FILE *file; /* File stream. */
+ struct replace_file *rf; /* Ticket for replacing output file. */
bool compress; /* 1=compressed, 0=not compressed. */
casenumber case_cnt; /* Number of cases written so far. */
sfm_open_writer (struct file_handle *fh, struct dictionary *d,
struct sfm_write_options opts)
{
- struct sfm_writer *w = NULL;
+ struct sfm_writer *w;
mode_t mode;
- FILE *file;
int idx;
int i;
opts.version = 3;
}
- /* 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;
- 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 = file;
+ w->fh = fh_ref (fh);
+ w->lock = NULL;
+ w->file = NULL;
+ w->rf = NULL;
w->compress = opts.compress;
w->case_cnt = 0;
w->segment_cnt = sfm_dictionary_to_sfm_vars (d, &w->sfm_vars,
&w->sfm_var_cnt);
+ /* Open file handle as an exclusive writer. */
+ /* TRANSLATORS: this fragment will be interpolated into
+ messages in fh_lock() that identify types of files. */
+ w->lock = fh_lock (fh, FH_REF_FILE, N_("system file"), FH_ACC_WRITE, true);
+ if (w->lock == NULL)
+ goto error;
+
+ /* Create the file on disk. */
+ mode = S_IRUSR | S_IRGRP | S_IROTH;
+ if (opts.create_writeable)
+ mode |= S_IWUSR | S_IWGRP | S_IWOTH;
+ w->rf = replace_file_start (fh_get_file_name (fh), "wb", mode,
+ &w->file, NULL);
+ if (w->rf == NULL)
+ {
+ msg (ME, _("Error opening \"%s\" for writing as a system file: %s."),
+ fh_get_file_name (fh), strerror (errno));
+ goto error;
+ }
+
/* Write the file header. */
write_header (w, d);
return casewriter_create (dict_get_next_value_idx (d),
&sys_file_casewriter_class, w);
+
+error:
+ close_writer (w);
+ return NULL;
}
/* Returns value of X truncated to two least-significant digits. */
if (mv_has_range (mv))
{
double x, y;
- mv_peek_range (mv, &x, &y);
+ mv_get_range (mv, &x, &y);
write_float (w, x);
write_float (w, y);
}
for (i = 0; i < mv_n_values (mv); i++)
{
union value value;
- mv_peek_value (mv, &value, i);
+ mv_get_value (mv, &value, i);
write_value (w, &value, seg0_width);
}
if (!ok)
msg (ME, _("An I/O error occurred writing system file \"%s\"."),
fh_get_file_name (w->fh));
+
+ if (ok ? !replace_file_commit (w->rf) : !replace_file_abort (w->rf))
+ ok = false;
}
- fh_close (w->fh, "system file", "we");
+ fh_unlock (w->lock);
+ fh_unref (w->fh);
free (w->sfm_vars);
free (w);