1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
24 */
25
26 /* Copyright (c) 1988 AT&T */
27 /* All Rights Reserved */
28
29 /*
30 * mktemp() expects a string with up to six trailing 'X's.
31 * These will be overlaid with letters, digits and symbols from
32 * the portable filename character set. If every combination thus
33 * inserted leads to an existing file name, the string is shortened
34 * to length zero and a pointer to a null string is returned.
35 *
36 * The guarantee made by mktime() to the caller is that the
37 * generated file name string will not match the string
38 * produced by any other concurrent process using mktemp().
39 * To guarantee uniqueness across the process-id space,
40 * the process-id of the caller is encoded into the string.
41 * To allow repeated calls within the same process to generate
42 * different strings on each call, a sequence number is encoded
43 * into the string along with process-id.
44 *
45 * The encoding is performed using radix-64 (6 bits per character),
46 * with 64 characters taken from the portable file name character set.
47 * This allows the six X's to be a representation of a 36-bit integer
48 * composed of bit fields:
49 * ( pid | seq )
50 * where the process-id occupies the high-order bits and the sequence
51 * number occupies the low-order bits. The size of the pid field is
52 * not fixed at the traditional 15 bits (MAXPID = 30000); the system
53 * now allows a larger process-id space and MAXPID is obtained from
54 * the system with a call to sysconf(_SC_MAXPID).
55 *
56 * mktime() should fail if fewer than six X's are presented to it.
57 * However, this has been traditionally accepted and is preserved
58 * in the present code. The consequence is that the 36-bit integer
59 * is reduced to a (6*N)-bit integer, where N is the number of X's.
60 * mktime() fails immediately if the resulting integer is not large
61 * enough to contain MAXPID.
62 *
63 * In an attempt to confuse and thwart hackers, the starting
64 * sequence number is randomized using the current time.
65 */
66
67 #pragma weak _mktemp = mktemp
68
69 #define XCNT 6
70
71 #include "lint.h"
72 #include "mtlib.h"
73 #include <sys/types.h>
74 #include <string.h>
75 #include <unistd.h>
76 #include <thread.h>
77 #include <synch.h>
78 #include <sys/stat.h>
79 #include <errno.h>
80 #include <sys/time.h>
81 #include <stdlib.h>
82 #include <stdio.h>
83 #include <sys/param.h>
84
85 /*
86 * 64-bit digits, must be from the POSIX "portable file name character set".
87 */
88 static char
89 chars[64] = {
90 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
91 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
92 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
93 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
94 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '_',
95 };
96
97 char *
libc_mktemps(char * as,int slen)98 libc_mktemps(char *as, int slen)
99 {
100 /* statics are protected by this static mutex */
101 static mutex_t mktemp_lock = DEFAULTMUTEX;
102 static int pidshift = 0;
103 static int previous_try = 0;
104 static pid_t previous_pid = 0;
105 static int previous_xcnt = XCNT;
106
107 pid_t pid;
108 int try;
109 int tryshift;
110 int max_try;
111 char *s;
112 char *first_x;
113 int len;
114 uint_t xcnt;
115 struct stat64 buf;
116
117 if (as == NULL || *as == '\0') /* If the string passed is null then */
118 return (as); /* a pointer to a null string is returned. */
119
120 lmutex_lock(&mktemp_lock);
121
122 pid = getpid();
123 if (pid != previous_pid) { /* first time or first after fork() */
124 /*
125 * Randomize the starting sequence number in
126 * an attempt to confuse and thwart hackers.
127 * Use the low 12 bits of the time in milliseconds.
128 */
129 struct timeval tm;
130
131 (void) gettimeofday(&tm, NULL);
132 previous_try = (tm.tv_sec * 1000 + tm.tv_usec / 1000) & 0xfff;
133 previous_pid = pid;
134 previous_xcnt = XCNT;
135 }
136
137 /* for all possible values of pid, 0 <= pid < (1 << pidshift) */
138 if (pidshift == 0) /* one-time initialization */
139 pidshift = fls((uint_t)MAXPID); /* high bit number */
140
141 /* count the X's */
142 xcnt = 0;
143 len = (int)strlen(as);
144 if (slen >= len || slen < 0)
145 goto fail;
146 len -= slen;
147 s = as + (len - 1);
148 while ((len != 0) && (xcnt < XCNT) && (*s == 'X')) {
149 xcnt++;
150 len--;
151 --s;
152 }
153 first_x = s + 1; /* Remember pointer to the first X */
154
155 /* fail if we don't have enough X's to represent MAXPID */
156 if ((tryshift = xcnt * 6 - pidshift) < 0) {
157 /*
158 * Some broken programs call mktemp() repeatedly,
159 * passing the same string without reinserting the X's.
160 * Check to see if this is such a call by testing
161 * the trailing characters of the string for a
162 * match with the process-id.
163 */
164 uint64_t xpid = 0; /* reconstructed pid */
165
166 s = as + len;
167 for (xcnt = previous_xcnt; xcnt && s > as; xcnt--) {
168 int c;
169 int i;
170
171 c = *--s;
172 for (i = 0; i < 64; i++)
173 if (c == chars[i])
174 break;
175 if (i == 64)
176 goto fail;
177 xpid = xpid * 64 + i;
178 }
179 xpid >>= (previous_xcnt * 6 - pidshift);
180 xpid &= ((1 << pidshift) - 1);
181
182 if (xpid == pid &&
183 lstat64(as, &buf) == -1 && errno == ENOENT) {
184 lmutex_unlock(&mktemp_lock);
185 return (as);
186 }
187
188 goto fail;
189 }
190
191 /* we can try sequence numbers in the range 0 <= try < max_try */
192 max_try = 1 << tryshift;
193 if (previous_try >= max_try)
194 previous_try = 0;
195
196 try = previous_try;
197 for (;;) {
198 /* num is up to a 36-bit integer ... */
199 uint64_t num = ((uint64_t)pid << tryshift) + (uint64_t)try;
200 int i;
201
202 /* ... which we represent backwards in base 64 */
203 for (i = 0, s = first_x; i < xcnt; i++) {
204 *s++ = chars[num & 077];
205 num >>= 6;
206 }
207
208 if (lstat64(as, &buf) == -1) {
209 if (errno != ENOENT)
210 break; /* unrecoverable error */
211 /* remember where we left off for the next call */
212 previous_try = try + 1;
213 previous_xcnt = xcnt;
214 lmutex_unlock(&mktemp_lock);
215 return (as);
216 }
217
218 if (++try == max_try)
219 try = 0;
220 if (try == previous_try)
221 break;
222 }
223
224 fail:
225 lmutex_unlock(&mktemp_lock);
226 *as = '\0';
227 return (as);
228 }
229
230 char *
mktemp(char * template)231 mktemp(char *template)
232 {
233 return (libc_mktemps(template, 0));
234 }
235