1#define _CRT_RAND_S
2#include <stdlib.h>
3#include <string.h>
4#include <direct.h>
5#include <errno.h>
6#include <time.h>
7#include <limits.h>
8
9/*
10 The mkdtemp() function generates a unique temporary name from template,
11 the creates the directory with that name and returns pointer to the modified
12 template string.
13
14 The template may be any name with at least six trailing Xs, for example
15 /tmp/temp.XXXXXXXX. The trailing Xs are replaced with a unique digit and
16 letter combination that makes the file name unique. Since it will be
17 modified, template must not be a string constant, but should be declared as
18 a character array.
19 */
20char *__cdecl mkdtemp (char *template_name)
21{
22 int j, ret, len, index;
23 unsigned int i, r;
24
25 /* These are the (62) characters used in temporary filenames. */
26 static const char letters[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
27
28 /* The last six characters of template must be "XXXXXX" */
29 if (template_name == NULL || (len = strlen (template_name)) < 6
30 || memcmp (template_name + (len - 6), "XXXXXX", 6)) {
31 errno = EINVAL;
32 return NULL;
33 }
34
35 /* User may supply more than six trailing Xs */
36 for (index = len - 6; index > 0 && template_name[index - 1] == 'X'; index--);
37
38 /* Like OpenBSD, mkdtemp() will try 2 ** 31 combinations before giving up. */
39 for (i = 0; i <= INT_MAX; i++) {
40 for(j = index; j < len; j++) {
41 if (rand_s(&r))
42 r = rand() ^ _time32(NULL);
43 template_name[j] = letters[r % 62];
44 }
45 ret = _mkdir(template_name);
46 if (ret == 0) return template_name;
47 if (ret != 0 && errno != EEXIST) return NULL;
48 }
49
50 return NULL;
51}
52
53#if 0
54#include <stdio.h>
55int main ()
56{
57 int i;
58
59 for (i = 0; i < 10; i++) {
60 char template_name[] = { "temp_XXXXXX" };
61 char *name = mkdtemp (template_name);
62 if (name) {
63 fprintf (stderr, "name=%s\n", name);
64 rmdir (name);
65 } else {
66 fprintf (stderr, "errno=%d\n", errno);
67 }
68 }
69
70 for (i = 0; i < 10; i++) {
71 char template_name[] = { "temp_XXXXXXXX" };
72 char *name = mkdtemp (template_name);
73 if (name) {
74 fprintf (stderr, "name=%s\n", name);
75 rmdir (name);
76 } else {
77 fprintf (stderr, "errno=%d\n", errno);
78 }
79 }
80
81 return 0;
82}
83#endif