Actually, the S_IFMT can be used as both, a constant and a function, depending on whether you pass in parameters:
void
S_IFMT(...)
PREINIT:
dXSTARG;
PPCODE:
PUSHu(items ? (SvUV(ST(0)) & S_IFMT) : S_IFMT);
It seems to return the AND-ed value from stat():
#!/usr/bin/env perl
use strict;
use warnings;
use Fcntl qw[];
printf "%08x\n", (stat("/tmp"))[2];
printf "%08x\n", (stat("/etc/passwd"))[2];
printf "%08x\n", Fcntl::S_IFMT( (stat("/tmp"))[2] );
printf "%08x\n", Fcntl::S_IFMT( (stat("/etc/passwd"))[2] );
printf "%08x\n", Fcntl::S_IFMT();
__END__
000043ff
000081a4
00004000
00008000
0000f000
I think the intended usage is to compare against identity, just like the GNU usage does, and to use lstat if you want to know about the link instead of the link target:
#!/usr/bin/env perl
use strict;
use warnings;
use Fcntl qw[];
for my $file ('/tmp/testlink', '/etc/passwd', '/etc') {
print "--- $file is link: ", -l $file, "\n";
my $mode = (stat($file))[2];
my $lmode = (lstat($file))[2];
printf "mode: %016b\n", $mode;
printf "lmode: %016b\n", $lmode;
printf "S_IFMT(): %016b\n", Fcntl::S_IFMT($lmode);
printf "S_IFMT: %016b\n", Fcntl::S_IFMT() & $lmode;
printf "S_IFMT: %016b\n", Fcntl::S_IFMT();
printf "S_IFLNK: %016b\n", Fcntl::S_IFLNK();
printf "S_IFLNK: %016b\n", (Fcntl::S_IFLNK() & Fcntl::S_IFMT() & $lmo
+de) == Fcntl::S_IFLNK() ;
printf "S_ISLNK():%016b\n", Fcntl::S_ISLNK($lmode);
print "---\n";
}
__END__
--- /tmp/testlink is link: 1
mode: 0100001111111111
lmode: 1010000111111111
S_IFMT(): 1010000000000000
S_IFMT: 1010000000000000
S_IFMT: 1111000000000000
S_IFLNK: 1010000000000000
S_IFLNK: 0000000000000001
S_ISLNK():0000000000000001
---
--- /etc/passwd is link:
mode: 1000000110100100
lmode: 1000000110100100
S_IFMT(): 1000000000000000
S_IFMT: 1000000000000000
S_IFMT: 1111000000000000
S_IFLNK: 1010000000000000
S_IFLNK: 0000000000000000
S_ISLNK():0000000000000000
---
--- /etc is link:
mode: 0100000111101101
lmode: 0100000111101101
S_IFMT(): 0100000000000000
S_IFMT: 0100000000000000
S_IFMT: 1111000000000000
S_IFLNK: 1010000000000000
S_IFLNK: 0000000000000000
S_ISLNK():0000000000000000
---
|