summaryrefslogtreecommitdiff
path: root/openbsd-compat/mktemp.c
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2012-05-17 13:04:02 +0100
committerColin Watson <cjwatson@debian.org>2012-05-17 13:04:02 +0100
commitdd5ed53e20d218607260916a6b04d1c8c5b3d88f (patch)
treec59b4dbcc610f10700945f885adf3bddc2542c26 /openbsd-compat/mktemp.c
parent8241a65bf12ac53c1b7304bba7ce739aad80b8b8 (diff)
parentb9bc38990c5eb5d99e28ca5af6d3491fd4a0060a (diff)
merge 6.0p1
Diffstat (limited to 'openbsd-compat/mktemp.c')
-rw-r--r--openbsd-compat/mktemp.c239
1 files changed, 101 insertions, 138 deletions
diff --git a/openbsd-compat/mktemp.c b/openbsd-compat/mktemp.c
index 2285c84df..4eb52f421 100644
--- a/openbsd-compat/mktemp.c
+++ b/openbsd-compat/mktemp.c
@@ -1,34 +1,22 @@
1/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */ 1/* THIS FILE HAS BEEN MODIFIED FROM THE ORIGINAL OPENBSD SOURCE */
2/* Changes: Removed mktemp */ 2/* Changes: Removed mktemp */
3 3
4/* $OpenBSD: mktemp.c,v 1.19 2005/08/08 08:05:36 espie Exp $ */ 4/* $OpenBSD: mktemp.c,v 1.30 2010/03/21 23:09:30 schwarze Exp $ */
5/* 5/*
6 * Copyright (c) 1987, 1993 6 * Copyright (c) 1996-1998, 2008 Theo de Raadt
7 * The Regents of the University of California. All rights reserved. 7 * Copyright (c) 1997, 2008-2009 Todd C. Miller
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Permission to use, copy, modify, and distribute this software for any
10 * modification, are permitted provided that the following conditions 10 * purpose with or without fee is hereby granted, provided that the above
11 * are met: 11 * copyright notice and this permission notice appear in all copies.
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 * 12 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */ 20 */
33 21
34/* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */ 22/* OPENBSD ORIGINAL: lib/libc/stdio/mktemp.c */
@@ -37,142 +25,117 @@
37 25
38#include <sys/types.h> 26#include <sys/types.h>
39#include <sys/stat.h> 27#include <sys/stat.h>
40 28#include <errno.h>
41#include <fcntl.h> 29#include <fcntl.h>
30#include <limits.h>
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
42#include <ctype.h> 34#include <ctype.h>
43#include <errno.h>
44#include <unistd.h> 35#include <unistd.h>
45 36
46#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) 37#if !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP)
47 38
48static int _gettemp(char *, int *, int, int); 39#define MKTEMP_NAME 0
40#define MKTEMP_FILE 1
41#define MKTEMP_DIR 2
49 42
50int 43#define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
51mkstemps(char *path, int slen) 44#define NUM_CHARS (sizeof(TEMPCHARS) - 1)
45
46static int
47mktemp_internal(char *path, int slen, int mode)
52{ 48{
49 char *start, *cp, *ep;
50 const char *tempchars = TEMPCHARS;
51 unsigned int r, tries;
52 struct stat sb;
53 size_t len;
53 int fd; 54 int fd;
54 55
55 return (_gettemp(path, &fd, 0, slen) ? fd : -1); 56 len = strlen(path);
57 if (len == 0 || slen < 0 || (size_t)slen >= len) {
58 errno = EINVAL;
59 return(-1);
60 }
61 ep = path + len - slen;
62
63 tries = 1;
64 for (start = ep; start > path && start[-1] == 'X'; start--) {
65 if (tries < INT_MAX / NUM_CHARS)
66 tries *= NUM_CHARS;
67 }
68 tries *= 2;
69
70 do {
71 for (cp = start; cp != ep; cp++) {
72 r = arc4random_uniform(NUM_CHARS);
73 *cp = tempchars[r];
74 }
75
76 switch (mode) {
77 case MKTEMP_NAME:
78 if (lstat(path, &sb) != 0)
79 return(errno == ENOENT ? 0 : -1);
80 break;
81 case MKTEMP_FILE:
82 fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR);
83 if (fd != -1 || errno != EEXIST)
84 return(fd);
85 break;
86 case MKTEMP_DIR:
87 if (mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR) == 0)
88 return(0);
89 if (errno != EEXIST)
90 return(-1);
91 break;
92 }
93 } while (--tries);
94
95 errno = EEXIST;
96 return(-1);
56} 97}
57 98
58int 99#if 0
59mkstemp(char *path) 100char *_mktemp(char *);
60{
61 int fd;
62 101
63 return (_gettemp(path, &fd, 0, 0) ? fd : -1); 102char *
103_mktemp(char *path)
104{
105 if (mktemp_internal(path, 0, MKTEMP_NAME) == -1)
106 return(NULL);
107 return(path);
64} 108}
65 109
110__warn_references(mktemp,
111 "warning: mktemp() possibly used unsafely; consider using mkstemp()");
112
66char * 113char *
67mkdtemp(char *path) 114mktemp(char *path)
68{ 115{
69 return(_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL); 116 return(_mktemp(path));
70} 117}
118#endif
71 119
72static int 120int
73_gettemp(path, doopen, domkdir, slen) 121mkstemp(char *path)
74 char *path;
75 register int *doopen;
76 int domkdir;
77 int slen;
78{ 122{
79 register char *start, *trv, *suffp; 123 return(mktemp_internal(path, 0, MKTEMP_FILE));
80 struct stat sbuf; 124}
81 int rval;
82 pid_t pid;
83 125
84 if (doopen && domkdir) { 126int
85 errno = EINVAL; 127mkstemps(char *path, int slen)
86 return(0); 128{
87 } 129 return(mktemp_internal(path, slen, MKTEMP_FILE));
130}
88 131
89 for (trv = path; *trv; ++trv) 132char *
90 ; 133mkdtemp(char *path)
91 trv -= slen; 134{
92 suffp = trv; 135 int error;
93 --trv;
94 if (trv < path) {
95 errno = EINVAL;
96 return (0);
97 }
98 pid = getpid();
99 while (trv >= path && *trv == 'X' && pid != 0) {
100 *trv-- = (pid % 10) + '0';
101 pid /= 10;
102 }
103 while (trv >= path && *trv == 'X') {
104 char c;
105
106 pid = (arc4random() & 0xffff) % (26+26);
107 if (pid < 26)
108 c = pid + 'A';
109 else
110 c = (pid - 26) + 'a';
111 *trv-- = c;
112 }
113 start = trv + 1;
114
115 /*
116 * check the target directory; if you have six X's and it
117 * doesn't exist this runs for a *very* long time.
118 */
119 if (doopen || domkdir) {
120 for (;; --trv) {
121 if (trv <= path)
122 break;
123 if (*trv == '/') {
124 *trv = '\0';
125 rval = stat(path, &sbuf);
126 *trv = '/';
127 if (rval != 0)
128 return(0);
129 if (!S_ISDIR(sbuf.st_mode)) {
130 errno = ENOTDIR;
131 return(0);
132 }
133 break;
134 }
135 }
136 }
137 136
138 for (;;) { 137 error = mktemp_internal(path, 0, MKTEMP_DIR);
139 if (doopen) { 138 return(error ? NULL : path);
140 if ((*doopen =
141 open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
142 return(1);
143 if (errno != EEXIST)
144 return(0);
145 } else if (domkdir) {
146 if (mkdir(path, 0700) == 0)
147 return(1);
148 if (errno != EEXIST)
149 return(0);
150 } else if (lstat(path, &sbuf))
151 return(errno == ENOENT ? 1 : 0);
152
153 /* tricky little algorithm for backward compatibility */
154 for (trv = start;;) {
155 if (!*trv)
156 return (0);
157 if (*trv == 'Z') {
158 if (trv == suffp)
159 return (0);
160 *trv++ = 'a';
161 } else {
162 if (isdigit(*trv))
163 *trv = 'a';
164 else if (*trv == 'z') /* inc from z to A */
165 *trv = 'A';
166 else {
167 if (trv == suffp)
168 return (0);
169 ++*trv;
170 }
171 break;
172 }
173 }
174 }
175 /*NOTREACHED*/
176} 139}
177 140
178#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */ 141#endif /* !defined(HAVE_MKDTEMP) || defined(HAVE_STRICT_MKSTEMP) */