xref: /original-bsd/lib/libc/stdio/mktemp.c (revision abe165e9)
1 /*
2  * Copyright (c) 1987 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)mktemp.c	5.9 (Berkeley) 06/01/90";
10 #endif /* LIBC_SCCS and not lint */
11 
12 #include <sys/types.h>
13 #include <sys/file.h>
14 #include <sys/stat.h>
15 #include <errno.h>
16 #include <stdio.h>
17 #include <ctype.h>
18 
19 mkstemp(path)
20 	char *path;
21 {
22 	int fd;
23 
24 	return (_gettemp(path, &fd) ? fd : -1);
25 }
26 
27 char *
28 mktemp(path)
29 	char *path;
30 {
31 	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
32 }
33 
34 static
35 _gettemp(path, doopen)
36 	char *path;
37 	register int *doopen;
38 {
39 	extern int errno;
40 	register char *start, *trv;
41 	struct stat sbuf;
42 	u_int pid;
43 
44 	pid = getpid();
45 	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
46 	while (*--trv == 'X') {
47 		*trv = (pid % 10) + '0';
48 		pid /= 10;
49 	}
50 
51 	/*
52 	 * check the target directory; if you have six X's and it
53 	 * doesn't exist this runs for a *very* long time.
54 	 */
55 	for (start = trv + 1;; --trv) {
56 		if (trv <= path)
57 			break;
58 		if (*trv == '/') {
59 			*trv = '\0';
60 			if (stat(path, &sbuf))
61 				return(0);
62 			if (!S_ISDIR(sbuf.st_mode)) {
63 				errno = ENOTDIR;
64 				return(0);
65 			}
66 			*trv = '/';
67 			break;
68 		}
69 	}
70 
71 	for (;;) {
72 		if (doopen) {
73 			if ((*doopen =
74 			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
75 				return(1);
76 			if (errno != EEXIST)
77 				return(0);
78 		}
79 		else if (stat(path, &sbuf))
80 			return(errno == ENOENT ? 1 : 0);
81 
82 		/* tricky little algorithm for backward compatibility */
83 		for (trv = start;;) {
84 			if (!*trv)
85 				return(0);
86 			if (*trv == 'z')
87 				*trv++ = 'a';
88 			else {
89 				if (isdigit(*trv))
90 					*trv = 'a';
91 				else
92 					++*trv;
93 				break;
94 			}
95 		}
96 	}
97 	/*NOTREACHED*/
98 }
99