X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdata%2Fsys-file-writer.c;h=fd663d69b5bc7532d98412eeebf865dcd41d61fa;hb=cd3e91d39a1f9b80c8e81e54942a1be1aed81213;hp=6b4344a79d779a1bed28c0ea58c42f9f8dd6854d;hpb=679e253a4777564db48ccec70b8ce2f6e5b7e46b;p=pspp-builds.git diff --git a/src/data/sys-file-writer.c b/src/data/sys-file-writer.c index 6b4344a7..fd663d69 100644 --- a/src/data/sys-file-writer.c +++ b/src/data/sys-file-writer.c @@ -21,17 +21,13 @@ #include #include -#include #include #include #include #include -#include -#include #include #include -#include #include #include #include @@ -42,7 +38,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -51,9 +49,11 @@ #include "minmax.h" #include "unlocked-io.h" +#include "xalloc.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 @@ -64,7 +64,9 @@ 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. */ @@ -150,9 +152,8 @@ struct casewriter * 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; - int fd; int idx; int i; @@ -164,22 +165,12 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d, opts.version = 3; } - /* 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, "system file", "we")) - goto error; - /* Create and initialize writer. */ w = xmalloc (sizeof *w); - w->fh = fh; - w->file = fdopen (fd, "w"); + w->fh = fh_ref (fh); + w->lock = NULL; + w->file = NULL; + w->rf = NULL; w->compress = opts.compress; w->case_cnt = 0; @@ -193,11 +184,24 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d, w->segment_cnt = sfm_dictionary_to_sfm_vars (d, &w->sfm_vars, &w->sfm_var_cnt); - /* Check that file create succeeded. */ - if (w->file == NULL) + /* 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) { - close (fd); - goto open_error; + 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. */ @@ -236,18 +240,17 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d, write_int (w, 0); if (write_error (w)) - goto error; + { + close_writer (w); + return NULL; + } - return casewriter_create (&sys_file_casewriter_class, w); + return casewriter_create (dict_get_next_value_idx (d), + &sys_file_casewriter_class, w); - error: +error: close_writer (w); return NULL; - - open_error: - msg (ME, _("Error opening \"%s\" for writing as a system file: %s."), - fh_get_file_name (fh), strerror (errno)); - goto error; } /* Returns value of X truncated to two least-significant digits. */ @@ -418,7 +421,7 @@ write_variable (struct sfm_writer *w, const struct variable *v) /* Number of missing values. If there is a range, then the range counts as 2 missing values and causes the number to be negated. */ - write_int (w, mv_has_range (mv) ? 2 - mv_n_values (mv) : mv_n_values (mv)); + write_int (w, mv_has_range (mv) ? -2 - mv_n_values (mv) : mv_n_values (mv)); /* Print and write formats. */ write_format (w, *var_get_print_format (v), seg0_width); @@ -442,14 +445,14 @@ write_variable (struct sfm_writer *w, const struct variable *v) 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); } @@ -733,9 +736,13 @@ close_writer (struct sfm_writer *w) 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);