Jump to content

Unique rand() directory names in temp folder


MutantJohn

Recommended Posts

Okay, so I'm kind of a PHP noob.

 

But out of context, for this site that I'm designing, it's easiest if I make a directory in the temporary folder PHP uses. In my case, /tmp/ because I am on Linux.

 

I want to use rand() to generate a random name for the page. But I then realized something, rand() could produce duplicates. How do I prevent PHP from trying to make the same directory at the same time? I know there are functions that will check if a file exists but I'm assuming it'll fail if that directory is currently being created, right?

 

How do I assure thread safety?

 

I willing to change my idea and not use rand(). Is there a way to get a unique key for each anonymous user on my site?

Link to comment
Share on other sites

What you need to do is use a good random number generator. The rand() function is indeed poor and may produce duplicate results. But if you use the generator of your operating system, you'll get high-quality output and don't have to worry about any collisions.

 

There are several different interfaces:

  • If you have the Mcrypt extension, use mcrypt_create_iv()

  • If you have the OpenSSL extension, use openssl_random_pseudo_bytes()

  • If you have neither, you need to use the low-level API of your operating system. On Unix, there's the /dev/(u)random device. On Windows, it's a bit more complicated.

16 random bytes are enough to make the risk of collision neglectable (so no need for any checks). You then have to encode the raw bytes as hex digits or whatever you like best. For example:

<?php

$rand_bytes = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
$rand_hex = bin2hex($rand_bytes);

echo $rand_hex;

A lot of people will tell you that you should use things like mt_rand() or uniqid(). Don't. While those functions are slightly better than rand(), they're still poor compared to a proper generator like /dev/urandom.

Edited by Jacques1
Link to comment
Share on other sites

Hey, that's a much better idea. 

 

I also read up on flock() but I couldn't get it to work. Just using PHP's native rand() function, I was planning on doing something like this :

$outdir = "/tmp/";

$fp = fopen("/tmp", "w+");

// this works
if (is_readable("/tmp"))
    echo "Can read directory.<br />\n";

// this works
if (is_writable("/tmp"))
    echo "Can write directory.<br />\n";

// this always returns false
if (flock($fp, LOCK_EX))
{
    // initial hash
    $dir_hash = rand();

    // if the subdirectory/file exists, loop
    while (file_exists("/tmp/".$dir_hash))
    {
        $dir_hash = rand();
    }

    // append random number
    $outdir .= $dir_hash;

    // release lock
    flock($fp, LOCK_UN);

}
else
    echo "Was unable to lock directory <br />\n";

fclose($fp);

echo $outdir."<br />\n";
Link to comment
Share on other sites

This makes no sense. I'm not sure if it's even possible to get an exclusive lock on a directory (Google suggests otherwise), but in any case, you're missing two things:

  • The /tmp folder is used by lots and lots of processes, not just your PHP application. Making them all wait until you've created your user directories is a terrible idea.
  • Locks obtained through flock() are only advisory, which means other applications are free to ignore them and overwrite your folders nonetheless. So the idea doesn't even work out.

Like I said, proper randomness will make all checks and while loops unnecessary. But even if you're super-paranoid and want to rule out any chance of a collision, you still wouldn't do those checks. Simply call mkdir() and see if it failed. It does not overwrite existing folders but will throw an error instead.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.