如何保证指定文件是PHPBSD/Linux上的设备?
How to guarantee a specified file is a device on BSD/Linux from PHP?
在处理从 /dev/urandom
读取以生成随机字节的项目时,有人建议我检查以确保 /dev/urandom
是一个设备而不仅仅是一个文件。
最直接的方法似乎是这样的:
/**
* 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;
}
我的问题有两个:
- 这是检查此文件是否为设备的最佳方法吗?
- 是否存在此
$stat['rdev'] !== 0
检查可能失败的情况?
重要:我需要的解决方案必须在 PHP 中,而不依赖于任何 PECL 扩展或自定义 C 代码。该项目是 a pure PHP 5 polyfill of PHP 7's random_bytes()
and random_int()
functions,旨在由 Composer 安装在其他任何人的 PHP 5 个项目中。
嗯,你可以使用 filetype()。
如果你在 urandom 上做一个快速 ll,你会看到:
ll /dev/urandom
crw-rw-rw- 1 root root 1, 9 Jul 26 17:38 /dev/urandom
开头的 'c' 表示它是 "character" 文件类型。您可以在此处查看所有不同的文件类型:
https://en.wikipedia.org/wiki/Unix_file_types
这意味着如果你 运行
filetype("/dev/urandom");
你会得到 "char" 返回,意思是字符文件类型。 应该 做到这一点。
更新
我最初的解决方案原来只是 filetype($filepath) === 'char'
的重新实现,所以 filetype()
似乎是您唯一需要的。
基于@frymaster 的回答...
我查看了 PHP 的 stat()
函数是如何工作的,寻找 "char" 并找到了 this。
结合 Linux and FreeBSD, as well as a comment on PHP's manual for stat() 的 stat(2) 手册,我得出以下结论:
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));
}
适用于我的 Linux 系统。
更新(回答第二个问题)
是的,stat($file)['rdev'] !== 0
可能会失败。根据我的发现,如果 OS 不支持,它可能 return -1,而即使是正值也可能指向不同的设备类型。它的值似乎也依赖于 OS。
在处理从 /dev/urandom
读取以生成随机字节的项目时,有人建议我检查以确保 /dev/urandom
是一个设备而不仅仅是一个文件。
最直接的方法似乎是这样的:
/**
* 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;
}
我的问题有两个:
- 这是检查此文件是否为设备的最佳方法吗?
- 是否存在此
$stat['rdev'] !== 0
检查可能失败的情况?
重要:我需要的解决方案必须在 PHP 中,而不依赖于任何 PECL 扩展或自定义 C 代码。该项目是 a pure PHP 5 polyfill of PHP 7's random_bytes()
and random_int()
functions,旨在由 Composer 安装在其他任何人的 PHP 5 个项目中。
嗯,你可以使用 filetype()。
如果你在 urandom 上做一个快速 ll,你会看到:
ll /dev/urandom
crw-rw-rw- 1 root root 1, 9 Jul 26 17:38 /dev/urandom
开头的 'c' 表示它是 "character" 文件类型。您可以在此处查看所有不同的文件类型:
https://en.wikipedia.org/wiki/Unix_file_types
这意味着如果你 运行
filetype("/dev/urandom");
你会得到 "char" 返回,意思是字符文件类型。 应该 做到这一点。
更新
我最初的解决方案原来只是 filetype($filepath) === 'char'
的重新实现,所以 filetype()
似乎是您唯一需要的。
基于@frymaster 的回答...
我查看了 PHP 的 stat()
函数是如何工作的,寻找 "char" 并找到了 this。
结合 Linux and FreeBSD, as well as a comment on PHP's manual for stat() 的 stat(2) 手册,我得出以下结论:
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)); }
适用于我的 Linux 系统。
更新(回答第二个问题)
是的,stat($file)['rdev'] !== 0
可能会失败。根据我的发现,如果 OS 不支持,它可能 return -1,而即使是正值也可能指向不同的设备类型。它的值似乎也依赖于 OS。