1bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
2bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* Changes: Removed mktemp */
3bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
4d059297112922cabb0c674840589be8db821fd9aAdam Langley/*	$OpenBSD: mktemp.c,v 1.30 2010/03/21 23:09:30 schwarze Exp $ */
5bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/*
6d059297112922cabb0c674840589be8db821fd9aAdam Langley * Copyright (c) 1996-1998, 2008 Theo de Raadt
7d059297112922cabb0c674840589be8db821fd9aAdam Langley * Copyright (c) 1997, 2008-2009 Todd C. Miller
8bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
9d059297112922cabb0c674840589be8db821fd9aAdam Langley * Permission to use, copy, modify, and distribute this software for any
10d059297112922cabb0c674840589be8db821fd9aAdam Langley * purpose with or without fee is hereby granted, provided that the above
11d059297112922cabb0c674840589be8db821fd9aAdam Langley * copyright notice and this permission notice appear in all copies.
12bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman *
13d059297112922cabb0c674840589be8db821fd9aAdam Langley * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14d059297112922cabb0c674840589be8db821fd9aAdam Langley * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15d059297112922cabb0c674840589be8db821fd9aAdam Langley * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16d059297112922cabb0c674840589be8db821fd9aAdam Langley * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17d059297112922cabb0c674840589be8db821fd9aAdam Langley * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18d059297112922cabb0c674840589be8db821fd9aAdam Langley * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19d059297112922cabb0c674840589be8db821fd9aAdam Langley * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman */
21bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
22bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman/* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */
23bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
24bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include "includes.h"
25bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
26bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/types.h>
27bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <sys/stat.h>
28d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <errno.h>
29bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <fcntl.h>
30d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <limits.h>
31d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <stdio.h>
32d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <stdlib.h>
33d059297112922cabb0c674840589be8db821fd9aAdam Langley#include <string.h>
34bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <ctype.h>
35bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#include <unistd.h>
36bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
37bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
38bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
39d059297112922cabb0c674840589be8db821fd9aAdam Langley#define MKTEMP_NAME	0
40d059297112922cabb0c674840589be8db821fd9aAdam Langley#define MKTEMP_FILE	1
41d059297112922cabb0c674840589be8db821fd9aAdam Langley#define MKTEMP_DIR	2
42bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
43d059297112922cabb0c674840589be8db821fd9aAdam Langley#define TEMPCHARS	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
44d059297112922cabb0c674840589be8db821fd9aAdam Langley#define NUM_CHARS	(sizeof(TEMPCHARS) - 1)
45d059297112922cabb0c674840589be8db821fd9aAdam Langley
46d059297112922cabb0c674840589be8db821fd9aAdam Langleystatic int
47d059297112922cabb0c674840589be8db821fd9aAdam Langleymktemp_internal(char *path, int slen, int mode)
48bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
49d059297112922cabb0c674840589be8db821fd9aAdam Langley	char *start, *cp, *ep;
50d059297112922cabb0c674840589be8db821fd9aAdam Langley	const char *tempchars = TEMPCHARS;
51d059297112922cabb0c674840589be8db821fd9aAdam Langley	unsigned int r, tries;
52d059297112922cabb0c674840589be8db821fd9aAdam Langley	struct stat sb;
53d059297112922cabb0c674840589be8db821fd9aAdam Langley	size_t len;
54bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman	int fd;
55bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
56d059297112922cabb0c674840589be8db821fd9aAdam Langley	len = strlen(path);
57d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (len == 0 || slen < 0 || (size_t)slen >= len) {
58d059297112922cabb0c674840589be8db821fd9aAdam Langley		errno = EINVAL;
59d059297112922cabb0c674840589be8db821fd9aAdam Langley		return(-1);
60d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
61d059297112922cabb0c674840589be8db821fd9aAdam Langley	ep = path + len - slen;
62d059297112922cabb0c674840589be8db821fd9aAdam Langley
63d059297112922cabb0c674840589be8db821fd9aAdam Langley	tries = 1;
64d059297112922cabb0c674840589be8db821fd9aAdam Langley	for (start = ep; start > path && start[-1] == 'X'; start--) {
65d059297112922cabb0c674840589be8db821fd9aAdam Langley		if (tries < INT_MAX / NUM_CHARS)
66d059297112922cabb0c674840589be8db821fd9aAdam Langley			tries *= NUM_CHARS;
67d059297112922cabb0c674840589be8db821fd9aAdam Langley	}
68d059297112922cabb0c674840589be8db821fd9aAdam Langley	tries *= 2;
69d059297112922cabb0c674840589be8db821fd9aAdam Langley
70d059297112922cabb0c674840589be8db821fd9aAdam Langley	do {
71d059297112922cabb0c674840589be8db821fd9aAdam Langley		for (cp = start; cp != ep; cp++) {
72d059297112922cabb0c674840589be8db821fd9aAdam Langley			r = arc4random_uniform(NUM_CHARS);
73d059297112922cabb0c674840589be8db821fd9aAdam Langley			*cp = tempchars[r];
74d059297112922cabb0c674840589be8db821fd9aAdam Langley		}
75d059297112922cabb0c674840589be8db821fd9aAdam Langley
76d059297112922cabb0c674840589be8db821fd9aAdam Langley		switch (mode) {
77d059297112922cabb0c674840589be8db821fd9aAdam Langley		case MKTEMP_NAME:
78d059297112922cabb0c674840589be8db821fd9aAdam Langley			if (lstat(path, &sb) != 0)
79d059297112922cabb0c674840589be8db821fd9aAdam Langley				return(errno == ENOENT ? 0 : -1);
80d059297112922cabb0c674840589be8db821fd9aAdam Langley			break;
81d059297112922cabb0c674840589be8db821fd9aAdam Langley		case MKTEMP_FILE:
82d059297112922cabb0c674840589be8db821fd9aAdam Langley			fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
83d059297112922cabb0c674840589be8db821fd9aAdam Langley			if (fd != -1 || errno != EEXIST)
84d059297112922cabb0c674840589be8db821fd9aAdam Langley				return(fd);
85d059297112922cabb0c674840589be8db821fd9aAdam Langley			break;
86d059297112922cabb0c674840589be8db821fd9aAdam Langley		case MKTEMP_DIR:
87d059297112922cabb0c674840589be8db821fd9aAdam Langley			if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0)
88d059297112922cabb0c674840589be8db821fd9aAdam Langley				return(0);
89d059297112922cabb0c674840589be8db821fd9aAdam Langley			if (errno != EEXIST)
90d059297112922cabb0c674840589be8db821fd9aAdam Langley				return(-1);
91d059297112922cabb0c674840589be8db821fd9aAdam Langley			break;
92d059297112922cabb0c674840589be8db821fd9aAdam Langley		}
93d059297112922cabb0c674840589be8db821fd9aAdam Langley	} while (--tries);
94d059297112922cabb0c674840589be8db821fd9aAdam Langley
95d059297112922cabb0c674840589be8db821fd9aAdam Langley	errno = EEXIST;
96d059297112922cabb0c674840589be8db821fd9aAdam Langley	return(-1);
97bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
98bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
99d059297112922cabb0c674840589be8db821fd9aAdam Langley#if 0
100d059297112922cabb0c674840589be8db821fd9aAdam Langleychar *_mktemp(char *);
101bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
102d059297112922cabb0c674840589be8db821fd9aAdam Langleychar *
103d059297112922cabb0c674840589be8db821fd9aAdam Langley_mktemp(char *path)
104d059297112922cabb0c674840589be8db821fd9aAdam Langley{
105d059297112922cabb0c674840589be8db821fd9aAdam Langley	if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
106d059297112922cabb0c674840589be8db821fd9aAdam Langley		return(NULL);
107d059297112922cabb0c674840589be8db821fd9aAdam Langley	return(path);
108bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
109bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
110d059297112922cabb0c674840589be8db821fd9aAdam Langley__warn_references(mktemp,
111d059297112922cabb0c674840589be8db821fd9aAdam Langley    "warning: mktemp() possibly used unsafely; consider using mkstemp()");
112d059297112922cabb0c674840589be8db821fd9aAdam Langley
113bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartmanchar *
114d059297112922cabb0c674840589be8db821fd9aAdam Langleymktemp(char *path)
115bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
116d059297112922cabb0c674840589be8db821fd9aAdam Langley	return(_mktemp(path));
117bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
118d059297112922cabb0c674840589be8db821fd9aAdam Langley#endif
119bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
120d059297112922cabb0c674840589be8db821fd9aAdam Langleyint
121d059297112922cabb0c674840589be8db821fd9aAdam Langleymkstemp(char *path)
122bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman{
123d059297112922cabb0c674840589be8db821fd9aAdam Langley	return(mktemp_internal(path, 0, MKTEMP_FILE));
124d059297112922cabb0c674840589be8db821fd9aAdam Langley}
125bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
126d059297112922cabb0c674840589be8db821fd9aAdam Langleyint
127d059297112922cabb0c674840589be8db821fd9aAdam Langleymkstemps(char *path, int slen)
128d059297112922cabb0c674840589be8db821fd9aAdam Langley{
129d059297112922cabb0c674840589be8db821fd9aAdam Langley	return(mktemp_internal(path, slen, MKTEMP_FILE));
130d059297112922cabb0c674840589be8db821fd9aAdam Langley}
131bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
132d059297112922cabb0c674840589be8db821fd9aAdam Langleychar *
133d059297112922cabb0c674840589be8db821fd9aAdam Langleymkdtemp(char *path)
134d059297112922cabb0c674840589be8db821fd9aAdam Langley{
135d059297112922cabb0c674840589be8db821fd9aAdam Langley	int error;
136bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
137d059297112922cabb0c674840589be8db821fd9aAdam Langley	error = mktemp_internal(path, 0, MKTEMP_DIR);
138d059297112922cabb0c674840589be8db821fd9aAdam Langley	return(error ? NULL : path);
139bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman}
140bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman
141bd77cf78387b72b7b3ea870459077672bf75c3b5Greg Hartman#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */
142