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,56 +3414,6 @@ 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) -{ - char * p; - int i; - unsigned uid = GetCurrentThreadId (); - static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#"; - - if (template == NULL) - return NULL; - p = template + strlen (template); - i = 5; - /* replace up to the last 5 X's with uid in decimal */ - while (--p >= template && p[0] == 'X' && --i >= 0) - { - p[0] = '0' + uid % 10; - uid /= 10; - } - - if (i < 0 && p[0] == 'X') - { - i = 0; - do - { - int save_errno = errno; - p[0] = first_char[i]; - if (faccessat (AT_FDCWD, template, F_OK, AT_EACCESS) < 0) - { - errno = save_errno; - return template; - } - } - 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) { @@ -3481,6 +3431,61 @@ sys_open (const char * path, int oflag, int 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, fd = -1; + unsigned uid = GetCurrentThreadId (); + int save_errno = errno; + static char first_char[] = "abcdefghijklmnopqrstuvwyz0123456789!%-_@#"; + + errno = EINVAL; + if (template == NULL) + return -1; + + p = template + strlen (template); + i = 5; + /* replace up to the last 5 X's with uid in decimal */ + while (--p >= template && p[0] == 'X' && --i >= 0) + { + p[0] = '0' + uid % 10; + uid /= 10; + } + + if (i < 0 && p[0] == 'X') + { + i = 0; + do + { + p[0] = first_char[i]; + if ((fd = sys_open (template, + flags | _O_CREAT | _O_EXCL | _O_RDWR, + S_IRUSR | S_IWUSR)) >= 0 + || errno != EEXIST) + { + 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. */ + return -1; +} + int fchmod (int fd, mode_t mode) {