mkdtemp.cpp
author insilmaril
Fri, 05 Mar 2010 20:16:46 +0000
branchrelease-1-12-maintained
changeset 80 5c5b4464b24f
permissions -rwxr-xr-x
Some changes by Tagg for Win version
     1 #include "mkdtemp.h"
     2 #include <stdint.h>
     3 #include <string.h>
     4 #include <errno.h>
     5 #include <io.h>
     6 
     7 char *
     8 mkdtemp(char *tmpl)
     9 {
    10     // Implementation based on GLIBC implementation.
    11 
    12     static const char letters[] =
    13         "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    14 
    15     static uint64_t value;
    16 
    17     const unsigned int ATTEMPTS_MIN = (62 * 62 * 62);
    18 
    19     int save_errno = errno;
    20 
    21     size_t len = strlen(tmpl);
    22     if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
    23     {
    24         errno = EINVAL;
    25         return NULL;
    26     }
    27 
    28     char *XXXXXX = &tmpl[len - 6];
    29 
    30     uint64_t random_time_bits = time(NULL);
    31 
    32     value += (random_time_bits ^ getpid());
    33 
    34     unsigned int count;
    35     for (count = 0; count < ATTEMPTS_MIN; value += 7777, ++count)
    36     {
    37         uint64_t v = value;
    38 
    39         XXXXXX[0] = letters[v % 62];
    40         v /= 62;
    41         XXXXXX[1] = letters[v % 62];
    42         v /= 62;
    43         XXXXXX[2] = letters[v % 62];
    44         v /= 62;
    45         XXXXXX[3] = letters[v % 62];
    46         v /= 62;
    47         XXXXXX[4] = letters[v % 62];
    48         v /= 62;
    49         XXXXXX[5] = letters[v % 62];
    50 
    51 		if (mkdir(tmpl) == 0)
    52         {
    53             errno = save_errno;
    54 			return tmpl;
    55         }
    56 
    57 		if (errno != EEXIST)
    58 			return NULL;
    59     }
    60 
    61     errno = EEXIST;
    62     return NULL;
    63 }