xref: /freebsd/crypto/openssh/openbsd-compat/mktemp.c (revision 021d409f5beb1827f72d24f171e3c3ed233ed62a)
183d2307dSDag-Erling Smørgrav /* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
283d2307dSDag-Erling Smørgrav /* Changes: Removed mktemp */
383d2307dSDag-Erling Smørgrav 
4021d409fSDag-Erling Smørgrav /*	$OpenBSD: mktemp.c,v 1.19 2005/08/08 08:05:36 espie Exp $ */
583d2307dSDag-Erling Smørgrav /*
683d2307dSDag-Erling Smørgrav  * Copyright (c) 1987, 1993
783d2307dSDag-Erling Smørgrav  *	The Regents of the University of California.  All rights reserved.
883d2307dSDag-Erling Smørgrav  *
983d2307dSDag-Erling Smørgrav  * Redistribution and use in source and binary forms, with or without
1083d2307dSDag-Erling Smørgrav  * modification, are permitted provided that the following conditions
1183d2307dSDag-Erling Smørgrav  * are met:
1283d2307dSDag-Erling Smørgrav  * 1. Redistributions of source code must retain the above copyright
1383d2307dSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer.
1483d2307dSDag-Erling Smørgrav  * 2. Redistributions in binary form must reproduce the above copyright
1583d2307dSDag-Erling Smørgrav  *    notice, this list of conditions and the following disclaimer in the
1683d2307dSDag-Erling Smørgrav  *    documentation and/or other materials provided with the distribution.
17d95e11bfSDag-Erling Smørgrav  * 3. Neither the name of the University nor the names of its contributors
1883d2307dSDag-Erling Smørgrav  *    may be used to endorse or promote products derived from this software
1983d2307dSDag-Erling Smørgrav  *    without specific prior written permission.
2083d2307dSDag-Erling Smørgrav  *
2183d2307dSDag-Erling Smørgrav  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2283d2307dSDag-Erling Smørgrav  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2383d2307dSDag-Erling Smørgrav  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2483d2307dSDag-Erling Smørgrav  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2583d2307dSDag-Erling Smørgrav  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2683d2307dSDag-Erling Smørgrav  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2783d2307dSDag-Erling Smørgrav  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2883d2307dSDag-Erling Smørgrav  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2983d2307dSDag-Erling Smørgrav  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3083d2307dSDag-Erling Smørgrav  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3183d2307dSDag-Erling Smørgrav  * SUCH DAMAGE.
3283d2307dSDag-Erling Smørgrav  */
3383d2307dSDag-Erling Smørgrav 
34021d409fSDag-Erling Smørgrav /* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */
35021d409fSDag-Erling Smørgrav 
3683d2307dSDag-Erling Smørgrav #include "includes.h"
3783d2307dSDag-Erling Smørgrav 
38d0c8c0bcSDag-Erling Smørgrav #if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
3983d2307dSDag-Erling Smørgrav 
4083d2307dSDag-Erling Smørgrav static int _gettemp(char *, int *, int, int);
4183d2307dSDag-Erling Smørgrav 
4283d2307dSDag-Erling Smørgrav int
43021d409fSDag-Erling Smørgrav mkstemps(char *path, int slen)
4483d2307dSDag-Erling Smørgrav {
4583d2307dSDag-Erling Smørgrav 	int fd;
4683d2307dSDag-Erling Smørgrav 
4783d2307dSDag-Erling Smørgrav 	return (_gettemp(path, &fd, 0, slen) ? fd : -1);
4883d2307dSDag-Erling Smørgrav }
4983d2307dSDag-Erling Smørgrav 
5083d2307dSDag-Erling Smørgrav int
51021d409fSDag-Erling Smørgrav mkstemp(char *path)
5283d2307dSDag-Erling Smørgrav {
5383d2307dSDag-Erling Smørgrav 	int fd;
5483d2307dSDag-Erling Smørgrav 
5583d2307dSDag-Erling Smørgrav 	return (_gettemp(path, &fd, 0, 0) ? fd : -1);
5683d2307dSDag-Erling Smørgrav }
5783d2307dSDag-Erling Smørgrav 
5883d2307dSDag-Erling Smørgrav char *
59021d409fSDag-Erling Smørgrav mkdtemp(char *path)
6083d2307dSDag-Erling Smørgrav {
6183d2307dSDag-Erling Smørgrav 	return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
6283d2307dSDag-Erling Smørgrav }
6383d2307dSDag-Erling Smørgrav 
6483d2307dSDag-Erling Smørgrav static int
6583d2307dSDag-Erling Smørgrav _gettemp(path, doopen, domkdir, slen)
6683d2307dSDag-Erling Smørgrav 	char *path;
6783d2307dSDag-Erling Smørgrav 	register int *doopen;
6883d2307dSDag-Erling Smørgrav 	int domkdir;
6983d2307dSDag-Erling Smørgrav 	int slen;
7083d2307dSDag-Erling Smørgrav {
7183d2307dSDag-Erling Smørgrav 	register char *start, *trv, *suffp;
7283d2307dSDag-Erling Smørgrav 	struct stat sbuf;
7383d2307dSDag-Erling Smørgrav 	int rval;
7483d2307dSDag-Erling Smørgrav 	pid_t pid;
7583d2307dSDag-Erling Smørgrav 
7683d2307dSDag-Erling Smørgrav 	if (doopen && domkdir) {
7783d2307dSDag-Erling Smørgrav 		errno = EINVAL;
7883d2307dSDag-Erling Smørgrav 		return(0);
7983d2307dSDag-Erling Smørgrav 	}
8083d2307dSDag-Erling Smørgrav 
8183d2307dSDag-Erling Smørgrav 	for (trv = path; *trv; ++trv)
8283d2307dSDag-Erling Smørgrav 		;
8383d2307dSDag-Erling Smørgrav 	trv -= slen;
8483d2307dSDag-Erling Smørgrav 	suffp = trv;
8583d2307dSDag-Erling Smørgrav 	--trv;
8683d2307dSDag-Erling Smørgrav 	if (trv < path) {
8783d2307dSDag-Erling Smørgrav 		errno = EINVAL;
8883d2307dSDag-Erling Smørgrav 		return (0);
8983d2307dSDag-Erling Smørgrav 	}
9083d2307dSDag-Erling Smørgrav 	pid = getpid();
914b17dab0SDag-Erling Smørgrav 	while (trv >= path && *trv == 'X' && pid != 0) {
9283d2307dSDag-Erling Smørgrav 		*trv-- = (pid % 10) + '0';
9383d2307dSDag-Erling Smørgrav 		pid /= 10;
9483d2307dSDag-Erling Smørgrav 	}
954b17dab0SDag-Erling Smørgrav 	while (trv >= path && *trv == 'X') {
9683d2307dSDag-Erling Smørgrav 		char c;
9783d2307dSDag-Erling Smørgrav 
9883d2307dSDag-Erling Smørgrav 		pid = (arc4random() & 0xffff) % (26+26);
9983d2307dSDag-Erling Smørgrav 		if (pid < 26)
10083d2307dSDag-Erling Smørgrav 			c = pid + 'A';
10183d2307dSDag-Erling Smørgrav 		else
10283d2307dSDag-Erling Smørgrav 			c = (pid - 26) + 'a';
10383d2307dSDag-Erling Smørgrav 		*trv-- = c;
10483d2307dSDag-Erling Smørgrav 	}
10583d2307dSDag-Erling Smørgrav 	start = trv + 1;
10683d2307dSDag-Erling Smørgrav 
10783d2307dSDag-Erling Smørgrav 	/*
10883d2307dSDag-Erling Smørgrav 	 * check the target directory; if you have six X's and it
10983d2307dSDag-Erling Smørgrav 	 * doesn't exist this runs for a *very* long time.
11083d2307dSDag-Erling Smørgrav 	 */
11183d2307dSDag-Erling Smørgrav 	if (doopen || domkdir) {
11283d2307dSDag-Erling Smørgrav 		for (;; --trv) {
11383d2307dSDag-Erling Smørgrav 			if (trv <= path)
11483d2307dSDag-Erling Smørgrav 				break;
11583d2307dSDag-Erling Smørgrav 			if (*trv == '/') {
11683d2307dSDag-Erling Smørgrav 				*trv = '\0';
11783d2307dSDag-Erling Smørgrav 				rval = stat(path, &sbuf);
11883d2307dSDag-Erling Smørgrav 				*trv = '/';
11983d2307dSDag-Erling Smørgrav 				if (rval != 0)
12083d2307dSDag-Erling Smørgrav 					return(0);
12183d2307dSDag-Erling Smørgrav 				if (!S_ISDIR(sbuf.st_mode)) {
12283d2307dSDag-Erling Smørgrav 					errno = ENOTDIR;
12383d2307dSDag-Erling Smørgrav 					return(0);
12483d2307dSDag-Erling Smørgrav 				}
12583d2307dSDag-Erling Smørgrav 				break;
12683d2307dSDag-Erling Smørgrav 			}
12783d2307dSDag-Erling Smørgrav 		}
12883d2307dSDag-Erling Smørgrav 	}
12983d2307dSDag-Erling Smørgrav 
13083d2307dSDag-Erling Smørgrav 	for (;;) {
13183d2307dSDag-Erling Smørgrav 		if (doopen) {
13283d2307dSDag-Erling Smørgrav 			if ((*doopen =
13383d2307dSDag-Erling Smørgrav 			    open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
13483d2307dSDag-Erling Smørgrav 				return(1);
13583d2307dSDag-Erling Smørgrav 			if (errno != EEXIST)
13683d2307dSDag-Erling Smørgrav 				return(0);
13783d2307dSDag-Erling Smørgrav 		} else if (domkdir) {
13883d2307dSDag-Erling Smørgrav 			if (mkdir(path, 0700) == 0)
13983d2307dSDag-Erling Smørgrav 				return(1);
14083d2307dSDag-Erling Smørgrav 			if (errno != EEXIST)
14183d2307dSDag-Erling Smørgrav 				return(0);
14283d2307dSDag-Erling Smørgrav 		} else if (lstat(path, &sbuf))
14383d2307dSDag-Erling Smørgrav 			return(errno == ENOENT ? 1 : 0);
14483d2307dSDag-Erling Smørgrav 
14583d2307dSDag-Erling Smørgrav 		/* tricky little algorithm for backward compatibility */
14683d2307dSDag-Erling Smørgrav 		for (trv = start;;) {
14783d2307dSDag-Erling Smørgrav 			if (!*trv)
14883d2307dSDag-Erling Smørgrav 				return (0);
14983d2307dSDag-Erling Smørgrav 			if (*trv == 'Z') {
15083d2307dSDag-Erling Smørgrav 				if (trv == suffp)
15183d2307dSDag-Erling Smørgrav 					return (0);
15283d2307dSDag-Erling Smørgrav 				*trv++ = 'a';
15383d2307dSDag-Erling Smørgrav 			} else {
15483d2307dSDag-Erling Smørgrav 				if (isdigit(*trv))
15583d2307dSDag-Erling Smørgrav 					*trv = 'a';
15683d2307dSDag-Erling Smørgrav 				else if (*trv == 'z')	/* inc from z to A */
15783d2307dSDag-Erling Smørgrav 					*trv = 'A';
15883d2307dSDag-Erling Smørgrav 				else {
15983d2307dSDag-Erling Smørgrav 					if (trv == suffp)
16083d2307dSDag-Erling Smørgrav 						return (0);
16183d2307dSDag-Erling Smørgrav 					++*trv;
16283d2307dSDag-Erling Smørgrav 				}
16383d2307dSDag-Erling Smørgrav 				break;
16483d2307dSDag-Erling Smørgrav 			}
16583d2307dSDag-Erling Smørgrav 		}
16683d2307dSDag-Erling Smørgrav 	}
16783d2307dSDag-Erling Smørgrav 	/*NOTREACHED*/
16883d2307dSDag-Erling Smørgrav }
16983d2307dSDag-Erling Smørgrav 
170d0c8c0bcSDag-Erling Smørgrav #endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */
171