为什么 is_regular_file 对于符号链接报告为 true

joh*_*ohn 5 c++ symlink std-filesystem

为什么报告is_regular_file中的那个函数std::filesystem对于符号链接来说是正确的?我查看了该调用的文档,但找不到原因,并且 cppreference 上的示例表现出相同的行为。

举个例子,如果我们看一下二进制文件pidof;它作为符号链接存在/usr/sbin/pidof并正确标记为符号链接,如下所示stat

[@rhel9 ~]$ stat /usr/sbin/pidof 
  File: /usr/sbin/pidof -> /usr/bin/pidof
  Size: 14          Blocks: 0          IO Block: 4096   symbolic link
Device: fd00h/64768d    Inode: 34952482    Links: 1
Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:bin_t:s0
Access: 2024-02-05 15:46:24.124158991 +0000
Modify: 2023-01-28 09:40:21.000000000 +0000
Change: 2023-05-09 17:34:59.432002380 +0100
 Birth: 2023-05-09 17:34:59.432002380 +0100
Run Code Online (Sandbox Code Playgroud)

如果我们点击链接并运行stat它:

[@rhel9 ~]$ stat /usr/bin/pidof 
  File: /usr/bin/pidof
  Size: 23760       Blocks: 48         IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 18153014    Links: 1
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Context: system_u:object_r:bin_t:s0
Access: 2024-02-02 15:12:41.804334284 +0000
Modify: 2023-01-28 09:40:21.000000000 +0000
Change: 2023-05-09 17:34:59.418002380 +0100
 Birth: 2023-05-09 17:34:59.417002380 +0100
Run Code Online (Sandbox Code Playgroud)

如果我们运行以下代码:

const std::filesystem::path fsBin("/usr/sbin/pidof");
if (true == std::filesystem::is_regular_file(fsBin))
{
    std::cout << "Regular File" << std::endl;
}
else if(true == std::filesystem::is_symlink(fsBin))
{
    std::cout << "Symbolic Link" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

尽管路径是符号链接,但代码始终打印“常规文件”。如果我切换大小写(作为is_symlink第一次检查),它会正确报告它是符号链接。同样有趣的是,如果我使用对象std::filesystem::status而不是对象std::filesystem::path,则无论顺序如何,它都不会报告符号链接。

对于我可能忽略的这种行为有什么解释吗?

hea*_*run 7

如cppreference上所述,该函数

bool std::filesystem::is_regular_file(const std::filesystem::path& p);
Run Code Online (Sandbox Code Playgroud)

相当于

std::filesystem::is_regular_file(std::filesystem::status(p))
Run Code Online (Sandbox Code Playgroud)

其中std::filesystem::status函数

p确定由 POSIX标识的文件系统对象的类型和属性stat符号链接后面是其目标)。

std::filesystem::symlink_status函数

与该函数相同std::filesystem::status,但行为就像lstat使用 POSIX(不遵循符号链接)。

因此,您的情况的正确用法是:

if (std::filesystem::is_regular_file(std::filesystem::symlink_status(fsBin)))
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)