dagolden / Path-Tiny

File path utility
41 stars 59 forks source link

Add functions to fetch and check permissions for #295 #296

Closed scottchiefbaker closed 1 month ago

scottchiefbaker commented 1 month ago

This adds four methods, unit tests, and documentation:

$path->permissions($class);
$path->is_readable($class);
$path->is_writeable($class);
$path->is_executable($class);

$class can be user, group, other.

scottchiefbaker commented 1 month ago

Any thoughts on this?

xdg commented 1 month ago

Sorry it's taken me a while to get to this. After some considerations, I'm going to pass on this API extension. Path::Tiny already provides stat, so these sorts of checks are relatively straightforward uses of $path->stat->mode.

scottchiefbaker commented 3 weeks ago

Respectfully, I think you should reconsider part of this. The reason I wrote this was because I needed to see if a file was world readable. Getting the permissions via stat is simple, but breaking out the permission bitmasks to determine what user/group has what permission is non-trivial. If I simplified this down to just the permission piece would you accept that?

I'm sure there are a bunch of people that don't know how to convert the permission integer into it's various pieces.

ap commented 3 weeks ago

No need for any bit twiddling.

use Fcntl 'S_IRUSR';
$path->stat->cando( S_IRUSR );

That may be less neat-looking than, but is the same shape as,

$path->is_readable( 'user' )

and the upside of the slight cumbersomeness of having to work with a constant is that use strict will catch mistakes immediately. Passing strings (as in the suggested patch) allows the user to pass things like bogus, and sweeping such errors under the rug (by just returning a falsy value) lets the caller keep running and only blow up once execution gets somewhere where it may no longer be obvious why.

scottchiefbaker commented 2 weeks ago

For archival purposes if someone else needs this functionality here is a quicky function I came up with to get file permissions:

my @p     = get_file_permissions("/tmp/foo.txt");
my $other = $p[2];

# 4 = readable, 2 = writeable, 1 = executable
if ($other & 4) { print "File is world readable\n"; }
if ($other & 2) { print "File is world writeable\n"; }
if ($other & 1) { print "File is world executable\n"; }
sub get_file_permissions {
    my $file = shift();

    my @x    = stat($file);
    my $mode = $x[2];

    my $user  = ($mode & 0700) >> 6;
    my $group = ($mode & 0070) >> 3;
    my $other = ($mode & 0007);

    my @ret = ($user, $group, $other);

    return @ret;
}