summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjb <jb@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-05 06:30:51 +0000
committerjb <jb@138bc75d-0d04-0410-961f-82ee72b054a4>2012-05-05 06:30:51 +0000
commita291e3b6538a0697986d1a7d22aa220829998bab (patch)
treeac63807666eaf2ebc05379c848806981ba536332
parente3168f5bde2d4ceb1543c5ea0c779ee66b5f9a02 (diff)
downloadgcc-a291e3b6538a0697986d1a7d22aa220829998bab.tar.gz
Fix handling of temporary files.
2012-05-05 Janne Blomqvist <jb@gcc.gnu.org> * gfortran.texi (GFORTRAN_TMPDIR): Rename to TMPDIR, explain algorithm for choosing temp directory. 2012-05-05 Janne Blomqvist <jb@gcc.gnu.org> * config.h.in: Regenerated. * configure: Regenerated. * configure.ac: Add checks for getegid and __secure_getenv. * io/unix.c (P_tmpdir): Fallback definition for macro. (tempfile_open): New function. (tempfile): Use secure_getenv, call tempfile_open to try each directory in turn. * libgfortran.h (DEFAULT_TMPDIR): Remove macro. (secure_getenv): New macro/prototype. * runtime/environ.c (secure_getenv): New function. (variable_table): Rename GFORTRAN_TMPDIR to TMPDIR. * runtime/main.c (find_addr2line): Use secure_getenv. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@187190 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/fortran/ChangeLog5
-rw-r--r--gcc/fortran/gfortran.texi31
-rw-r--r--libgfortran/ChangeLog15
-rw-r--r--libgfortran/config.h.in6
-rwxr-xr-xlibgfortran/configure10
-rw-r--r--libgfortran/configure.ac2
-rw-r--r--libgfortran/io/unix.c125
-rw-r--r--libgfortran/libgfortran.h16
-rw-r--r--libgfortran/runtime/environ.c18
-rw-r--r--libgfortran/runtime/main.c2
10 files changed, 163 insertions, 67 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index bb4c22d49bc..d1cb4294be6 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,8 @@
+2012-05-05 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * gfortran.texi (GFORTRAN_TMPDIR): Rename to TMPDIR, explain
+ algorithm for choosing temp directory.
+
2012-05-04 Tobias Burnus <burnus@net-b.de>
PR fortran/53175
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index b1790c6ad5f..96662c49423 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -576,10 +576,10 @@ environment variables.
Malformed environment variables are silently ignored.
@menu
+* TMPDIR:: Directory for scratch files
* GFORTRAN_STDIN_UNIT:: Unit number for standard input
* GFORTRAN_STDOUT_UNIT:: Unit number for standard output
* GFORTRAN_STDERR_UNIT:: Unit number for standard error
-* GFORTRAN_TMPDIR:: Directory for scratch files
* GFORTRAN_UNBUFFERED_ALL:: Do not buffer I/O for all units.
* GFORTRAN_UNBUFFERED_PRECONNECTED:: Do not buffer I/O for preconnected units.
* GFORTRAN_SHOW_LOCUS:: Show location for runtime errors
@@ -590,6 +590,27 @@ Malformed environment variables are silently ignored.
* GFORTRAN_ERROR_BACKTRACE:: Show backtrace on run-time errors
@end menu
+@node TMPDIR
+@section @env{TMPDIR}---Directory for scratch files
+
+When opening a file with @code{STATUS='SCRATCH'}, GNU Fortran tries to
+create the file in one of the potential directories by testing each
+directory in the order below.
+
+@enumerate
+@item
+The environment variable @env{TMPDIR}, if it exists.
+
+@item
+On the MinGW target, the directory returned by the @code{GetTempPath}
+function. Alternatively, on the Cygwin target, the @env{TMP} and
+@env{TEMP} environment variables, if they exist, in that order.
+
+@item
+The @code{P_tmpdir} macro if it is defined, otherwise the directory
+@file{/tmp}.
+@end enumerate
+
@node GFORTRAN_STDIN_UNIT
@section @env{GFORTRAN_STDIN_UNIT}---Unit number for standard input
@@ -611,14 +632,6 @@ This environment variable can be used to select the unit number
preconnected to standard error. This must be a positive integer.
The default value is 0.
-@node GFORTRAN_TMPDIR
-@section @env{GFORTRAN_TMPDIR}---Directory for scratch files
-
-This environment variable controls where scratch files are
-created. If this environment variable is missing,
-GNU Fortran searches for the environment variable @env{TMP}, then @env{TEMP}.
-If these are missing, the default is @file{/tmp}.
-
@node GFORTRAN_UNBUFFERED_ALL
@section @env{GFORTRAN_UNBUFFERED_ALL}---Do not buffer I/O on all units
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index ec662841ee2..46f2cf41853 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,3 +1,18 @@
+2012-05-05 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * config.h.in: Regenerated.
+ * configure: Regenerated.
+ * configure.ac: Add checks for getegid and __secure_getenv.
+ * io/unix.c (P_tmpdir): Fallback definition for macro.
+ (tempfile_open): New function.
+ (tempfile): Use secure_getenv, call tempfile_open to try each
+ directory in turn.
+ * libgfortran.h (DEFAULT_TMPDIR): Remove macro.
+ (secure_getenv): New macro/prototype.
+ * runtime/environ.c (secure_getenv): New function.
+ (variable_table): Rename GFORTRAN_TMPDIR to TMPDIR.
+ * runtime/main.c (find_addr2line): Use secure_getenv.
+
2012-04-22 Tobias Burnus <burnus@net-b.de>
PR fortran/53051
diff --git a/libgfortran/config.h.in b/libgfortran/config.h.in
index 30a7e121325..b75fa968023 100644
--- a/libgfortran/config.h.in
+++ b/libgfortran/config.h.in
@@ -426,6 +426,9 @@
/* Define to 1 if you have the `getcwd' function. */
#undef HAVE_GETCWD
+/* Define to 1 if you have the `getegid' function. */
+#undef HAVE_GETEGID
+
/* Define to 1 if you have the `geteuid' function. */
#undef HAVE_GETEUID
@@ -834,6 +837,9 @@
/* Define to 1 if you have the `ynl' function. */
#undef HAVE_YNL
+/* Define to 1 if you have the `__secure_getenv' function. */
+#undef HAVE___SECURE_GETENV
+
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
diff --git a/libgfortran/configure b/libgfortran/configure
index b80f5453d00..e2db9ea2537 100755
--- a/libgfortran/configure
+++ b/libgfortran/configure
@@ -2592,6 +2592,8 @@ as_fn_append ac_func_list " getppid"
as_fn_append ac_func_list " getuid"
as_fn_append ac_func_list " geteuid"
as_fn_append ac_func_list " umask"
+as_fn_append ac_func_list " getegid"
+as_fn_append ac_func_list " __secure_getenv"
as_fn_append ac_header_list " math.h"
# Check that the precious variables saved in the cache have kept the same
# value.
@@ -12319,7 +12321,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12322 "configure"
+#line 12324 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -12425,7 +12427,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 12428 "configure"
+#line 12430 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -16536,6 +16538,10 @@ done
+
+
+
+
# Check for C99 (and other IEEE) math functions
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sin in -lm" >&5
$as_echo_n "checking for sin in -lm... " >&6; }
diff --git a/libgfortran/configure.ac b/libgfortran/configure.ac
index d70924e8fcf..41bef720234 100644
--- a/libgfortran/configure.ac
+++ b/libgfortran/configure.ac
@@ -266,7 +266,7 @@ ftruncate chsize chdir getlogin gethostname kill link symlink sleep ttyname \
alarm access fork execl wait setmode execve pipe dup2 close \
strcasestr getrlimit gettimeofday stat fstat lstat getpwuid vsnprintf dup \
getcwd localtime_r gmtime_r strerror_r getpwuid_r ttyname_r clock_gettime \
-readlink getgid getpid getppid getuid geteuid umask)
+readlink getgid getpid getppid getuid geteuid umask getegid __secure_getenv)
# Check for C99 (and other IEEE) math functions
GCC_CHECK_MATH_FUNC([acosf])
diff --git a/libgfortran/io/unix.c b/libgfortran/io/unix.c
index 185936f109d..c81163f2563 100644
--- a/libgfortran/io/unix.c
+++ b/libgfortran/io/unix.c
@@ -176,6 +176,17 @@ fallback_access (const char *path, int mode)
#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;
@@ -1026,54 +1037,23 @@ unpack_filename (char *cstring, const char *fstring, int len)
}
-/* 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;
-#endif
+ const char *slash = "/";
- 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] == '\\'
@@ -1082,7 +1062,7 @@ tempfile (st_parameter_open *opp)
slash = "";
// Take care that the template is longer in the mktemp() branch.
- template = xmalloc (tempdirlen + 23);
+ char * template = xmalloc (tempdirlen + 23);
#ifdef HAVE_MKSTEMP
snprintf (template, tempdirlen + 23, "%s%sgfortrantmpXXXXXX",
@@ -1092,8 +1072,8 @@ tempfile (st_parameter_open *opp)
#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",
@@ -1127,8 +1107,59 @@ tempfile (st_parameter_open *opp)
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;
}
diff --git a/libgfortran/libgfortran.h b/libgfortran/libgfortran.h
index e7f5b711a51..051e2e85a1e 100644
--- a/libgfortran/libgfortran.h
+++ b/libgfortran/libgfortran.h
@@ -584,10 +584,6 @@ iexport_data_proto(filename);
#define gfc_alloca(x) __builtin_alloca(x)
-/* Directory for creating temporary files. Only used when none of the
- following environment variables exist: GFORTRAN_TMPDIR, TMP and TEMP. */
-#define DEFAULT_TEMPDIR "/tmp"
-
/* The default value of record length for preconnected units is defined
here. This value can be overriden by an environment variable.
Default value is 1 Gb. */
@@ -776,6 +772,18 @@ internal_proto(show_variables);
unit_convert get_unformatted_convert (int);
internal_proto(get_unformatted_convert);
+/* Secure getenv() which returns NULL if running as SUID/SGID. */
+#ifdef HAVE___SECURE_GETENV
+#define secure_getenv __secure_getenv
+#elif defined(HAVE_GETUID) && defined(HAVE_GETEUID) \
+ && defined(HAVE_GETGID) && defined(HAVE_GETEGID)
+#define FALLBACK_SECURE_GETENV
+extern char *secure_getenv (const char *);
+internal_proto(secure_getenv);
+#else
+#define secure_getenv getenv
+#endif
+
/* string.c */
extern int find_option (st_parameter_common *, const char *, gfc_charlen_type,
diff --git a/libgfortran/runtime/environ.c b/libgfortran/runtime/environ.c
index 7782cee044c..bcb91f44613 100644
--- a/libgfortran/runtime/environ.c
+++ b/libgfortran/runtime/environ.c
@@ -56,6 +56,19 @@ variable;
static void init_unformatted (variable *);
+
+#ifdef FALLBACK_SECURE_GETENV
+char *
+secure_getenv (const char *name)
+{
+ if ((getuid () == geteuid ()) && (getgid () == getegid ()))
+ return getenv (name);
+ else
+ return NULL;
+}
+#endif
+
+
/* print_spaces()-- Print a particular number of spaces. */
static void
@@ -285,9 +298,8 @@ static variable variable_table[] = {
"Unit number that will be preconnected to standard error\n"
"(No preconnection if negative)", 0},
- {"GFORTRAN_TMPDIR", 0, NULL, init_string, show_string,
- "Directory for scratch files. Overrides the TMP environment variable\n"
- "If TMP is not set " DEFAULT_TEMPDIR " is used.", 0},
+ {"TMPDIR", 0, NULL, init_string, show_string,
+ "Directory for scratch files.", 0},
{"GFORTRAN_UNBUFFERED_ALL", 0, &options.all_unbuffered, init_boolean,
show_boolean,
diff --git a/libgfortran/runtime/main.c b/libgfortran/runtime/main.c
index 79659e52bcd..72c32fc2e1b 100644
--- a/libgfortran/runtime/main.c
+++ b/libgfortran/runtime/main.c
@@ -163,7 +163,7 @@ find_addr2line (void)
{
#ifdef HAVE_ACCESS
#define A2L_LEN 10
- char *path = getenv ("PATH");
+ char *path = secure_getenv ("PATH");
if (!path)
return;
size_t n = strlen (path);