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