如何保证指定的文件是来自PHP的BSD/Linux设备?
在处理从如何保证指定的文件是来自PHP的BSD/Linux设备?,php,linux,file-io,filesystems,bsd,Php,Linux,File Io,Filesystems,Bsd,在处理从/dev/uradom读取以生成随机字节的项目时,建议我检查以确保/dev/uradom不仅仅是一个文件,而是一个设备 最直接的方法似乎是: /** * Is the given file a device? * * @param string|resource $file * @return boolean */ function is_device($file) { if (is_resource($file)) { $stat = fstat($
/dev/uradom
读取以生成随机字节的项目时,建议我检查以确保/dev/uradom
不仅仅是一个文件,而是一个设备
最直接的方法似乎是:
/**
* 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检查是否可能失败
ll /dev/urandom
crw-rw-rw- 1 root root 1, 9 Jul 26 17:38 /dev/urandom
开头的“c”表示它是一个“字符”文件类型。您可以在此处查看所有不同的文件类型:
这意味着如果你跑步
filetype("/dev/urandom");
您将返回“char”,意思是字符文件类型。这应该可以解决问题。更新 我最初的解决方案只是重新实现了
filetype($filepath)==“char”
,因此filetype()
似乎是您唯一需要的
根据@frymaster的回答 我查看了PHP的
stat()
函数的工作原理,查找“char”并找到了它
结合and和a的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));
}
函数是\u设备($filepath)
{
如果(!file_存在($filepath)或(stripos(PHP_OS,'Linux')==false&&stripos(PHP_OS,'BSD')==false))
{
返回false;
}
$mode=stat($filepath)['mode'];
返回(020000==($mode&0170000));
}
在我的Linux系统上工作
更新(回答第二个问题)
是,
stat($file)['rdev']!=0
可能会失败。根据我的发现,如果操作系统不支持,它可能返回-1,而即使是正值也可能指向不同的设备类型。它的值似乎也依赖于操作系统。“您应该花时间研究openssl_random_pseudo_bytes()。”。所讨论的项目是PHP7的random_bytes()
和random_int()
函数的polyfill。我目前的非正式立场是,“TOCTOU问题和文件描述符耗尽攻击超出范围。如果您的文件系统被破坏,您的PHP web应用程序将无法拯救您。”libsodum似乎做了一些非常类似的事情:这就是filetype()
返回“char”时所做的事情:)刚刚更新了答案。。。这与@frymaster所说的非常相似。不客气。:)我也这么做了——我以前不知道这些,事实上也不知道PHP有一个filetype()
函数,还以为你在谈论别的东西。然而,从你的答案中提取了另一条线索,并将其作为一个完整的循环——集体思考在工作中!:D