summaryrefslogtreecommitdiff
path: root/lib/File
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2012-06-18 13:09:02 +0200
committerNicholas Clark <nick@ccl4.org>2012-06-21 09:00:36 +0200
commit4c77591b9d78214701bc6ba2df3a2fbd9914c389 (patch)
treeab83725cb3a285ce80df74129bef729add230af4 /lib/File
parentff4803d9cfd18b5f2c1c00c307ca73700c048174 (diff)
downloadperl-4c77591b9d78214701bc6ba2df3a2fbd9914c389.tar.gz
Fix File::stat's -x and -X for root for directories and executable files.
Previously File::stat's overloaded -x and -X operators did not give the correct results for directories or executable files when running as root. They had been treating executable permissions for root just like for any other user, performing group membership tests etc. for files not owned by root. They now follow the correct Unix behaviour - for a directory they are always true, and for a file if any of the three execute permission bits are set then they report that root can execute the file. Perl's builtin -x and -X operators, added in Perl 2, have always been correct.
Diffstat (limited to 'lib/File')
-rw-r--r--lib/File/stat.pm19
1 files changed, 13 insertions, 6 deletions
diff --git a/lib/File/stat.pm b/lib/File/stat.pm
index 90d53d78e8..b631fbf875 100644
--- a/lib/File/stat.pm
+++ b/lib/File/stat.pm
@@ -10,7 +10,7 @@ BEGIN { *warnif = \&warnings::warnif }
our(@EXPORT, @EXPORT_OK, %EXPORT_TAGS);
-our $VERSION = '1.06';
+our $VERSION = '1.07';
my @fields;
BEGIN {
@@ -87,15 +87,22 @@ else {
*cando = sub {
my ($s, $mode, $eff) = @_;
my $uid = $eff ? $> : $<;
-
- # If we're root on unix and we are not testing for executable
- # status, then all file tests are true.
- $^O ne "VMS" and $uid == 0 and !($mode & 0111) and return 1;
-
my ($stmode, $stuid, $stgid) = @$s[2,4,5];
# This code basically assumes that the rwx bits of the mode are
# the 0777 bits, but so does Perl_cando.
+
+ if ($uid == 0 && $^O ne "VMS") {
+ # If we're root on unix
+ # not testing for executable status => all file tests are true
+ return 1 if !($mode & 0111);
+ # testing for executable status =>
+ # for a file, any x bit will do
+ # for a directory, always true
+ return 1 if $stmode & 0111 || S_ISDIR($stmode);
+ return "";
+ }
+
if ($stuid == $uid) {
$stmode & $mode and return 1;
}