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 <[EMAIL PROTECTED]> Bruno Haible <[EMAIL PROTECTED]> * 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