--- /dev/null
+/* 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;
+}
--- /dev/null
+# 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], [:])