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:
$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.
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.
Update
My original solution turned out to be just a re-implementation of filetype($filepath) === 'char'
, so filetype()
seems to be the only thing you need.
Based on @frymaster's answer ...
I looked at how PHP's stat()
function works, looking for "char" and found this.
Combined with the stat(2) manual for both Linux and FreeBSD, as well as a comment on PHP's manual for stat(), I came up with the following:
function is_device($filepath) { if ( ! file_exists($filepath) OR (stripos(PHP_OS, 'Linux') === false && stripos(PHP_OS, 'BSD') === false)) { return false; } $mode = stat($filepath)['mode']; return (020000 === ($mode & 0170000)); }
Works on my Linux system.
Update (to answer the second question)
Yes, stat($file)['rdev'] !== 0
can fail. From what I found, it may return -1 if not supported by the OS, while even a positive value may point at a different device type. Its values also appear to be OS-dependent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With