xref: /original-bsd/lib/libc/stdio/mktemp.c (revision 823023b8)
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.7 (Berkeley) 06/27/88";
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 #define	YES	1
30 #define	NO	0
31 
32 mkstemp(as)
33 	char	*as;
34 {
35 	int	fd;
36 
37 	return (_gettemp(as, &fd) ? fd : -1);
38 }
39 
40 char *
41 mktemp(as)
42 	char	*as;
43 {
44 	return(_gettemp(as, (int *)NULL) ? as : (char *)NULL);
45 }
46 
47 static
48 _gettemp(as, doopen)
49 	char	*as;
50 	register int	*doopen;
51 {
52 	extern int	errno;
53 	register char	*start, *trv;
54 	struct stat	sbuf;
55 	u_int	pid;
56 
57 	pid = getpid();
58 
59 	/* extra X's get set to 0's */
60 	for (trv = as; *trv; ++trv);
61 	while (*--trv == 'X') {
62 		*trv = (pid % 10) + '0';
63 		pid /= 10;
64 	}
65 
66 	/*
67 	 * check for write permission on target directory; if you have
68 	 * six X's and you can't write the directory, this will run for
69 	 * a *very* long time.
70 	 */
71 	for (start = ++trv; trv > as && *trv != '/'; --trv);
72 	if (*trv == '/') {
73 		*trv = '\0';
74 		if (stat(as, &sbuf) || !(sbuf.st_mode & S_IFDIR))
75 			return(NO);
76 		*trv = '/';
77 	}
78 	else if (stat(".", &sbuf) == -1)
79 		return(NO);
80 
81 	for (;;) {
82 		if (doopen) {
83 		    if ((*doopen = open(as, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
84 			return(YES);
85 		    if (errno != EEXIST)
86 			return(NO);
87 		}
88 		else if (stat(as, &sbuf))
89 			return(errno == ENOENT ? YES : NO);
90 
91 		/* tricky little algorithm for backward compatibility */
92 		for (trv = start;;) {
93 			if (!*trv)
94 				return(NO);
95 			if (*trv == 'z')
96 				*trv++ = 'a';
97 			else {
98 				if (isdigit(*trv))
99 					*trv = 'a';
100 				else
101 					++*trv;
102 				break;
103 			}
104 		}
105 	}
106 	/*NOTREACHED*/
107 }
108