xref: /freebsd/crypto/krb5/src/util/support/mkstemp.c (revision 7f2fe78b9dd5f51c821d771b63d2e096f6fd49e9)
1*7f2fe78bSCy Schubert /* -*- mode: c; c-file-style: "bsd"; indent-tabs-mode: t -*- */
2*7f2fe78bSCy Schubert /*
3*7f2fe78bSCy Schubert  * Copyright (c) 1987, 1993
4*7f2fe78bSCy Schubert  *	The Regents of the University of California.  All rights reserved.
5*7f2fe78bSCy Schubert  *
6*7f2fe78bSCy Schubert  * Redistribution and use in source and binary forms, with or without
7*7f2fe78bSCy Schubert  * modification, are permitted provided that the following conditions
8*7f2fe78bSCy Schubert  * are met:
9*7f2fe78bSCy Schubert  * 1. Redistributions of source code must retain the above copyright
10*7f2fe78bSCy Schubert  *    notice, this list of conditions and the following disclaimer.
11*7f2fe78bSCy Schubert  * 2. Redistributions in binary form must reproduce the above copyright
12*7f2fe78bSCy Schubert  *    notice, this list of conditions and the following disclaimer in the
13*7f2fe78bSCy Schubert  *    documentation and/or other materials provided with the distribution.
14*7f2fe78bSCy Schubert  * 3. All advertising materials mentioning features or use of this software
15*7f2fe78bSCy Schubert  *    must display the following acknowledgement:
16*7f2fe78bSCy Schubert  *	This product includes software developed by the University of
17*7f2fe78bSCy Schubert  *	California, Berkeley and its contributors.
18*7f2fe78bSCy Schubert  * 4. Neither the name of the University nor the names of its contributors
19*7f2fe78bSCy Schubert  *    may be used to endorse or promote products derived from this software
20*7f2fe78bSCy Schubert  *    without specific prior written permission.
21*7f2fe78bSCy Schubert  *
22*7f2fe78bSCy Schubert  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*7f2fe78bSCy Schubert  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*7f2fe78bSCy Schubert  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*7f2fe78bSCy Schubert  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*7f2fe78bSCy Schubert  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*7f2fe78bSCy Schubert  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*7f2fe78bSCy Schubert  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*7f2fe78bSCy Schubert  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*7f2fe78bSCy Schubert  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*7f2fe78bSCy Schubert  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*7f2fe78bSCy Schubert  * SUCH DAMAGE.
33*7f2fe78bSCy Schubert  */
34*7f2fe78bSCy Schubert 
35*7f2fe78bSCy Schubert #if defined(LIBC_SCCS) && !defined(lint)
36*7f2fe78bSCy Schubert static char sccsid[] = "@(#)mktemp.c	8.1 (Berkeley) 6/4/93";
37*7f2fe78bSCy Schubert #endif /* LIBC_SCCS and not lint */
38*7f2fe78bSCy Schubert 
39*7f2fe78bSCy Schubert #include "k5-platform.h"
40*7f2fe78bSCy Schubert 
41*7f2fe78bSCy Schubert #include <sys/types.h>
42*7f2fe78bSCy Schubert #include <sys/stat.h>
43*7f2fe78bSCy Schubert #include <fcntl.h>
44*7f2fe78bSCy Schubert #include <errno.h>
45*7f2fe78bSCy Schubert #include <stdio.h>
46*7f2fe78bSCy Schubert #include <ctype.h>
47*7f2fe78bSCy Schubert #ifdef HAVE_UNISTD_H
48*7f2fe78bSCy Schubert #include <unistd.h>
49*7f2fe78bSCy Schubert #endif
50*7f2fe78bSCy Schubert 
51*7f2fe78bSCy Schubert #ifndef O_BINARY
52*7f2fe78bSCy Schubert #define O_BINARY 0
53*7f2fe78bSCy Schubert #endif
54*7f2fe78bSCy Schubert 
55*7f2fe78bSCy Schubert #if !defined S_ISDIR
56*7f2fe78bSCy Schubert #if defined S_IFMT
57*7f2fe78bSCy Schubert #define S_ISDIR(MODE)	(((MODE) & S_IFMT) == S_IFDIR)
58*7f2fe78bSCy Schubert #elif defined _S_IFMT
59*7f2fe78bSCy Schubert #define S_ISDIR(MODE)	(((MODE) & _S_IFMT) == _S_IFDIR)
60*7f2fe78bSCy Schubert #else
61*7f2fe78bSCy Schubert /* Hope that there's a S_ISDIR function defined.  */
62*7f2fe78bSCy Schubert #endif
63*7f2fe78bSCy Schubert #endif
64*7f2fe78bSCy Schubert 
65*7f2fe78bSCy Schubert static int _gettemp(char *, int *);
66*7f2fe78bSCy Schubert 
mkstemp(path)67*7f2fe78bSCy Schubert int mkstemp(path)
68*7f2fe78bSCy Schubert 	char *path;
69*7f2fe78bSCy Schubert {
70*7f2fe78bSCy Schubert 	int fd;
71*7f2fe78bSCy Schubert 
72*7f2fe78bSCy Schubert 	return (_gettemp(path, &fd) ? fd : -1);
73*7f2fe78bSCy Schubert }
74*7f2fe78bSCy Schubert 
75*7f2fe78bSCy Schubert static int
_gettemp(path,doopen)76*7f2fe78bSCy Schubert _gettemp(path, doopen)
77*7f2fe78bSCy Schubert 	char *path;
78*7f2fe78bSCy Schubert 	int *doopen;
79*7f2fe78bSCy Schubert {
80*7f2fe78bSCy Schubert 	char *start, *trv;
81*7f2fe78bSCy Schubert 	struct stat sbuf;
82*7f2fe78bSCy Schubert 	u_int pid;
83*7f2fe78bSCy Schubert 
84*7f2fe78bSCy Schubert 	pid = getpid();
85*7f2fe78bSCy Schubert 	for (trv = path; *trv; ++trv);		/* extra X's get set to 0's */
86*7f2fe78bSCy Schubert 	while (*--trv == 'X') {
87*7f2fe78bSCy Schubert 		*trv = (pid % 10) + '0';
88*7f2fe78bSCy Schubert 		pid /= 10;
89*7f2fe78bSCy Schubert 	}
90*7f2fe78bSCy Schubert 
91*7f2fe78bSCy Schubert 	/*
92*7f2fe78bSCy Schubert 	 * check the target directory; if you have six X's and it
93*7f2fe78bSCy Schubert 	 * doesn't exist this runs for a *very* long time.
94*7f2fe78bSCy Schubert 	 */
95*7f2fe78bSCy Schubert 	for (start = trv + 1;; --trv) {
96*7f2fe78bSCy Schubert 		if (trv <= path)
97*7f2fe78bSCy Schubert 			break;
98*7f2fe78bSCy Schubert 		if (*trv == '/') {
99*7f2fe78bSCy Schubert 			*trv = '\0';
100*7f2fe78bSCy Schubert 			if (stat(path, &sbuf))
101*7f2fe78bSCy Schubert 				return(0);
102*7f2fe78bSCy Schubert 			if (!S_ISDIR(sbuf.st_mode)) {
103*7f2fe78bSCy Schubert 				errno = ENOTDIR;
104*7f2fe78bSCy Schubert 				return(0);
105*7f2fe78bSCy Schubert 			}
106*7f2fe78bSCy Schubert 			*trv = '/';
107*7f2fe78bSCy Schubert 			break;
108*7f2fe78bSCy Schubert 		}
109*7f2fe78bSCy Schubert 	}
110*7f2fe78bSCy Schubert 
111*7f2fe78bSCy Schubert 	for (;;) {
112*7f2fe78bSCy Schubert 		if (doopen) {
113*7f2fe78bSCy Schubert 			if ((*doopen =
114*7f2fe78bSCy Schubert 			    open(path, O_CREAT|O_EXCL|O_RDWR|O_BINARY, 0600)) >= 0)
115*7f2fe78bSCy Schubert 				return(1);
116*7f2fe78bSCy Schubert 			if (errno != EEXIST)
117*7f2fe78bSCy Schubert 				return(0);
118*7f2fe78bSCy Schubert 		}
119*7f2fe78bSCy Schubert 		else if (stat(path, &sbuf))
120*7f2fe78bSCy Schubert 			return(errno == ENOENT ? 1 : 0);
121*7f2fe78bSCy Schubert 
122*7f2fe78bSCy Schubert 		/* tricky little algorithm for backward compatibility */
123*7f2fe78bSCy Schubert 		for (trv = start;;) {
124*7f2fe78bSCy Schubert 			if (!*trv)
125*7f2fe78bSCy Schubert 				return(0);
126*7f2fe78bSCy Schubert 			if (*trv == 'z')
127*7f2fe78bSCy Schubert 				*trv++ = 'a';
128*7f2fe78bSCy Schubert 			else {
129*7f2fe78bSCy Schubert 				if (isdigit(*trv))
130*7f2fe78bSCy Schubert 					*trv = 'a';
131*7f2fe78bSCy Schubert 				else
132*7f2fe78bSCy Schubert 					++*trv;
133*7f2fe78bSCy Schubert 				break;
134*7f2fe78bSCy Schubert 			}
135*7f2fe78bSCy Schubert 		}
136*7f2fe78bSCy Schubert 	}
137*7f2fe78bSCy Schubert 	/*NOTREACHED*/
138*7f2fe78bSCy Schubert }
139