blob: 9ed1bc80f4eae35d7f50066368d9d3b5a80dff77 [file] [log] [blame]
Damien Millerd4a8b7e1999-10-27 13:42:43 +10001/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
2/* Changes: Removed mktemp */
3
4/*
5 * Copyright (c) 1987, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
Damien Miller87d29ed2000-08-30 09:21:22 +110037#include "includes.h"
Damien Miller04f80141999-11-19 15:32:34 +110038
39#ifndef HAVE_MKDTEMP
40
Damien Millerd4a8b7e1999-10-27 13:42:43 +100041#if defined(LIBC_SCCS) && !defined(lint)
42static char rcsid[] = "$OpenBSD: mktemp.c,v 1.13 1998/06/30 23:03:13 deraadt Exp $";
43#endif /* LIBC_SCCS and not lint */
44
Damien Millerbac2d8a2000-09-05 16:13:06 +110045#ifdef HAVE_CYGWIN
46#define open binary_open
47extern int binary_open();
48#endif
49
Damien Millerab18c411999-11-11 10:40:23 +110050static int _gettemp(char *, int *, int, int);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100051
52int
53mkstemps(path, slen)
54 char *path;
55 int slen;
56{
57 int fd;
58
59 return (_gettemp(path, &fd, 0, slen) ? fd : -1);
60}
61
62int
63mkstemp(path)
64 char *path;
65{
66 int fd;
67
68 return (_gettemp(path, &fd, 0, 0) ? fd : -1);
69}
70
71char *
72mkdtemp(path)
73 char *path;
74{
75 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
76}
77
78static int
79_gettemp(path, doopen, domkdir, slen)
80 char *path;
81 register int *doopen;
82 int domkdir;
83 int slen;
84{
85 register char *start, *trv, *suffp;
86 struct stat sbuf;
87 int pid, rval;
88
89 if (doopen && domkdir) {
90 errno = EINVAL;
91 return(0);
92 }
93
94 for (trv = path; *trv; ++trv)
95 ;
96 trv -= slen;
97 suffp = trv;
98 --trv;
99 if (trv < path) {
100 errno = EINVAL;
101 return (0);
102 }
103 pid = getpid();
104 while (*trv == 'X' && pid != 0) {
105 *trv-- = (pid % 10) + '0';
106 pid /= 10;
107 }
108 while (*trv == 'X') {
109 char c;
110
111 pid = (arc4random() & 0xffff) % (26+26);
112 if (pid < 26)
113 c = pid + 'A';
114 else
115 c = (pid - 26) + 'a';
116 *trv-- = c;
117 }
118 start = trv + 1;
119
120 /*
121 * check the target directory; if you have six X's and it
122 * doesn't exist this runs for a *very* long time.
123 */
124 if (doopen || domkdir) {
125 for (;; --trv) {
126 if (trv <= path)
127 break;
128 if (*trv == '/') {
129 *trv = '\0';
130 rval = stat(path, &sbuf);
131 *trv = '/';
132 if (rval != 0)
133 return(0);
134 if (!S_ISDIR(sbuf.st_mode)) {
135 errno = ENOTDIR;
136 return(0);
137 }
138 break;
139 }
140 }
141 }
142
143 for (;;) {
144 if (doopen) {
145 if ((*doopen =
146 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
147 return(1);
148 if (errno != EEXIST)
149 return(0);
150 } else if (domkdir) {
151 if (mkdir(path, 0700) == 0)
152 return(1);
153 if (errno != EEXIST)
154 return(0);
155 } else if (lstat(path, &sbuf))
156 return(errno == ENOENT ? 1 : 0);
157
158 /* tricky little algorithm for backward compatibility */
159 for (trv = start;;) {
160 if (!*trv)
161 return (0);
162 if (*trv == 'Z') {
163 if (trv == suffp)
164 return (0);
165 *trv++ = 'a';
166 } else {
167 if (isdigit(*trv))
168 *trv = 'a';
169 else if (*trv == 'z') /* inc from z to A */
170 *trv = 'A';
171 else {
172 if (trv == suffp)
173 return (0);
174 ++*trv;
175 }
176 break;
177 }
178 }
179 }
180 /*NOTREACHED*/
181}
Damien Millere413cba1999-10-28 14:12:54 +1000182
183#endif /* !HAVE_MKDTEMP */