Increase the size of the mktemp() filename space by dropping the PID from

the encoding and using the character set [a-zA-Z0-9]. This gives a total
of 62^6 = 56800235584 possible temporary filenames for the usual default
invocation of 6 X's (compared to as few as 52 possibilities for the
previous algorithm where up to 5 characters were wasted by the PID).

Update some apparently bitrotten comments to reflect reality.

Audited by:	eivind, freebsd-audit
Reviewed by:	freebsd-current (a while ago)
Originally submitted by:	Peter Jeremy <Peter.Jeremy@alcatel.com.au>
This commit is contained in:
kris 2000-11-10 23:27:55 +00:00
parent fd17851060
commit 919c3e124e

View File

@ -45,6 +45,7 @@ static const char rcsid[] =
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
@ -52,6 +53,9 @@ char *_mktemp __P((char *));
static int _gettemp __P((char *, int *, int, int));
static const unsigned char padchar[] =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
int
mkstemps(path, slen)
char *path;
@ -103,8 +107,10 @@ _gettemp(path, doopen, domkdir, slen)
int slen;
{
register char *start, *trv, *suffp;
char *pad;
struct stat sbuf;
int pid, rval;
int rval;
uint32_t rand;
if (doopen && domkdir) {
errno = EINVAL;
@ -120,26 +126,16 @@ _gettemp(path, doopen, domkdir, slen)
errno = EINVAL;
return (0);
}
pid = getpid();
while (*trv == 'X' && pid != 0) {
*trv-- = (pid % 10) + '0';
pid /= 10;
}
while (*trv == 'X') {
char c;
pid = (arc4random() & 0xffff) % (26+26);
if (pid < 26)
c = pid + 'A';
else
c = (pid - 26) + 'a';
*trv-- = c;
/* Fill space with random characters */
while (*trv == 'X') {
rand = arc4random() % (sizeof(padchar) - 1);
*trv-- = padchar[rand];
}
start = trv + 1;
/*
* check the target directory; if you have six X's and it
* doesn't exist this runs for a *very* long time.
* check the target directory.
*/
if (doopen || domkdir) {
for (;; --trv) {
@ -175,19 +171,15 @@ _gettemp(path, doopen, domkdir, slen)
} else if (lstat(path, &sbuf))
return(errno == ENOENT ? 1 : 0);
/* tricky little algorithm for backward compatibility */
/* If we have a collision, cycle through the space of filenames */
for (trv = start;;) {
if (*trv == '\0' || trv == suffp)
return(0);
if (*trv == 'Z')
*trv++ = 'a';
pad = strchr(padchar, *trv);
if (pad == NULL || !*++pad)
*trv++ = padchar[0];
else {
if (isdigit((unsigned char)*trv))
*trv = 'a';
else if (*trv == 'z') /* inc from z to A */
*trv = 'A';
else
++*trv;
*trv++ = *pad;
break;
}
}