1 /* 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
37 #include "includes.h"
38
39 #ifndef HAVE_MKDTEMP
40
41 #if defined(LIBC_SCCS) && !defined(lint)
42 static char rcsid[] = "$OpenBSD: mktemp.c,v 1.16 2002/05/27 18:20:45 millert Exp $";
43 #endif /* LIBC_SCCS and not lint */
44
45 #ifdef HAVE_CYGWIN
46 #define open binary_open
47 extern int binary_open();
48 #endif
49
50 static int _gettemp(char *, int *, int, int);
51
52 int
mkstemps(path,slen)53 mkstemps(path, slen)
54 char *path;
55 int slen;
56 {
57 int fd;
58
59 return (_gettemp(path, &fd, 0, slen) ? fd : -1);
60 }
61
62 int
mkstemp(path)63 mkstemp(path)
64 char *path;
65 {
66 int fd;
67
68 return (_gettemp(path, &fd, 0, 0) ? fd : -1);
69 }
70
71 char *
mkdtemp(path)72 mkdtemp(path)
73 char *path;
74 {
75 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
76 }
77
78 static int
_gettemp(path,doopen,domkdir,slen)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 rval;
88 pid_t pid;
89
90 if (doopen && domkdir) {
91 errno = EINVAL;
92 return(0);
93 }
94
95 for (trv = path; *trv; ++trv)
96 ;
97 trv -= slen;
98 suffp = trv;
99 --trv;
100 if (trv < path) {
101 errno = EINVAL;
102 return (0);
103 }
104 pid = getpid();
105 while (trv >= path && *trv == 'X' && pid != 0) {
106 *trv-- = (pid % 10) + '0';
107 pid /= 10;
108 }
109 while (trv >= path && *trv == 'X') {
110 char c;
111
112 pid = (arc4random() & 0xffff) % (26+26);
113 if (pid < 26)
114 c = pid + 'A';
115 else
116 c = (pid - 26) + 'a';
117 *trv-- = c;
118 }
119 start = trv + 1;
120
121 /*
122 * check the target directory; if you have six X's and it
123 * doesn't exist this runs for a *very* long time.
124 */
125 if (doopen || domkdir) {
126 for (;; --trv) {
127 if (trv <= path)
128 break;
129 if (*trv == '/') {
130 *trv = '\0';
131 rval = stat(path, &sbuf);
132 *trv = '/';
133 if (rval != 0)
134 return(0);
135 if (!S_ISDIR(sbuf.st_mode)) {
136 errno = ENOTDIR;
137 return(0);
138 }
139 break;
140 }
141 }
142 }
143
144 for (;;) {
145 if (doopen) {
146 if ((*doopen =
147 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
148 return(1);
149 if (errno != EEXIST)
150 return(0);
151 } else if (domkdir) {
152 if (mkdir(path, 0700) == 0)
153 return(1);
154 if (errno != EEXIST)
155 return(0);
156 } else if (lstat(path, &sbuf))
157 return(errno == ENOENT ? 1 : 0);
158
159 /* tricky little algorithm for backward compatibility */
160 for (trv = start;;) {
161 if (!*trv)
162 return (0);
163 if (*trv == 'Z') {
164 if (trv == suffp)
165 return (0);
166 *trv++ = 'a';
167 } else {
168 if (isdigit(*trv))
169 *trv = 'a';
170 else if (*trv == 'z') /* inc from z to A */
171 *trv = 'A';
172 else {
173 if (trv == suffp)
174 return (0);
175 ++*trv;
176 }
177 break;
178 }
179 }
180 }
181 /*NOTREACHED*/
182 }
183
184 #endif /* !HAVE_MKDTEMP */
185
186 #pragma ident "%Z%%M% %I% %E% SMI"
187