diff options
author | Nicholas Clark <nick@ccl4.org> | 2012-06-18 13:09:02 +0200 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2012-06-21 09:00:36 +0200 |
commit | 4c77591b9d78214701bc6ba2df3a2fbd9914c389 (patch) | |
tree | ab83725cb3a285ce80df74129bef729add230af4 /lib/File | |
parent | ff4803d9cfd18b5f2c1c00c307ca73700c048174 (diff) | |
download | perl-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.pm | 19 |
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; } |