X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/19c443d277831d6d128d2e6a4e300258b8666bea..6a92d676c45b440fe47f0c74db028883c14bc999:/lib-src/ntlib.c diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index 41b4e3a0cb..23d7ba77b8 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -1,6 +1,6 @@ /* Utility and Unix shadow routines for GNU Emacs support programs on NT. -Copyright (C) 1994, 2001-2013 Free Software Foundation, Inc. +Copyright (C) 1994, 2001-2014 Free Software Foundation, Inc. Author: Geoff Voelker (voelker@cs.washington.edu) Created: 10-8-94 @@ -422,3 +422,72 @@ lstat (const char * path, struct stat * buf) { return stat (path, buf); } + +/* Implementation of mkostemp for MS-Windows, to avoid race conditions + when using mktemp. Copied from w32.c. + + This is used only in update-game-score.c. It is overkill for that + use case, since update-game-score renames the temporary file into + the game score file, which isn't atomic on MS-Windows anyway, when + the game score already existed before running the program, which it + almost always does. But using a simpler implementation just to + make a point is uneconomical... */ + +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; +} + +/* On Windows, you cannot rename into an existing file. */ +int +sys_rename (const char *from, const char *to) +{ + int retval = rename (from, to); + + if (retval < 0 && errno == EEXIST) + { + if (unlink (to) == 0) + retval = rename (from, to); + } + return retval; +}