You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fcntl provides a S_ISENFMT function that makes no sense. If it exists at all (depends on whether your platform defines S_ENFMT), it always returns false. It should just be removed from Fcntl (and not mentioned in perlfunc/stat).
Background
If you want to get the type of a file in C, you get its st_mode from stat or lstat, apply the S_IFMT mask (filtering out the non-type bits), then compare the result to one of the other S_IF* constants:
if ((x.st_mode&S_IFMT) ==S_IFREG) {
// it's a regular file
}
This is annoying enough that C provides additional S_IS* helper macros, one for each type of file:
if (S_ISREG(x.st_mode)) {
// it's a regular file
}
Perl's Fcntl module provides the same interface (mostly) with subroutines:
use Fcntl qw(:mode);
if (($mode & S_IFMT) == S_IFREG) {
# it's a regular file
}
if (S_ISREG($mode)) {
# it's a regular file
}
However, Fcntl also defines a S_ISENFMT function that doesn't correspond to anything in nature (C).
On some platforms, there is an S_ENFMT ("enforcement of file locks") constant, which indicates that record locks placed on this file are mandatory, not advisory. It typically shares its value with S_ISGID ("set group id") because the combination of a non-executable file with the setgid bit set is not otherwise meaningful. Note that this bit is part of the file permissions, not of its type! That's why there is no corresponding S_ISENFMT macro for it.
Perl's S_ISENFMT was originally added in ca6e1c2 (presumably by mistake), defined as:
Finally, S_ENFMT is a constant that actually exists (on some platforms)! So now it is possible to actually use S_ISENFMT without getting a runtime error. Unfortunately the code still makes no sense: $_[0] & _S_IFMT extracts the file type bits, but S_ENFMT is not a file type, so this comparison always returns false.
In 87eca6e, the whole logic was moved from Perl to XS code, but it still fails the same way: It always returns false at runtime. (If your platform defines S_ENFMT, that is; otherwise S_ISENFMT just isn't defined at all.)
Steps to Reproduce
$ perl -e 'use Fcntl qw(S_ISENFMT)'
$
Expected behavior
$ perl -e 'use Fcntl qw(S_ISENFMT)'
"S_ISENFMT" is not exported by the Fcntl module
Can't continue after import errors at -e line 1.
BEGIN failed--compilation aborted at -e line 1.
The text was updated successfully, but these errors were encountered:
S_ISENFMT($mode) has no equivalent C macro. It was implemented (in XS)
as the equivalent of `($mode & S_IFMT) == S_ENFMT`, which is always
false because S_ENFMT is not a file type and thus not covered by the
S_IFMT mask.
(See commits ca6e1c2, 0e6f150, 0f68039, fb59364, 87eca6e for the history
of this function, which has always been broken in various ways ever
since it was added in 2000.)
FixesPerl#22190.
mauke
linked a pull request
May 9, 2024
that will
close
this issue
Module: Fcntl
Description
Fcntl provides a
S_ISENFMT
function that makes no sense. If it exists at all (depends on whether your platform definesS_ENFMT
), it always returns false. It should just be removed from Fcntl (and not mentioned in perlfunc/stat).Background
If you want to get the type of a file in C, you get its
st_mode
fromstat
orlstat
, apply theS_IFMT
mask (filtering out the non-type bits), then compare the result to one of the otherS_IF*
constants:This is annoying enough that C provides additional
S_IS*
helper macros, one for each type of file:Perl's
Fcntl
module provides the same interface (mostly) with subroutines:However,
Fcntl
also defines aS_ISENFMT
function that doesn't correspond to anything in nature (C).On some platforms, there is an
S_ENFMT
("enforcement of file locks") constant, which indicates that record locks placed on this file are mandatory, not advisory. It typically shares its value withS_ISGID
("set group id") because the combination of a non-executable file with the setgid bit set is not otherwise meaningful. Note that this bit is part of the file permissions, not of its type! That's why there is no correspondingS_ISENFMT
macro for it.Perl's
S_ISENFMT
was originally added in ca6e1c2 (presumably by mistake), defined as:(Note that it's trying to compare to a non-existent
S_ISENFMT
constant. This went unnoticed becauseFcntl
didn'tuse strict
.)This code was subsequently "fixed" in 0e6f150, changing it to:
(Note the change to
S_IFENFMT
, which still doesn't exist becauseS_ENFMT
is not a file type.)Then 0f68039 added
use strict
and changed the code to:So now it is trying to call a non-existent
S_IFENFMT
subroutine.It got further "fixed" by fb59364:
Finally,
S_ENFMT
is a constant that actually exists (on some platforms)! So now it is possible to actually useS_ISENFMT
without getting a runtime error. Unfortunately the code still makes no sense:$_[0] & _S_IFMT
extracts the file type bits, butS_ENFMT
is not a file type, so this comparison always returns false.In 87eca6e, the whole logic was moved from Perl to XS code, but it still fails the same way: It always returns false at runtime. (If your platform defines
S_ENFMT
, that is; otherwiseS_ISENFMT
just isn't defined at all.)Steps to Reproduce
Expected behavior
The text was updated successfully, but these errors were encountered: