[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: fix inadequate Windows implementation of tmpfile
From: |
Bruno Haible |
Subject: |
Re: fix inadequate Windows implementation of tmpfile |
Date: |
Sat, 17 Feb 2007 16:13:08 +0100 |
User-agent: |
KMail/1.5.4 |
Paul Eggert wrote:
> I think gnulib is for porting GNU applications, and if GNU
> applications assume glibc behavior for a function then it's OK to
> replace a vendor's function that behaves differrently.
OK. So I'm adding Ben's module, with the following modifications:
* tmpfile.c:
- Don't use _O_TEMPORARY on Windows 95/98/ME.
- Provide an 'errno' in the case of the first 'goto done'.
- Restructure the code so as to avoid 'goto'.
- Allocate 'dir' and 'xtemplate' on the stack, since their size is
bounded by PATH_MAX (<= 4096 or so).
- Change range check to allow paths of length PATH_MAX - 1.
* tmpfile.m4:
- Change the configure message. (If the message says "for tmpfile that only
uses the root directory", it should also test for this behaviour.)
- Use AC_EGREP_CPP instead of AC_COMPILE_IFELSE, since it's faster.
- Actually invoke gl_PREREQ_TMPFILE.
* modules/tmpfile:
- Don't mention "Windows" in the module description. The module description
should be abstract enough that it doesn't need to change if problems
appear on other platforms.
- Mention <stdio.h> as header file to be included.
* MODULES.html.sh: Put new section about <stdio.h> before <stdlib.h>, not
between <stdlib.h> and <stdlib.h>.
Please proofread again. Did I miss something?
2007-02-17 Ben Pfaff <address@hidden>
Bruno Haible <address@hidden>
* modules/tmpfile: New file.
* lib/tmpfile.c: New file.
* m4/tmpfile.m4: New file.
* MODULES.html.sh (func_all_modules): New section "Input/output".
================================ modules/tmpfile =============================
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
================================= lib/tmpfile.c ==============================
/* 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;
}
================================= m4/tmpfile.m4 ==============================
# 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], [:])
==============================================================================
*** MODULES.html.sh 15 Feb 2007 03:07:04 -0000 1.194
--- MODULES.html.sh 17 Feb 2007 15:03:27 -0000
***************
*** 1524,1529 ****
--- 1524,1539 ----
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
- fix inadequate Windows implementation of tmpfile, Ben Pfaff, 2007/02/15
- Re: fix inadequate Windows implementation of tmpfile, Ben Pfaff, 2007/02/15
- Re: fix inadequate Windows implementation of tmpfile, Bruno Haible, 2007/02/15
- Re: fix inadequate Windows implementation of tmpfile, Ben Pfaff, 2007/02/15
- Re: fix inadequate Windows implementation of tmpfile, Bruno Haible, 2007/02/15
- Re: fix inadequate Windows implementation of tmpfile, Bruno Haible, 2007/02/15
- Re: fix inadequate Windows implementation of tmpfile, Paul Eggert, 2007/02/16
- Re: fix inadequate Windows implementation of tmpfile,
Bruno Haible <=
- Re: fix inadequate Windows implementation of tmpfile, Ben Pfaff, 2007/02/17
- Re: fix inadequate Windows implementation of tmpfile, Bruno Haible, 2007/02/20
- Re: fix inadequate Windows implementation of tmpfile, Ben Pfaff, 2007/02/20