/* PSPP - a program for statistical analysis.
- Copyright (C) 1997-9, 2000, 2006 Free Software Foundation, Inc.
+ Copyright (C) 1997-9, 2000, 2006, 2009 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
#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/make-file.h>
#include <data/missing-values.h>
#include <data/short-names.h>
#include <data/value-labels.h>
#include <data/variable.h>
-#include <libpspp/alloc.h>
#include <libpspp/hash.h>
-#include <libpspp/magic.h>
#include <libpspp/message.h>
#include <libpspp/misc.h>
#include <libpspp/str.h>
#include <libpspp/version.h>
+#include "xalloc.h"
+
#include "gettext.h"
#define _(msgid) gettext (msgid)
+#define N_(msgid) (msgid)
/* Maximum width of a variable in a portable file. */
#define MAX_POR_WIDTH 255
struct pfm_writer
{
struct file_handle *fh; /* File handle. */
+ struct fh_lock *lock; /* Lock on file handle. */
FILE *file; /* File stream. */
+ struct replace_file *rf; /* Ticket for replacing output file. */
int lc; /* Number of characters on this line so far. */
int fv; /* Starting case index. */
};
-static struct casewriter_class por_file_casewriter_class;
+static const struct casewriter_class por_file_casewriter_class;
static bool close_writer (struct pfm_writer *);
static void buf_write (struct pfm_writer *, const void *, size_t);
{
struct pfm_writer *w = NULL;
mode_t mode;
- int fd;
size_t i;
- /* 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;
-
/* 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->fh = fh_ref (fh);
+ w->lock = NULL;
+ w->file = NULL;
+ w->rf = NULL;
w->lc = 0;
w->var_cnt = 0;
w->vars = NULL;
w->digits = DBL_DIG;
}
+ /* Lock file. */
+ /* 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_("portable file"), FH_ACC_WRITE, true);
+ if (w->lock == NULL)
+ goto error;
+
+ /* Create file. */
+ 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), "w", mode,
+ &w->file, NULL);
+ if (w->rf == NULL)
+ {
+ msg (ME, _("Error opening \"%s\" for writing as a portable file: %s."),
+ fh_get_file_name (fh), strerror (errno));
+ goto error;
+ }
+
/* Write file header. */
write_header (w);
write_version_data (w);
buf_write (w, "F", 1);
if (ferror (w->file))
goto error;
- return casewriter_create (&por_file_casewriter_class, w);
+ return casewriter_create (dict_get_next_value_idx (dict),
+ &por_file_casewriter_class, w);
- error:
+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;
}
\f
/* Write NBYTES starting at BUF to the portable file represented by
else
casewriter_force_error (writer);
- case_destroy (c);
+ case_unref (c);
}
static void
if (!ok)
msg (ME, _("An I/O error occurred writing portable 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, "portable file", "we");
+ fh_unlock (w->lock);
+ fh_unref (w->fh);
free (w->vars);
free (w);
0...30**6, an invariant of the loop below. */
errno = 0;
base_2_sig = frexp (value, &base_2_exp);
- if (errno != 0 || !finite (base_2_sig))
+ if (errno != 0 || !isfinite (base_2_sig))
goto missing_value;
if (base_2_exp == 0 && base_2_sig == 0.)
goto zero;
return;
}
\f
-static struct casewriter_class por_file_casewriter_class =
+static const struct casewriter_class por_file_casewriter_class =
{
por_file_casewriter_write,
por_file_casewriter_destroy,