Fix handling of temporary files.
authorJanne Blomqvist <jb@gcc.gnu.org>
Sat, 5 May 2012 06:30:51 +0000 (09:30 +0300)
committerJanne Blomqvist <jb@gcc.gnu.org>
Sat, 5 May 2012 06:30:51 +0000 (09:30 +0300)
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.

From-SVN: r187190

gcc/fortran/ChangeLog
gcc/fortran/gfortran.texi
libgfortran/ChangeLog
libgfortran/config.h.in
libgfortran/configure
libgfortran/configure.ac
libgfortran/io/unix.c
libgfortran/libgfortran.h
libgfortran/runtime/environ.c
libgfortran/runtime/main.c

index bb4c22d..d1cb429 100644 (file)
@@ -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
index b1790c6..96662c4 100644 (file)
@@ -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
 
index ec66284..46f2cf4 100644 (file)
@@ -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
index 30a7e12..b75fa96 100644 (file)
 /* 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
 
 /* 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
index b80f545..e2db9ea 100755 (executable)
@@ -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; }
index d70924e..41bef72 100644 (file)
@@ -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])
index 185936f..c81163f 100644 (file)
@@ -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;
 }
index e7f5b71..051e2e8 100644 (file)
@@ -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,
index 7782cee..bcb91f4 100644 (file)
@@ -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,
index 79659e5..72c32fc 100644 (file)
@@ -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);