diff options
Diffstat (limited to 'sysdeps/posix/mkstemp.c')
-rw-r--r-- | sysdeps/posix/mkstemp.c | 42 |
1 files changed, 34 insertions, 8 deletions
diff --git a/sysdeps/posix/mkstemp.c b/sysdeps/posix/mkstemp.c index 3765488f73..fceb59b4be 100644 --- a/sysdeps/posix/mkstemp.c +++ b/sysdeps/posix/mkstemp.c @@ -19,9 +19,11 @@ #include <stdlib.h> #include <string.h> #include <errno.h> +#include <stdint.h> #include <stdio.h> #include <fcntl.h> #include <unistd.h> +#include <sys/time.h> /* Generate a unique temporary file name from TEMPLATE. The last six characters of TEMPLATE must be "XXXXXX"; @@ -33,30 +35,54 @@ mkstemp (template) { static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + static uint32_t value; + struct timeval tv; + char *XXXXXX; size_t len; - size_t i; + int count; len = strlen (template); if (len < 6 || strcmp (&template[len - 6], "XXXXXX")) { __set_errno (EINVAL); - return -1; + return NULL; } - if (sprintf (&template[len - 5], "%.5u", - (unsigned int) getpid () % 100000) != 5) - /* Inconceivable lossage. */ - return -1; + /* This is where the Xs start. */ + XXXXXX = &template[len - 6]; - for (i = 0; i < sizeof (letters); ++i) + /* Get some more or less random data. */ + __gettimeofday (&tv, NULL); + value += tv.tv_usec | getpid (); + + for (count = 0; count < TMP_MAX; ++count) { + struct stat ignored; + uint32_t v = value; int fd; - template[len - 6] = letters[i]; + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; fd = open (template, O_RDWR|O_CREAT|O_EXCL, 0600); if (fd >= 0) + /* The file does not exist. */ return fd; + + /* This is a random value. It is only necessary that the next + TMP_MAX values generated by adding 7777 to VALUE are different + with (module 2^32). */ + value += 7777; } /* We return the null string if we can't find a unique file name. */ |