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

I have been working on a problem and I am looking for some insight. I am using perl to check File Permissions on a UNIX Filesystem using stat, however I need to determine if a file is '0755' or less permissive such as '0644'. Thus if I have a file that is either 0750, 0751, 0754, or 0755, my check would succeed, but 0756, 0757, or 0752 (since the write bit is on for those conditions) which would fail. (This has to be done for user, group and world permissions, which makes it more complicated). My other problem was that I could not install any modules since the script will reside of numerous UNIX boxes. My thought has been to convert each digit to a binary number and do a series of comparsions, as strings, such as comparing the binary number of 5: (101) to 4: (100) which should succeed. I thought about binary comparisons, however that doesn't seem to get me the information that I need (ie XOR, AND, etc). If anyone has some insight to my problem, it would be greatly appreciated.

  • Comment on UNIX File Permissions equal or less than conditions

Replies are listed 'Best First'.
Re: UNIX File Permissions equal or less than conditions
by SuicideJunkie (Vicar) on Sep 17, 2013 at 21:01 UTC

    Bitwise Negate 0755 into 0022. Bitwise-and your test value with 0022. If the result is not zero, then the test value has scary bits set and the permissions test should fail.

    Next take your required bits 0750 (?) and bitwise and them with your test value. If the result is not 0750 then the test value has insufficient bits set and the permissions test should also fail.

    Otherwise, it passes.

Re: UNIX File Permissions equal or less than conditions
by marinersk (Priest) on Sep 17, 2013 at 21:10 UTC
    Binary XOR and AND are the answers I would have expected to give, yet you state they don't give the info you need.

    Perhaps you can explain that. In the meantime:
    Update: SuicideJunkie combines both bit checks in the same mask, much more elegant. Apparently marinersk needs coffee. Or sleep.

    #!/usr/bin/perl -w use strict; my $MASK_WRITE_GROUP = 0020; my $MASK_WRITE_WORLD = 0002; my @TestData = ( 0644, 0750, 0751, 0754, 0755, # success tests 0756, 0757, 0752, # failure tests ); { foreach my $permissionsMask (@TestData) { printf "Checking %04o - ", $permissionsMask; my $groupWritePermission = ( $permissionsMask & $MASK_WRITE_GR +OUP ); my $worldWritePermission = ( $permissionsMask & $MASK_WRITE_WO +RLD ); if ( $groupWritePermission || $worldWritePermission ) { print "FAIL\n"; } else { print "PASS\n"; } } } exit; __END__ C:\Steve\Dev\PerlMonks\P-2013-09-17@2251-BitMask>bitmask.pl Checking 0644 - PASS Checking 0750 - PASS Checking 0751 - PASS Checking 0754 - PASS Checking 0755 - PASS Checking 0756 - FAIL Checking 0757 - FAIL Checking 0752 - FAIL
      So the changes:

      my $DANGER_BITS = 0022; my $dangerBitCheck = ( $permissionsMask & $DANGER_BITS ); if ($dangerBitCheck) { print "FAIL\n"; }
        All -- thanks for the insight. I ended up with
        if ($mode & 07022) { ... }
        (I also want to check for setuid/setgid/sticky.) I knew that bitwise was the best way to go, thanks for setting me back on the path.