changeset 8162:46995f2e94ca

New module 'tmpfile'.
author Bruno Haible <bruno@clisp.org>
date Sat, 17 Feb 2007 15:04:50 +0000
parents f7359fba603e
children e717b8d5a144
files ChangeLog MODULES.html.sh lib/tmpfile.c m4/tmpfile.m4 modules/tmpfile
diffstat 5 files changed, 207 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-02-17  Ben Pfaff  <blp@cs.stanford.edu>
+            Bruno Haible  <bruno@clisp.org>
+
+	* modules/tmpfile: New file.
+	* lib/tmpfile.c: New file.
+	* m4/tmpfile.m4: New file.
+	* MODULES.html.sh (func_all_modules): New section "Input/output".
+
 2007-02-15  Bruno Haible  <bruno@clisp.org>
 
 	* lib/clean-temp.c [WIN32 && !CYGWIN]: Include <windows.h>.
--- a/MODULES.html.sh
+++ b/MODULES.html.sh
@@ -1524,6 +1524,16 @@
   func_module verify
   func_end_table
 
+  element="Input/output <stdio.h>"
+  element=`printf "%s" "$element" | sed -e "$sed_lt" -e "$sed_gt"`
+  func_section_wrap ansic_enh_stdio
+  func_wrap H3
+  func_echo "$element"
+
+  func_begin_table
+  func_module tmpfile
+  func_end_table
+
   element="Memory management functions <stdlib.h>"
   element=`printf "%s" "$element" | sed -e "$sed_lt" -e "$sed_gt"`
   func_section_wrap ansic_enh_stdlib_memory
new file mode 100644
--- /dev/null
+++ b/lib/tmpfile.c
@@ -0,0 +1,125 @@
+/* Create a temporary file.
+   Copyright (C) 2007 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
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software Foundation,
+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
+
+/* Written by Ben Pfaff. */
+
+#include <config.h>
+
+/* Specification.  */
+#include <stdio.h>
+
+/* This replacement is used only on native Windows platforms.  */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <io.h>
+
+#define WIN32_LEAN_AND_MEAN  /* avoid including junk */
+#include <windows.h>
+
+#include "pathmax.h"
+#include "tempname.h"
+#include "tmpdir.h"
+
+/* On Windows, opening a file with _O_TEMPORARY has the effect of passing
+   the FILE_FLAG_DELETE_ON_CLOSE flag to CreateFile(), which has the effect
+   of deleting the file when it is closed - even when the program crashes.
+   But (according to the Cygwin sources) it works only on Windows NT or newer.
+   So we cache the info whether we are running on Windows NT or newer.  */
+
+static bool
+supports_delete_on_close ()
+{
+  static int known; /* 1 = yes, -1 = no, 0 = unknown */
+  if (!known)
+    {
+      OSVERSIONINFO v;
+
+      if (GetVersionEx (&v))
+	known = (v.dwPlatformId == VER_PLATFORM_WIN32_NT ? 1 : -1);
+      else
+	known = -1;
+    }
+  return (known > 0);
+}
+
+FILE *
+tmpfile (void)
+{
+  char dir[PATH_MAX];
+  DWORD retval;
+
+  /* Find Windows temporary file directory.
+     We provide this as the directory argument to path_search because Windows
+     defines P_tmpdir to "\\" and will therefore try to put all temporary files
+     in the root directory (unless $TMPDIR is set). */
+  retval = GetTempPath (PATH_MAX, dir);
+  if (retval > 0 && retval < PATH_MAX)
+    {
+      char xtemplate[PATH_MAX];
+
+      if (path_search (xtemplate, PATH_MAX, dir, NULL, true) >= 0)
+	{
+	  size_t len = strlen (xtemplate);
+	  int o_temporary = (supports_delete_on_close () ? _O_TEMPORARY : 0);
+	  int fd;
+
+	  do
+	    {
+	      memcpy (&xtemplate[len - 6], "XXXXXX", 6);
+	      if (gen_tempname (xtemplate, GT_NOCREATE) < 0)
+		{
+		  fd = -1;
+		  break;
+		}
+
+	      fd = _open (xtemplate,
+			  _O_CREAT | _O_EXCL | o_temporary
+			  | _O_RDWR | _O_BINARY,
+			  _S_IREAD | _S_IWRITE);
+	    }
+	  while (fd < 0 && errno == EEXIST);
+
+	  if (fd >= 0)
+	    {
+	      FILE *fp = _fdopen (fd, "w+b");
+
+	      if (fp != NULL)
+		return fp;
+	      else
+		{
+		  int saved_errno = errno;
+		  _close (fd);
+		  errno = saved_errno;
+		}
+	    }
+	}
+    }
+  else
+    {
+      if (retval > 0)
+	errno = ENAMETOOLONG;
+      else
+	/* Ideally this should translate GetLastError () to an errno value.  */
+	errno = ENOENT;
+    }
+
+  return NULL;
+}
new file mode 100644
--- /dev/null
+++ b/m4/tmpfile.m4
@@ -0,0 +1,39 @@
+# Check whether to use a replacement tmpfile() function.
+
+# Copyright (C) 2007 Free Software Foundation, Inc.
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# Written by Ben Pfaff.
+
+# The native Windows tmpfile function always tries to put the temporary
+# file in the root directory.  (This behaviour is even documented in
+# Microsoft's documentation!)  This often fails for ordinary users who
+# don't have the permissions to write in the root directory.
+#
+# We can't test for tmpfile even at runtime, since our test program
+# might be running with privileges that allow it to write to the root
+# directory, even though tmpfile wouldn't work in general.  Instead,
+# just test for a Windows platform (excluding Cygwin).
+
+AC_DEFUN([gl_TMPFILE], [
+  AC_CACHE_CHECK([whether tmpfile should be overridden],
+    [gl_cv_func_tmpfile_unusable],
+    [AC_EGREP_CPP([choke me], [
+#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
+choke me
+#endif
+       ],
+       [gl_cv_func_tmpfile_unusable=yes],
+       [gl_cv_func_tmpfile_unusable=no])])
+  if test $gl_cv_func_tmpfile_unusable = yes; then
+    AC_LIBOBJ(tmpfile)
+    AC_DEFINE(tmpfile, rpl_tmpfile,
+      [Define to rpl_tmpfile if the replacement function should be used.])
+    gl_PREREQ_TMPFILE
+  fi
+])
+
+# Prerequisites of lib/tmpfile.c.
+AC_DEFUN([gl_PREREQ_TMPFILE], [:])
new file mode 100644
--- /dev/null
+++ b/modules/tmpfile
@@ -0,0 +1,25 @@
+Description:
+tmpfile() function: create a temporary file.
+
+Files:
+lib/tmpfile.c
+m4/tmpfile.m4
+
+Depends-on:
+pathmax
+tempname
+tmpdir
+
+configure.ac:
+gl_TMPFILE
+
+Makefile.am:
+
+Include:
+#include <stdio.h>
+
+License:
+GPL
+
+Maintainer:
+Ben Pfaff