Search code examples
phplinuxfile-iofilesystemsbsd

How to guarantee a specified file is a device on BSD/Linux from PHP?


While working on a project that reads from /dev/urandom to generate random bytes, it was suggested that I check to make sure that /dev/urandom is a device not just a file.

The most straightforward way seems to be something like:

/**
 * Is the given file a device?
 * 
 * @param string|resource $file
 * @return boolean
 */
function is_device($file)
{
    if (is_resource($file)) {
        $stat = fstat($file);            
    } elseif (is_readable($file) && !is_link($file)) {
        $stat = stat($file);
    } else {
        return false;
    }
    return $stat['rdev'] !== 0;
}

My question is two-fold:

  1. Is this the best way to check that this file is a device?
  2. Are there circumstances where this $stat['rdev'] !== 0 check can fail?

Important: The solution I need must be in PHP without depending on any PECL extensions or custom C code. The project is a pure PHP 5 polyfill of PHP 7's random_bytes() and random_int() functions and is intended to be installable in anyone else's PHP 5 projects by Composer.


Solution

  • well, you can use filetype().

    if you do a fast ll on urandom, you will see:

    ll /dev/urandom 
    crw-rw-rw- 1 root root 1, 9 Jul 26 17:38 /dev/urandom
    

    that 'c' at the beginnng means it's a "character" filetype. you can check out all the different filetypes here:

    https://en.wikipedia.org/wiki/Unix_file_types

    this means that if you run

    filetype("/dev/urandom");
    

    you will get "char" back, meaning character filetype. that should do the trick.