[Module::Build] Re: Preserving files' executable bits, once more (was: r5891 - in Module-Build/trunk
Status: Beta
Brought to you by:
kwilliams
From: Julian M. <ju...@me...> - 2006-04-23 17:13:37
|
Ken Williams wrote: > demerphq wrote: > > Randy W. Sims wrote: > > > Ken Williams wrote: > > > > I wonder whether we should check for executability with "-x $file" > > > > rather than "(stat $file)[2] & 0111". Besides being simpler, it > > > > seems like it might DTRT on more platforms, where stat values might > > > > be nontrustworthy. > > > > > > You mean like so: > > > > > > $mode =3D 0444 | ( -x $file ? 0111 : 0 ); > > > > Seems to me that if -x and stat with the appropriate mask arent > > returning the same thing you have a bug in Perl. > > Not necessarily. On Unix, for example, if the permissions on a file > you own are 0445, then "(stat $file)[2] & 0111" will return true but > "-x $file" will return false. Maybe that means we're not using "the > appropriate mask", but what would an appropriate mask be in all the > situations we care about? Probably none exists. Sorry for my late comment on this. `perldoc -f -x` is interesting: | The interpretation of the file permission operators "-r", "-R", "-w", | "-W", "-x", and "-X" is by default based solely on the mode of the file | and the uids and gids of the user. There may be other reasons you can't | actually read, write, or execute the file. Such reasons may be for | example network filesystem access controls, ACLs (access control lists), | read-only filesystems, and unrecognized executable formats. |=20 | Also note that, for the superuser on the local filesystems, the "-r", | "-R", "-w", and "-W" tests always return 1, and "-x" and "-X" return 1 | if any execute bit is set in the mode. Scripts run by the superuser may | thus need to do a stat() to determine the actual mode of the file, or | temporarily set their effective uid to something else. On Linux/Unix: | $ ls -go --time-style=3D+ | total 0 | -rw-r--r-- 1 0 f--------- | -rw-r--r-x 1 0 f--------x | -rw-r-xr-- 1 0 f-----x--- | -rw-r-xr-x 1 0 f-----x--x | -rwxr--r-- 1 0 f--x------ | -rwxr--r-x 1 0 f--x-----x | -rwxr-xr-x 1 0 f--x--x--x | $ perl -e 'printf("%s: -x =3D %s\n", $_, -x $_ || "0") for @ARGV' * | f---------: -x =3D 0 | f--------x: -x =3D 0 | f-----x---: -x =3D 0 | f-----x--x: -x =3D 0 | f--x------: -x =3D 1 | f--x-----x: -x =3D 1 | f--x--x--x: -x =3D 1 | $ sudo perl -e 'printf("%s: -x =3D %s\n", $_, -x $_ || "0") for @ARGV' * | f---------: -x =3D 0 | f--------x: -x =3D 1 | f-----x---: -x =3D 1 | f-----x--x: -x =3D 1 | f--x------: -x =3D 1 | f--x-----x: -x =3D 1 | f--x--x--x: -x =3D 1 So apparently -x always returns true for root, and (mode & 0100) for=20 non-root. Also: | $ sudo -u julian ./f--x------ | $ sudo -u julian ./f--------x | sudo: unable to execute ./f--------x: Permission denied | $ sudo ./f--x------ | $ sudo ./f--------x | $ If a file really is 0445 (0455), then I think it is reasonably safe to=20 assume that either ug-x (u-x) was _deliberately_ set or that o+x (go+x)=20 was _accidentally_ set, and that therefore "not x" should be assumed. IOW,= =20 it should be reasonably safe to consider the user x bit authoritative. Thus Module::Build should use -x for the executable check. However since=20 root (e.g. during `Build install`) always sees files as "x" if _any_ x bit= =20 is set, M::B would have to emulate -x's non-root behavior: my $mode =3D 0444 | ( (stat($file))[2] & 0100 ? 0111 : 0 ); |