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