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