Why is it that is_regular_file
function that is part of std::filesystem
reports true for a symbolic link? I have looked at the documentation for the call and can't find the reason and the examples on cppreference exhibit the same behaviour.
As an example, if we look at the binary pidof
; It exists as /usr/sbin/pidof
and correctly labelled as a symbolic link as shown here by 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
If we follow the link and run stat
on it:
[@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
If we run the following code:
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;
}
The code always prints "Regular File" despite the path being a symbolic link. If I switch the cases around (have is_symlink
as the first check), it reports correctly that it is a symlink. What is interesting too is that if I use a std::filesystem::status
objects instead of the std::filesystem::path
, it never reports a symlink regardless of the order.
Is there an explanation for this behaviour that I'm maybe overlooking?
As documented on cppreference, the function
bool std::filesystem::is_regular_file(const std::filesystem::path& p);
is equivalent to
std::filesystem::is_regular_file(std::filesystem::status(p))
where the std::filesystem::status
function
Determines the type and attributes of the filesystem object identified by
p
as if by POSIXstat
(symlinks are followed to their targets).
Whereas the std::filesystem::symlink_status
function
is the same as the
std::filesystem::status
function, except that the behavior is as if the POSIXlstat
is used (symlinks are not followed).
Thus, the correct usage in your case would be:
if (std::filesystem::is_regular_file(std::filesystem::symlink_status(fsBin)))
{
// ...
}