From e443729d658ee2b9e0f55bbbb90241819bf516a6 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sun, 4 Aug 2013 20:52:25 +0300 Subject: [PATCH] MS-Windows followup to last commit. lib-src/ntlib.h: Include fcntl.h. (mkostemp): Declare prototype. (mktemp): Don't redefine. lib-src/ntlib.c (mkostemp): New function. Fixes: debbugs:15015 --- lib-src/ChangeLog | 8 +++++++ lib-src/ntlib.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++ lib-src/ntlib.h | 4 ++-- 3 files changed, 65 insertions(+), 2 deletions(-) diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 2cfe46f5352..ace62d9d8f7 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,11 @@ +2013-08-04 Eli Zaretskii + + * ntlib.h: Include fcntl.h. + (mkostemp): Declare prototype. + (mktemp): Don't redefine. + + * ntlib.c (mkostemp): New function. (Bug#15015) + 2013-08-04 Paul Eggert Fix some minor races in hosts lacking mkostemp (Bug#15015). diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index 41b4e3a0cbc..0d0642d1bf2 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -422,3 +422,58 @@ lstat (const char * path, struct stat * buf) { return stat (path, buf); } + +/* 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 = 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; +} diff --git a/lib-src/ntlib.h b/lib-src/ntlib.h index 3e48d2997e0..c30958365ca 100644 --- a/lib-src/ntlib.h +++ b/lib-src/ntlib.h @@ -22,6 +22,7 @@ along with GNU Emacs. If not, see . */ /* Include these headers now so we don't have to worry about include order dependencies in common source files. */ #include +#include #include #include @@ -41,6 +42,7 @@ int setuid (unsigned uid); int setregid (unsigned rgid, unsigned gid); char * getpass (const char * prompt); int fchown (int fd, unsigned uid, unsigned gid); +int mkostemp (char * template, int flags); /* redirect or undo interceptions created by config.h */ #undef access @@ -61,8 +63,6 @@ int fchown (int fd, unsigned uid, unsigned gid); #undef fopen #undef mkdir #define mkdir _mkdir -#undef mktemp -#define mktemp _mktemp #undef open #define open _open #undef pipe -- 2.39.2