mkdtemp.cpp
author insilmaril
Tue, 06 May 2008 10:24:27 +0000
changeset 698 14a1306dc144
parent 630 4998bb082c73
permissions -rwxr-xr-x
Version 1.12.0
insilmaril@630
     1
#include <stdint.h>
insilmaril@630
     2
#include <string.h>
insilmaril@630
     3
#include <errno.h>
insilmaril@630
     4
#include <io.h>
insilmaril@630
     5
#include <sys/time.h>
insilmaril@630
     6
insilmaril@630
     7
extern "C" {
insilmaril@630
     8
pid_t getpid (void);
insilmaril@630
     9
}
insilmaril@630
    10
insilmaril@630
    11
char *
insilmaril@630
    12
mkdtemp(char *tmpl)
insilmaril@630
    13
{
insilmaril@630
    14
    // Implementation based on GLIBC implementation.
insilmaril@630
    15
insilmaril@630
    16
    static const char letters[] =
insilmaril@630
    17
        "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
insilmaril@630
    18
insilmaril@630
    19
    static uint64_t value;
insilmaril@630
    20
insilmaril@630
    21
    const unsigned int ATTEMPTS_MIN = (62 * 62 * 62);
insilmaril@630
    22
insilmaril@630
    23
    int save_errno = errno;
insilmaril@630
    24
insilmaril@630
    25
    size_t len = strlen(tmpl);
insilmaril@630
    26
    if (len < 6 || strcmp(&tmpl[len - 6], "XXXXXX"))
insilmaril@630
    27
    {
insilmaril@630
    28
        errno = EINVAL;
insilmaril@630
    29
        return NULL;
insilmaril@630
    30
    }
insilmaril@630
    31
insilmaril@630
    32
    char *XXXXXX = &tmpl[len - 6];
insilmaril@630
    33
insilmaril@630
    34
    uint64_t random_time_bits = time(NULL);
insilmaril@630
    35
insilmaril@630
    36
    value += (random_time_bits ^ getpid());
insilmaril@630
    37
insilmaril@630
    38
    unsigned int count;
insilmaril@630
    39
    for (count = 0; count < ATTEMPTS_MIN; value += 7777, ++count)
insilmaril@630
    40
    {
insilmaril@630
    41
        uint64_t v = value;
insilmaril@630
    42
insilmaril@630
    43
        XXXXXX[0] = letters[v % 62];
insilmaril@630
    44
        v /= 62;
insilmaril@630
    45
        XXXXXX[1] = letters[v % 62];
insilmaril@630
    46
        v /= 62;
insilmaril@630
    47
        XXXXXX[2] = letters[v % 62];
insilmaril@630
    48
        v /= 62;
insilmaril@630
    49
        XXXXXX[3] = letters[v % 62];
insilmaril@630
    50
        v /= 62;
insilmaril@630
    51
        XXXXXX[4] = letters[v % 62];
insilmaril@630
    52
        v /= 62;
insilmaril@630
    53
        XXXXXX[5] = letters[v % 62];
insilmaril@630
    54
insilmaril@630
    55
		if (mkdir(tmpl) == 0)
insilmaril@630
    56
        {
insilmaril@630
    57
            errno = save_errno;
insilmaril@630
    58
			return tmpl;
insilmaril@630
    59
        }
insilmaril@630
    60
insilmaril@630
    61
		if (errno != EEXIST)
insilmaril@630
    62
			return NULL;
insilmaril@630
    63
    }
insilmaril@630
    64
insilmaril@630
    65
    errno = EEXIST;
insilmaril@630
    66
    return NULL;
insilmaril@630
    67
}