X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;ds=sidebyside;f=src%2Flibpspp%2Ftemp-file.c;h=9d3c392659753043667af822b9bbfe7bd3e1b0f0;hb=fc01177a9fccd839df87c5784abec33b69b4019c;hp=554a6d7d5f74276774057905fe2e71ef318df919;hpb=70514b3f2f32d57e58b04c01c83bc5f372559824;p=pspp
diff --git a/src/libpspp/temp-file.c b/src/libpspp/temp-file.c
index 554a6d7d5f..9d3c392659 100644
--- a/src/libpspp/temp-file.c
+++ b/src/libpspp/temp-file.c
@@ -1,5 +1,5 @@
/* PSPP - a program for statistical analysis.
- Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2010, 2011 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
@@ -14,154 +14,98 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see . */
-/* A interface to allow a temporary file to be treated as an
- array of data. */
+/* Functions for temporary files that honor $TMPDIR. */
#include
-#include
+#include "libpspp/temp-file.h"
+#include "libpspp/hmapx.h"
+#include "libpspp/hash-functions.h"
-#include
-#include
#include
-#include
-#include
+#include "gl/clean-temp.h"
+#include "gl/xvasprintf.h"
-#include "error.h"
-#include "xalloc.h"
+/* Creates and returns a new temporary file that will be removed automatically
+ when the process exits. The file is opened in mode "wb+". To close the
+ file before the process exits, use close_temp_file() to ensure that it gets
+ deleted early.
-#include "gettext.h"
-#define _(msgid) gettext (msgid)
+ Returns NULL if creating the temporary file fails.
-struct temp_file
- {
- FILE *file; /* Underlying file. */
+ This is similar to tmpfile(), except:
- /* Current byte offset in file. We track this manually,
- instead of using ftello, because in glibc ftello flushes
- the stream buffer, making the common case of sequential
- access to cases unreasonably slow. */
- off_t position;
- };
+ - It honors the $TMPDIR environment variable.
+
+*/
-/* Creates and returns a new temporary file. The temporary file
- will be automatically deleted when the process exits. */
-struct temp_file *
-temp_file_create (void)
-{
- struct temp_file *tf = xmalloc (sizeof *tf);
- tf->file = tmpfile ();
- if (tf->file == NULL)
- error (0, errno, _("failed to create temporary file"));
- tf->position = 0;
- return tf;
-}
-/* Closes and destroys temporary file TF. Returns true if I/O on
- TF always succeeded, false if an I/O error occurred at some
- point. */
-bool
-temp_file_destroy (struct temp_file *tf)
+static struct temp_dir *temp_dir;
+struct hmapx map;
+
+static void
+setup (void)
{
- bool ok = true;
- if (tf != NULL)
- {
- ok = !temp_file_error (tf);
- if (tf->file != NULL)
- fclose (tf->file);
- free (tf);
- }
- return ok;
+ hmapx_init (&map);
+ temp_dir = create_temp_dir ("pspp", NULL, true);
}
-/* Seeks TF's underlying file to the start of `union value'
- VALUE_IDX within case CASE_IDX.
- Returns true if the seek is successful and TF is not
- otherwise tainted, false otherwise. */
-static bool
-do_seek (const struct temp_file *tf_, off_t offset)
+static void
+cleanup (void)
{
- struct temp_file *tf = CONST_CAST (struct temp_file *, tf_);
+ struct hmapx_node *node;
+ char *fn;
+
+ cleanup_temp_dir (temp_dir);
- if (!temp_file_error (tf))
+ HMAPX_FOR_EACH (fn, node, &map)
{
- if (tf->position == offset)
- return true;
- else if (fseeko (tf->file, offset, SEEK_SET) == 0)
- {
- tf->position = offset;
- return true;
- }
- else
- error (0, errno, _("seeking in temporary file"));
+ free (fn);
}
- return false;
+ hmapx_destroy (&map);
}
-/* Reads BYTES bytes from TF's underlying file into BUFFER.
- TF must not be tainted upon entry into this function.
- Returns true if successful, false upon an I/O error (in which
- case TF is marked tainted). */
-static bool
-do_read (const struct temp_file *tf_, void *buffer, size_t bytes)
+FILE *
+create_temp_file (void)
{
- struct temp_file *tf = CONST_CAST (struct temp_file *, tf_);
+ static int idx = 0;
+ char *file_name;
+ FILE *stream;
- assert (!temp_file_error (tf));
- if (bytes > 0 && fread (buffer, bytes, 1, tf->file) != 1)
+ if (temp_dir == NULL)
{
- if (ferror (tf->file))
- error (0, errno, _("reading temporary file"));
- else if (feof (tf->file))
- error (0, 0, _("unexpected end of file reading temporary file"));
- else
- NOT_REACHED ();
- return false;
+ setup ();
+ if (temp_dir == NULL)
+ return NULL;
+ atexit (cleanup);
}
- tf->position += bytes;
- return true;
-}
-/* Writes BYTES bytes from BUFFER into TF's underlying file.
- TF must not be tainted upon entry into this function.
- Returns true if successful, false upon an I/O error (in which
- case TF is marked tainted). */
-static bool
-do_write (struct temp_file *tf, const void *buffer, size_t bytes)
-{
- assert (!temp_file_error (tf));
- if (bytes > 0 && fwrite (buffer, bytes, 1, tf->file) != 1)
- {
- error (0, errno, _("writing to temporary file"));
- return false;
- }
- tf->position += bytes;
- return true;
-}
+ file_name = xasprintf ("%s/%d", temp_dir->dir_name, idx++);
+ register_temp_file (temp_dir, file_name);
+ stream = fopen_temp (file_name, "wb+");
+ if (stream == NULL)
+ unregister_temp_file (temp_dir, file_name);
+ else
+ setvbuf (stream, NULL, _IOFBF, 65536);
-/* Reads N bytes from TF at byte offset OFFSET into DATA.
- Returns true if successful, false on failure. */
-bool
-temp_file_read (const struct temp_file *tf, off_t offset, size_t n, void *data)
-{
- return do_seek (tf, offset) && do_read (tf, data, n);
-}
+ hmapx_insert (&map, file_name, hash_pointer (stream, 0));
-/* Writes the N bytes in DATA to TF at byte offset OFFSET.
- Returns true if successful, false on failure. */
-bool
-temp_file_write (struct temp_file *tf, off_t offset, size_t n,
- const void *data)
-{
- return do_seek (tf, offset) && do_write (tf, data, n);
+ return stream;
}
-/* Returns true if an error has occurred in I/O on TF,
- false if no error has been detected. */
-bool
-temp_file_error (const struct temp_file *tf)
+/* Closes and removes a temporary file created by create_temp_file(). */
+void
+close_temp_file (FILE *file)
{
- return tf->file == NULL || ferror (tf->file) || feof (tf->file);
+ if (file != NULL)
+ {
+ struct hmapx_node *node = hmapx_first_with_hash (&map, hash_pointer (file, 0));
+ char *fn = node->data;
+ fclose_temp (file);
+ cleanup_temp_file (temp_dir, fn);
+ hmapx_delete (&map, node);
+ free (fn);
+ }
}