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