usr/src/lib/libc/port/gen/mktemp.c
author raf
Mon, 10 Apr 2006 12:27:38 -0700
changeset 1778 6357a59054f7
parent 1475 0c7070c5774f
child 6812 febeba71273d
permissions -rw-r--r--
6404383 select() behaviour changed in Solaris 10, breaking binary compatibility
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
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
/*
1475
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
    22
 * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Use is subject to license terms.
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
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
/*	Copyright (c) 1988 AT&T	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*	  All Rights Reserved  	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 *	mktemp() expects a string with up to six trailing 'X's.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *	These will be overlaid with letters, digits and symbols from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 *	the portable filename character set.  If every combination thus
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 *	inserted leads to an existing file name, the string is shortened
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 *	to length zero and a pointer to a null string is returned.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 *	The guarantee made by mktime() to the caller is that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 *	generated file name string will not match the string
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 *	produced by any other concurrent process using mktemp().
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *	To guarantee uniqueness across the process-id space,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 *	the process-id of the caller is encoded into the string.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 *	To allow repeated calls within the same process to generate
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 *	different strings on each call, a sequence number is encoded
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *	into the string along with process-id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 *	The encoding is performed using radix-64 (6 bits per character),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 *	with 64 characters taken from the portable file name character set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 *	This allows the six X's to be a representation of a 36-bit integer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 *	composed of bit fields:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
 *		( pid | seq )
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
 *	where the process-id occupies the high-order bits and the sequence
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
 *	number occupies the low-order bits.  The size of the pid field is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
 *	not fixed at the traditional 15 bits (MAXPID = 30000); the system
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
 *	now allows a larger process-id space and MAXPID is obtained from
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
 *	the system with a call to sysconf(_SC_MAXPID).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
 *	mktime() should fail if fewer than six X's are presented to it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
 *	However, this has been traditionally accepted and is preserved
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
 *	in the present code.  The consequence is that the 36-bit integer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
 *	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
    63
 *	mktime() fails immediately if the resulting integer is not large
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 *	enough to contain MAXPID.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
 *	In an attempt to confuse and thwart hackers, the starting
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
 *	sequence number is randomized using the current time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
#define	XCNT  6
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
#pragma weak mktemp = _mktemp
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
#include "synonyms.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
#include "mtlib.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
#include <unistd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
#include <thread.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
#include <synch.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
#include <sys/time.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
#include <stdio.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 * 64-bit digits, must be from the POSIX "portable file name character set".
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
static char
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
chars[64] = {
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
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
	'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '_',
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
 * Find highest one bit set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
 * Returns bit number of highest bit that is set.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
 * Low order bit is number 0, high order bit is number 31.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
highbit(uint_t i)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
	int h = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
	if (i & 0xffff0000)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
		h += 16, i >>= 16;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
	if (i & 0xff00)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
		h += 8, i >>= 8;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
	if (i & 0xf0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
		h += 4, i >>= 4;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
	if (i & 0xc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
		h += 2, i >>= 2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
	if (i & 0x2)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
		h += 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
	return (h);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
char *
1475
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   123
libc_mktemps(char *as, int slen)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
	/* statics are protected by this static mutex */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
	static mutex_t	mktemp_lock = DEFAULTMUTEX;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
	static int	pidshift = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
	static int	previous_try = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
	static pid_t	previous_pid = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
	static int	previous_xcnt = XCNT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
	pid_t		pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
	int		try;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
	int		tryshift;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	int		max_try;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	char		*s;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	char		*first_x;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	int		len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	uint_t		xcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	struct stat64	buf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
	if (as == NULL || *as == '\0')	/* If the string passed is null then */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
		return (as);	/* a pointer to a null string is returned. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	lmutex_lock(&mktemp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	pid = getpid();
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	if (pid != previous_pid) {	/* first time or first after fork() */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
		 * Randomize the starting sequence number in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
		 * an attempt to confuse and thwart hackers.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
		 * Use the low 12 bits of the time in milliseconds.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
		struct timeval tm;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
		(void) gettimeofday(&tm, NULL);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
		previous_try = (tm.tv_sec * 1000 + tm.tv_usec / 1000) & 0xfff;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
		previous_pid = pid;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
		previous_xcnt = XCNT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
	/* for all possible values of pid, 0 <= pid < (1 << pidshift) */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	if (pidshift == 0)	/* one-time initialization */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
		pidshift = highbit((uint_t)MAXPID) + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	/* count the X's */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	xcnt = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	len = (int)strlen(as);
1475
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   169
	if (slen >= len || slen < 0)
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   170
		goto fail;
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   171
	len -= slen;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	s = as + (len - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	while ((len != 0) && (xcnt < XCNT) && (*s == 'X')) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
		xcnt++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
		len--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
		--s;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
	first_x = s + 1;	/* Remember pointer to the first X */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	/* fail if we don't have enough X's to represent MAXPID */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	if ((tryshift = xcnt * 6 - pidshift) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
		 * Some broken programs call mktemp() repeatedly,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
		 * passing the same string without reinserting the X's.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
		 * Check to see if this is such a call by testing
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
		 * the trailing characters of the string for a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
		 * match with the process-id.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
		uint64_t xpid = 0;		/* reconstructed pid */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
		s = as + len;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
		for (xcnt = previous_xcnt; xcnt && s > as; xcnt--) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
			int c;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
			int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
			c = *--s;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
			for (i = 0; i < 64; i++)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
				if (c == chars[i])
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
					break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
			if (i == 64)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
				goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
			xpid = xpid * 64 + i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
		xpid >>= (previous_xcnt * 6 - pidshift);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
		xpid &= ((1 << pidshift) - 1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
		if (xpid == pid &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
		    lstat64(as, &buf) == -1 && errno == ENOENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
			lmutex_unlock(&mktemp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
			return (as);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
	/* we can try sequence numbers in the range 0 <= try < max_try */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
	max_try = 1 << tryshift;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
	if (previous_try >= max_try)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
		previous_try = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
	try = previous_try;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
	for (;;) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
		/* num is up to a 36-bit integer ... */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
		uint64_t num = ((uint64_t)pid << tryshift) + (uint64_t)try;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
		int i;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
		/* ... which we represent backwards in base 64 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
		for (i = 0, s = first_x; i < xcnt; i++) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
			*s++ = chars[num & 077];
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
			num >>= 6;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
		if (lstat64(as, &buf) == -1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
			if (errno != ENOENT)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
				break;		/* unrecoverable error */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
			/* remember where we left off for the next call */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
			previous_try = try + 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
			previous_xcnt = xcnt;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
			lmutex_unlock(&mktemp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
			return (as);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
		if (++try == max_try)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
			try = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
		if (try == previous_try)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
	lmutex_unlock(&mktemp_lock);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
	*as = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
	return (as);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
}
1475
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   254
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   255
char *
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   256
mktemp(char *template)
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   257
{
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   258
	return (libc_mktemps(template, 0));
0c7070c5774f PSARC/2006/107 mkstemps(3C)/mkdtemp(3C)
casper
parents: 0
diff changeset
   259
}