Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Testing for group or world writable files

by neilwatson (Priest)
on Jul 07, 2015 at 01:02 UTC ( [id://1133485]=perlquestion: print w/replies, xml ) Need Help??

neilwatson has asked for the wisdom of the Perl Monks concerning the following question:

Brethren,

I want to test if a file is writable by the group or world. What I tried is below, but test three fails unexpectedly

#!/usr/bin/perl use strict; use warnings; use Data::Dumper; use feature 'say'; use Test::More; use File::stat; my $file = $ARGV[0]; my $sb = stat( $file ); my $mode = $sb->mode & 0777; warn "mode of [$file] is [$mode]"; ok( -O $file, "File owned by real uid" ); ok( -f $file, "File is a plain file" ); ok( ! $mode & 022, "File is not group or world writable" ); done_testing; # Results in: mode of [/etc/passwd] is [420] at ./foo.pl line 14. not ok 1 - File owned by real uid # Failed test 'File owned by real uid' # at ./foo.pl line 16. ok 2 - File is a plain file not ok 3 - File is not group or world writable # Failed test 'File is not group or world writable' # at ./foo.pl line 18. 1..3 # Looks like you failed 2 tests of 3.

Neil Watson
watson-wilson.ca

Replies are listed 'Best First'.
Re: Testing for group or world writable files
by Loops (Curate) on Jul 07, 2015 at 01:34 UTC
    Seems you need the parenthesis for precedence:
    ok( ! ($mode & 022), "File is not group or world writable" );
    Works here.
      I've just seen a presentation on Coccinelle, this kind of error was quite common in the Linux kernel. See here.
      لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Testing for group or world writable files
by stevieb (Canon) on Jul 07, 2015 at 01:28 UTC

    Here's one non-scientific way to check:

    #!/usr/bin/perl use warnings; use strict; use Test::More; my $file = 'file.txt'; my $perms = sprintf("%o", (stat $file)[2] & 0777); my ($u, $g, $w) = split //, $perms; my @writable = qw(2 3 6 7); ok (!(grep /$g/, @writable), "File is not group writable"); ok (!(grep /$w/, @writable), "File is not world writable");

    -stevieb

Re: Testing for group or world writable files
by kcott (Archbishop) on Jul 07, 2015 at 13:48 UTC

    G'day Neil,

    I see answers identifying a precedence problem. Rather than using the ! operator and adding (multiple levels of) parentheses, you can just use the low-precedence equivalent: not (see "perlop: Operator Precedence and Associativity"). There's also low-precedence and, or and xor. I find these operators make the code easier to read than using parentheses: you, of course, may have a different preference.

    Instead of using Test::More's ok() function (and, where necessary, negating the test), consider using the is() and isnt() functions. This (at least in the case of your posted code) circumvents the precedence issue entirely; it also aligns the test function with the test description. Here's an example roughly based on your code:

    #!/usr/bin/env perl use strict; use warnings; use Test::More tests => 4; my $mode = (stat $0)[2]; isnt(-d $0, 1, "This script isn't a directory."); is( -O $0, 1, "This script is owned by real uid."); isnt($mode & 020, 020, "This script isn't group writable."); isnt($mode & 002, 002, "This script isn't world writable.");

    [Note that I've used the core (builtin) stat function. File::stat, by default, overrides this.]

    Output:

    1..4 ok 1 - This script isn't a directory. ok 2 - This script is owned by real uid. ok 3 - This script isn't group writable. ok 4 - This script isn't world writable.

    Update: While my intent was to compare ok() with is() and isnt(), which I believed I achieved, I did notice a bug in the example code. I've fixed the code; retested; and posted the new code and output. The offending line was:

    isnt((stat $0)[2] & 022, 022, "This script isn't group or world writab +le.");

    Update 2: My bug fix (from the initial update) left the code a bit messy. I've tidied that up. Now just one call to stat with the result stored in $mode. Retested successfully; output unchanged; new code posted.

    -- Ken

Re: Testing for group or world writable files
by Anonymous Monk on Jul 07, 2015 at 01:52 UTC

    I see, another way to the answer is via Basic debugging checklist

    $ perl -MO=Deparse,-p ok( ! $mode & 022, "File is not group or world writable" ); ^Z ok(((!$mode) & 18), 'File is not group or world writable'); - syntax OK

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1133485]
Approved by toolic
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others avoiding work at the Monastery: (6)
As of 2024-04-20 00:19 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found