mkdtemp.cpp
branchrelease-1-12-maintained
changeset 80 5c5b4464b24f
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/mkdtemp.cpp	Fri Mar 05 20:16:46 2010 +0000
     1.3 @@ -0,0 +1,63 @@
     1.4 +#include "mkdtemp.h"
     1.5 +#include <stdint.h>
     1.6 +#include <string.h>
     1.7 +#include <errno.h>
     1.8 +#include <io.h>
     1.9 +
    1.10 +char *
    1.11 +mkdtemp(char *tmpl)
    1.12 +{
    1.13 +    // Implementation based on GLIBC implementation.
    1.14 +
    1.15 +    static const char letters[] =
    1.16 +        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    1.17 +
    1.18 +    static uint64_t value;
    1.19 +
    1.20 +    const unsigned int ATTEMPTS_MIN = (62 * 62 * 62);
    1.21 +
    1.22 +    int save_errno = errno;
    1.23 +
    1.24 +    size_t len = strlen(tmpl);
    1.25 +    if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
    1.26 +    {
    1.27 +        errno = EINVAL;
    1.28 +        return NULL;
    1.29 +    }
    1.30 +
    1.31 +    char *XXXXXX = &tmpl[len - 6];
    1.32 +
    1.33 +    uint64_t random_time_bits = time(NULL);
    1.34 +
    1.35 +    value += (random_time_bits ^ getpid());
    1.36 +
    1.37 +    unsigned int count;
    1.38 +    for (count = 0; count < ATTEMPTS_MIN; value += 7777, ++count)
    1.39 +    {
    1.40 +        uint64_t v = value;
    1.41 +
    1.42 +        XXXXXX[0] = letters[v % 62];
    1.43 +        v /= 62;
    1.44 +        XXXXXX[1] = letters[v % 62];
    1.45 +        v /= 62;
    1.46 +        XXXXXX[2] = letters[v % 62];
    1.47 +        v /= 62;
    1.48 +        XXXXXX[3] = letters[v % 62];
    1.49 +        v /= 62;
    1.50 +        XXXXXX[4] = letters[v % 62];
    1.51 +        v /= 62;
    1.52 +        XXXXXX[5] = letters[v % 62];
    1.53 +
    1.54 +		if (mkdir(tmpl) == 0)
    1.55 +        {
    1.56 +            errno = save_errno;
    1.57 +			return tmpl;
    1.58 +        }
    1.59 +
    1.60 +		if (errno != EEXIST)
    1.61 +			return NULL;
    1.62 +    }
    1.63 +
    1.64 +    errno = EEXIST;
    1.65 +    return NULL;
    1.66 +}