From: Eli Zaretskii Date: Sun, 4 Aug 2013 15:32:12 +0000 (+0300) Subject: Implement mkostemp for MS-Windows. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~1686^2~436 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=63f5c6c20d393e05d517c5c02155d03694c41291;p=emacs.git Implement mkostemp for MS-Windows. nt/mingw-cfg.site (ac_cv_func_mkostemp): New var with value of "yes". nt/inc/ms-w32.h (mkostemp): Declare prototype. nt/config.nt (HAVE_MKOSTEMP): Define to 1. src/w32.c (mkostemp): New function. (mktemp): Remove, no longer used. Most of the code reused in mkostemp. Fixes: debbugs:15015 --- diff --git a/nt/ChangeLog b/nt/ChangeLog index c0598dd5630..23c0c74b6f1 100644 --- a/nt/ChangeLog +++ b/nt/ChangeLog @@ -1,3 +1,12 @@ +2013-08-04 Eli Zaretskii + + * mingw-cfg.site (ac_cv_func_mkostemp): New var with value of + "yes". + + * inc/ms-w32.h (mkostemp): Declare prototype. + + * config.nt (HAVE_MKOSTEMP): Define to 1. (Bug#15015) + 2013-07-07 Eli Zaretskii * inc/sys/socket.h (F_SETFD, O_CLOEXEC, F_DUPFD_CLOEXEC) diff --git a/nt/config.nt b/nt/config.nt index 95b56f2dc64..3ba60a85752 100644 --- a/nt/config.nt +++ b/nt/config.nt @@ -796,6 +796,9 @@ along with GNU Emacs. If not, see . */ systems that support xmenu.c. */ #undef HAVE_MENUS +/* Define to 1 if you have the `mkostemp' function. */ +#define HAVE_MKOSTEMP 1 + /* Define to 1 if you have the `mkstemp' function. */ #undef HAVE_MKSTEMP diff --git a/nt/inc/ms-w32.h b/nt/inc/ms-w32.h index 3e50c78f145..f01f254d81c 100644 --- a/nt/inc/ms-w32.h +++ b/nt/inc/ms-w32.h @@ -450,6 +450,8 @@ extern int getpagesize (void); extern void * memrchr (void const *, int, size_t); +extern int mkostemp (char *, int); + #if defined (__MINGW32__) diff --git a/nt/mingw-cfg.site b/nt/mingw-cfg.site index cf55fe04ed8..325bba29ae5 100644 --- a/nt/mingw-cfg.site +++ b/nt/mingw-cfg.site @@ -60,6 +60,7 @@ ac_cv_func_getpeername=yes # Implemented as sys_socket in w32.c ac_cv_func_socket=yes # Implemented in w32.c +ac_cv_func_mkostemp=yes ac_cv_func_readlink=yes ac_cv_func_symlink=yes # Avoid run-time tests of readlink and symlink, which will fail diff --git a/src/ChangeLog b/src/ChangeLog index 8a9de96358d..0fe6b4e6ce3 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,9 @@ +2013-08-04 Eli Zaretskii + + * w32.c (mkostemp): New function. + (mktemp): Remove, no longer used. Most of the code reused in + mkostemp. (Bug#15015) + 2013-08-04 Dmitry Antipov * dispnew.c (glyph_matrix_count, glyph_pool_count): diff --git a/src/w32.c b/src/w32.c index fb2d7c75972..af42c6f39c2 100644 --- a/src/w32.c +++ b/src/w32.c @@ -3414,25 +3414,46 @@ sys_mkdir (const char * path) return _mkdir (map_w32_filename (path, NULL)); } -/* Because of long name mapping issues, we need to implement this - ourselves. Also, MSVC's _mktemp returns NULL when it can't generate - a unique name, instead of setting the input template to an empty - string. - - Standard algorithm seems to be use pid or tid with a letter on the - front (in place of the 6 X's) and cycle through the letters to find a - unique name. We extend that to allow any reasonable character as the - first of the 6 X's. */ -char * -sys_mktemp (char * template) +int +sys_open (const char * path, int oflag, int mode) +{ + const char* mpath = map_w32_filename (path, NULL); + int res = -1; + + /* If possible, try to open file without _O_CREAT, to be able to + write to existing hidden and system files. Force all file + handles to be non-inheritable. */ + if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL)) + res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); + if (res < 0) + res = _open (mpath, oflag | _O_NOINHERIT, mode); + + return res; +} + +/* Implementation of mkostemp for MS-Windows, to avoid race conditions + when using mktemp. + + Standard algorithm for generating a temporary file name seems to be + use pid or tid with a letter on the front (in place of the 6 X's) + and cycle through the letters to find a unique name. We extend + that to allow any reasonable character as the first of the 6 X's, + so that the number of simultaneously used temporary files will be + greater. */ + +int +mkostemp (char * template, int flags) { char * p; - int i; + int i, fd = -1; unsigned uid = GetCurrentThreadId (); + int save_errno = errno; static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#"; + errno = EINVAL; if (template == NULL) - return NULL; + return -1; + p = template + strlen (template); i = 5; /* replace up to the last 5 X's with uid in decimal */ @@ -3447,38 +3468,22 @@ sys_mktemp (char * template) i = 0; do { - int save_errno = errno; p[0] = first_char[i]; - if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0) + if ((fd = sys_open (template, + flags | _O_CREAT | _O_EXCL | _O_RDWR, + S_IRUSR | S_IWUSR)) >= 0 + || errno != EEXIST) { - errno = save_errno; - return template; + if (fd >= 0) + errno = save_errno; + return fd; } } while (++i < sizeof (first_char)); } - /* Template is badly formed or else we can't generate a unique name, - so return empty string */ - template[0] = 0; - return template; -} - -int -sys_open (const char * path, int oflag, int mode) -{ - const char* mpath = map_w32_filename (path, NULL); - int res = -1; - - /* If possible, try to open file without _O_CREAT, to be able to - write to existing hidden and system files. Force all file - handles to be non-inheritable. */ - if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL)) - res = _open (mpath, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode); - if (res < 0) - res = _open (mpath, oflag | _O_NOINHERIT, mode); - - return res; + /* Template is badly formed or else we can't generate a unique name. */ + return -1; } int