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