1 /*
2  * mkstemp.c --
3  *
4  *	Source code for the "mkstemp" library routine.
5  *
6  * Copyright (c) 2009 Donal K. Fellows
7  *
8  * See the file "license.terms" for information on usage and redistribution of
9  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
10  */
11 
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <string.h>
17 
18 /*
19  *----------------------------------------------------------------------
20  *
21  * mkstemp --
22  *
23  *	Create an open temporary file from a template.
24  *
25  * Results:
26  *	A file descriptor, or -1 (with errno set) in the case of an error.
27  *
28  * Side effects:
29  *	The template is updated to contain the real filename.
30  *
31  *----------------------------------------------------------------------
32  */
33 
34 int
mkstemp(char * tmpl)35 mkstemp(
36     char *tmpl)		/* Template for filename. */
37 {
38     static const char alphanumerics[] =
39 	"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
40     char *a, *b;
41     int fd, count, alphanumericsLen = strlen(alphanumerics); /* == 62 */
42 
43     a = tmpl + strlen(tmpl);
44     while (a > tmpl && *(a-1) == 'X') {
45 	a--;
46     }
47 
48     if (a == tmpl) {
49 	errno = ENOENT;
50 	return -1;
51     }
52 
53     /*
54      * We'll only try up to 10 times; after that, we're suffering from enemy
55      * action and should let the caller know.
56      */
57 
58     count = 10;
59     do {
60 	/*
61 	 * Replace the X's in the original template with random alphanumeric
62 	 * digits.
63 	 */
64 
65 	for (b=a ; *b ; b++) {
66 	    float r = rand() / ((float) RAND_MAX);
67 
68 	    *b = alphanumerics[(int)(r * alphanumericsLen)];
69 	}
70 
71 	/*
72 	 * Template is now realized; try to open (with correct options).
73 	 */
74 
75 	fd = open(tmpl, O_RDWR|O_CREAT|O_EXCL, 0600);
76     } while (fd == -1 && errno == EEXIST && --count > 0);
77 
78     return fd;
79 }
80