summaryrefslogtreecommitdiff
path: root/lib-src/ntlib.c
diff options
context:
space:
mode:
authorEli Zaretskii <eliz@gnu.org>2013-08-04 20:52:25 +0300
committerEli Zaretskii <eliz@gnu.org>2013-08-04 20:52:25 +0300
commite443729d658ee2b9e0f55bbbb90241819bf516a6 (patch)
tree99b2252965cb7586270cbe13d16726df82f25a8e /lib-src/ntlib.c
parente0fdb6943066032db294720915c3bd644bf2bcd1 (diff)
downloademacs-e443729d658ee2b9e0f55bbbb90241819bf516a6.tar.gz
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
Diffstat (limited to 'lib-src/ntlib.c')
-rw-r--r--lib-src/ntlib.c55
1 files changed, 55 insertions, 0 deletions
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;
+}