#include <errno.h>
-/* min macro that evaluates its arguments only once. */
-#define min(a,b) \
- ({ typeof (a) _a = (a); \
- typeof (b) _b = (b); \
- _a < _b ? _a : _b; })
-
-
/* For mingw, we don't identify files by their inode number, but by a
64-bit identifier created from a BY_HANDLE_FILE_INFORMATION. */
#ifdef __MINGW32__
return id_from_handle ((HANDLE) _get_osfhandle (fd));
}
-#endif
+#endif /* HAVE_WORKING_STAT */
+#endif /* __MINGW32__ */
+
+
+/* min macro that evaluates its arguments only once. */
+#ifdef min
+#undef min
#endif
+#define min(a,b) \
+ ({ typeof (a) _a = (a); \
+ typeof (b) _b = (b); \
+ _a < _b ? _a : _b; })
+
#ifndef PATH_MAX
#define PATH_MAX 1024
#endif
#endif
+/* Fallback directory for creating temporary files. P_tmpdir is
+ defined on many POSIX platforms. */
+#ifndef P_tmpdir
+#ifdef _P_tmpdir
+#define P_tmpdir _P_tmpdir /* MinGW */
+#else
+#define P_tmpdir "/tmp"
+#endif
+#endif
+
+
/* Unix and internal stream I/O module */
static const int BUFFER_SIZE = 8192;
return retval;
}
+static const struct stream_vtable raw_vtable = {
+ .read = (void *) raw_read,
+ .write = (void *) raw_write,
+ .seek = (void *) raw_seek,
+ .tell = (void *) raw_tell,
+ .size = (void *) raw_size,
+ .trunc = (void *) raw_truncate,
+ .close = (void *) raw_close,
+ .flush = (void *) raw_flush
+};
+
static int
raw_init (unix_stream * s)
{
- s->st.read = (void *) raw_read;
- s->st.write = (void *) raw_write;
- s->st.seek = (void *) raw_seek;
- s->st.tell = (void *) raw_tell;
- s->st.size = (void *) raw_size;
- s->st.trunc = (void *) raw_truncate;
- s->st.close = (void *) raw_close;
- s->st.flush = (void *) raw_flush;
+ s->st.vptr = &raw_vtable;
s->buffer = NULL;
return 0;
return raw_close (s);
}
+static const struct stream_vtable buf_vtable = {
+ .read = (void *) buf_read,
+ .write = (void *) buf_write,
+ .seek = (void *) buf_seek,
+ .tell = (void *) buf_tell,
+ .size = (void *) buf_size,
+ .trunc = (void *) buf_truncate,
+ .close = (void *) buf_close,
+ .flush = (void *) buf_flush
+};
+
static int
buf_init (unix_stream * s)
{
- s->st.read = (void *) buf_read;
- s->st.write = (void *) buf_write;
- s->st.seek = (void *) buf_seek;
- s->st.tell = (void *) buf_tell;
- s->st.size = (void *) buf_size;
- s->st.trunc = (void *) buf_truncate;
- s->st.close = (void *) buf_close;
- s->st.flush = (void *) buf_flush;
+ s->st.vptr = &buf_vtable;
- s->buffer = get_mem (BUFFER_SIZE);
+ s->buffer = xmalloc (BUFFER_SIZE);
return 0;
}
}
-/* Stream read function for character(kine=1) internal units. */
+/* Stream read function for character(kind=1) internal units. */
static ssize_t
mem_read (stream * s, void * buf, ssize_t nbytes)
return 0;
}
+static const struct stream_vtable mem_vtable = {
+ .read = (void *) mem_read,
+ .write = (void *) mem_write,
+ .seek = (void *) mem_seek,
+ .tell = (void *) mem_tell,
+ /* buf_size is not a typo, we just reuse an identical
+ implementation. */
+ .size = (void *) buf_size,
+ .trunc = (void *) mem_truncate,
+ .close = (void *) mem_close,
+ .flush = (void *) mem_flush
+};
+
+static const struct stream_vtable mem4_vtable = {
+ .read = (void *) mem_read4,
+ .write = (void *) mem_write4,
+ .seek = (void *) mem_seek,
+ .tell = (void *) mem_tell,
+ /* buf_size is not a typo, we just reuse an identical
+ implementation. */
+ .size = (void *) buf_size,
+ .trunc = (void *) mem_truncate,
+ .close = (void *) mem_close,
+ .flush = (void *) mem_flush
+};
/*********************************************************************
Public functions -- A reimplementation of this module needs to
{
unix_stream *s;
- s = get_mem (sizeof (unix_stream));
- memset (s, '\0', sizeof (unix_stream));
+ s = xcalloc (1, sizeof (unix_stream));
s->buffer = base;
s->buffer_offset = offset;
- s->logical_offset = 0;
s->active = s->file_length = length;
- s->st.close = (void *) mem_close;
- s->st.seek = (void *) mem_seek;
- s->st.tell = (void *) mem_tell;
- /* buf_size is not a typo, we just reuse an identical
- implementation. */
- s->st.size = (void *) buf_size;
- s->st.trunc = (void *) mem_truncate;
- s->st.read = (void *) mem_read;
- s->st.write = (void *) mem_write;
- s->st.flush = (void *) mem_flush;
+ s->st.vptr = &mem_vtable;
return (stream *) s;
}
{
unix_stream *s;
- s = get_mem (sizeof (unix_stream));
- memset (s, '\0', sizeof (unix_stream));
+ s = xcalloc (1, sizeof (unix_stream));
s->buffer = base;
s->buffer_offset = offset;
- s->logical_offset = 0;
- s->active = s->file_length = length;
+ s->active = s->file_length = length * sizeof (gfc_char4_t);
- s->st.close = (void *) mem_close;
- s->st.seek = (void *) mem_seek;
- s->st.tell = (void *) mem_tell;
- /* buf_size is not a typo, we just reuse an identical
- implementation. */
- s->st.size = (void *) buf_size;
- s->st.trunc = (void *) mem_truncate;
- s->st.read = (void *) mem_read4;
- s->st.write = (void *) mem_write4;
- s->st.flush = (void *) mem_flush;
+ s->st.vptr = &mem4_vtable;
return (stream *) s;
}
struct stat statbuf;
unix_stream *s;
- s = get_mem (sizeof (unix_stream));
- memset (s, '\0', sizeof (unix_stream));
+ s = xcalloc (1, sizeof (unix_stream));
s->fd = fd;
- s->buffer_offset = 0;
- s->physical_offset = 0;
- s->logical_offset = 0;
/* Get the current length of the file. */
}
-/* tempfile()-- Generate a temporary filename for a scratch file and
- * open it. mkstemp() opens the file for reading and writing, but the
- * library mode prevents anything that is not allowed. The descriptor
- * is returned, which is -1 on error. The template is pointed to by
- * opp->file, which is copied into the unit structure
- * and freed later. */
+/* Helper function for tempfile(). Tries to open a temporary file in
+ the directory specified by tempdir. If successful, the file name is
+ stored in fname and the descriptor returned. Returns -1 on
+ failure. */
static int
-tempfile (st_parameter_open *opp)
+tempfile_open (const char *tempdir, char **fname)
{
- const char *tempdir;
- char *template;
- const char *slash = "/";
int fd;
- size_t tempdirlen;
-
-#ifndef HAVE_MKSTEMP
- int count;
- size_t slashlen;
+ const char *slash = "/";
+#if defined(HAVE_UMASK) && defined(HAVE_MKSTEMP)
+ mode_t mode_mask;
#endif
- tempdir = getenv ("GFORTRAN_TMPDIR");
-#ifdef __MINGW32__
- if (tempdir == NULL)
- {
- char buffer[MAX_PATH + 1];
- DWORD ret;
- ret = GetTempPath (MAX_PATH, buffer);
- /* If we are not able to get a temp-directory, we use
- current directory. */
- if (ret > MAX_PATH || !ret)
- buffer[0] = 0;
- else
- buffer[ret] = 0;
- tempdir = strdup (buffer);
- }
-#else
- if (tempdir == NULL)
- tempdir = getenv ("TMP");
- if (tempdir == NULL)
- tempdir = getenv ("TEMP");
- if (tempdir == NULL)
- tempdir = DEFAULT_TEMPDIR;
-#endif
+ if (!tempdir)
+ return -1;
- /* Check for special case that tempdir contains slash
- or backslash at end. */
- tempdirlen = strlen (tempdir);
+ /* Check for the special case that tempdir ends with a slash or
+ backslash. */
+ size_t tempdirlen = strlen (tempdir);
if (*tempdir == 0 || tempdir[tempdirlen - 1] == '/'
#ifdef __MINGW32__
|| tempdir[tempdirlen - 1] == '\\'
slash = "";
// Take care that the template is longer in the mktemp() branch.
- template = get_mem (tempdirlen + 23);
+ char * template = xmalloc (tempdirlen + 23);
#ifdef HAVE_MKSTEMP
snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
tempdir, slash);
+#ifdef HAVE_UMASK
+ /* Temporarily set the umask such that the file has 0600 permissions. */
+ mode_mask = umask (S_IXUSR | S_IRWXG | S_IRWXO);
+#endif
+
fd = mkstemp (template);
+#ifdef HAVE_UMASK
+ (void) umask (mode_mask);
+#endif
+
#else /* HAVE_MKSTEMP */
fd = -1;
- count = 0;
- slashlen = strlen (slash);
+ int count = 0;
+ size_t slashlen = strlen (slash);
do
{
snprintf (template, tempdirlen + 23, "%s%sgfortrantmpaaaXXXXXX",
while (fd == -1 && errno == EEXIST);
#endif /* HAVE_MKSTEMP */
- opp->file = template;
- opp->file_len = strlen (template); /* Don't include trailing nul */
+ *fname = template;
+ return fd;
+}
+
+
+/* tempfile()-- Generate a temporary filename for a scratch file and
+ * open it. mkstemp() opens the file for reading and writing, but the
+ * library mode prevents anything that is not allowed. The descriptor
+ * is returned, which is -1 on error. The template is pointed to by
+ * opp->file, which is copied into the unit structure
+ * and freed later. */
+
+static int
+tempfile (st_parameter_open *opp)
+{
+ const char *tempdir;
+ char *fname;
+ int fd = -1;
+
+ tempdir = secure_getenv ("TMPDIR");
+ fd = tempfile_open (tempdir, &fname);
+#ifdef __MINGW32__
+ if (fd == -1)
+ {
+ char buffer[MAX_PATH + 1];
+ DWORD ret;
+ ret = GetTempPath (MAX_PATH, buffer);
+ /* If we are not able to get a temp-directory, we use
+ current directory. */
+ if (ret > MAX_PATH || !ret)
+ buffer[0] = 0;
+ else
+ buffer[ret] = 0;
+ tempdir = strdup (buffer);
+ fd = tempfile_open (tempdir, &fname);
+ }
+#elif defined(__CYGWIN__)
+ if (fd == -1)
+ {
+ tempdir = secure_getenv ("TMP");
+ fd = tempfile_open (tempdir, &fname);
+ }
+ if (fd == -1)
+ {
+ tempdir = secure_getenv ("TEMP");
+ fd = tempfile_open (tempdir, &fname);
+ }
+#endif
+ if (fd == -1)
+ fd = tempfile_open (P_tmpdir, &fname);
+
+ opp->file = fname;
+ opp->file_len = strlen (fname); /* Don't include trailing nul */
return fd;
}