xref: /original-bsd/lib/libc/stdio/mktemp.c (revision da818fbb)
1 /*
2  * Copyright (c) 1987 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #if defined(LIBC_SCCS) && !defined(lint)
19 static char sccsid[] = "@(#)mktemp.c	5.8 (Berkeley) 10/16/89";
20 #endif /* LIBC_SCCS and not lint */
21 
22 #include <sys/types.h>
23 #include <sys/file.h>
24 #include <sys/stat.h>
25 #include <errno.h>
26 #include <stdio.h>
27 #include <ctype.h>
28 
29 mkstemp(path)
30 	char *path;
31 {
32 	int fd;
33 
34 	return (_gettemp(path, &fd) ? fd : -1);
35 }
36 
37 char *
38 mktemp(path)
39 	char *path;
40 {
41 	return(_gettemp(path, (int *)NULL) ? path : (char *)NULL);
42 }
43 
44 static
45 _gettemp(path, doopen)
46 	char *path;
47 	register int *doopen;
48 {
49 	extern int errno;
50 	register char *start, *trv;
51 	struct stat sbuf;
52 	u_int pid;
53 
54 	pid = getpid();
55 	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
56 	while (*--trv == 'X') {
57 		*trv = (pid % 10) + '0';
58 		pid /= 10;
59 	}
60 
61 	/*
62 	 * check the target directory; if you have six X's and it
63 	 * doesn't exist this runs for a *very* long time.
64 	 */
65 	for (start = trv + 1;; --trv) {
66 		if (trv <= path)
67 			break;
68 		if (*trv == '/') {
69 			*trv = '\0';
70 			if (stat(path, &sbuf))
71 				return(0);
72 			if (!S_ISDIR(sbuf.st_mode)) {
73 				errno = ENOTDIR;
74 				return(0);
75 			}
76 			*trv = '/';
77 			break;
78 		}
79 	}
80 
81 	for (;;) {
82 		if (doopen) {
83 			if ((*doopen =
84 			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
85 				return(1);
86 			if (errno != EEXIST)
87 				return(0);
88 		}
89 		else if (stat(path, &sbuf))
90 			return(errno == ENOENT ? 1 : 0);
91 
92 		/* tricky little algorithm for backward compatibility */
93 		for (trv = start;;) {
94 			if (!*trv)
95 				return(0);
96 			if (*trv == 'z')
97 				*trv++ = 'a';
98 			else {
99 				if (isdigit(*trv))
100 					*trv = 'a';
101 				else
102 					++*trv;
103 				break;
104 			}
105 		}
106 	}
107 	/*NOTREACHED*/
108 }
109