blob: 7c02ea1a29084c970babe11459db90338b7a990b [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 Miller04f80141999-11-19 15:32:34 +110037#include "config.h"
38
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
45#include <sys/types.h>
46#include <sys/stat.h>
47#include <fcntl.h>
48#include <errno.h>
49#include <stdio.h>
50#include <stdlib.h>
51#include <ctype.h>
52#include <unistd.h>
53
Damien Miller58ca7d81999-12-29 19:56:30 +110054#include "bsd-misc.h"
Damien Miller3d112ef1999-10-28 13:20:30 +100055
Damien Millerab18c411999-11-11 10:40:23 +110056static int _gettemp(char *, int *, int, int);
Damien Millerd4a8b7e1999-10-27 13:42:43 +100057
58int
59mkstemps(path, slen)
60 char *path;
61 int slen;
62{
63 int fd;
64
65 return (_gettemp(path, &fd, 0, slen) ? fd : -1);
66}
67
68int
69mkstemp(path)
70 char *path;
71{
72 int fd;
73
74 return (_gettemp(path, &fd, 0, 0) ? fd : -1);
75}
76
77char *
78mkdtemp(path)
79 char *path;
80{
81 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
82}
83
84static int
85_gettemp(path, doopen, domkdir, slen)
86 char *path;
87 register int *doopen;
88 int domkdir;
89 int slen;
90{
91 register char *start, *trv, *suffp;
92 struct stat sbuf;
93 int pid, rval;
94
95 if (doopen && domkdir) {
96 errno = EINVAL;
97 return(0);
98 }
99
100 for (trv = path; *trv; ++trv)
101 ;
102 trv -= slen;
103 suffp = trv;
104 --trv;
105 if (trv < path) {
106 errno = EINVAL;
107 return (0);
108 }
109 pid = getpid();
110 while (*trv == 'X' && pid != 0) {
111 *trv-- = (pid % 10) + '0';
112 pid /= 10;
113 }
114 while (*trv == 'X') {
115 char c;
116
117 pid = (arc4random() & 0xffff) % (26+26);
118 if (pid < 26)
119 c = pid + 'A';
120 else
121 c = (pid - 26) + 'a';
122 *trv-- = c;
123 }
124 start = trv + 1;
125
126 /*
127 * check the target directory; if you have six X's and it
128 * doesn't exist this runs for a *very* long time.
129 */
130 if (doopen || domkdir) {
131 for (;; --trv) {
132 if (trv <= path)
133 break;
134 if (*trv == '/') {
135 *trv = '\0';
136 rval = stat(path, &sbuf);
137 *trv = '/';
138 if (rval != 0)
139 return(0);
140 if (!S_ISDIR(sbuf.st_mode)) {
141 errno = ENOTDIR;
142 return(0);
143 }
144 break;
145 }
146 }
147 }
148
149 for (;;) {
150 if (doopen) {
151 if ((*doopen =
152 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
153 return(1);
154 if (errno != EEXIST)
155 return(0);
156 } else if (domkdir) {
157 if (mkdir(path, 0700) == 0)
158 return(1);
159 if (errno != EEXIST)
160 return(0);
161 } else if (lstat(path, &sbuf))
162 return(errno == ENOENT ? 1 : 0);
163
164 /* tricky little algorithm for backward compatibility */
165 for (trv = start;;) {
166 if (!*trv)
167 return (0);
168 if (*trv == 'Z') {
169 if (trv == suffp)
170 return (0);
171 *trv++ = 'a';
172 } else {
173 if (isdigit(*trv))
174 *trv = 'a';
175 else if (*trv == 'z') /* inc from z to A */
176 *trv = 'A';
177 else {
178 if (trv == suffp)
179 return (0);
180 ++*trv;
181 }
182 break;
183 }
184 }
185 }
186 /*NOTREACHED*/
187}
Damien Millere413cba1999-10-28 14:12:54 +1000188
189#endif /* !HAVE_MKDTEMP */