Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

What does ">>" do? (And other stat questions)

by three18ti (Scribe)
on Oct 31, 2013 at 01:26 UTC ( #1060491=perlquestion: print w/ replies, xml ) Need Help??
three18ti has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks

I'm looking to search for files and directories with "777" permissions, so I'm reading the stat manpage. I think I know HOW to use the module, but I really don't understand.

for instance, the first example is:

$mode = (stat($filename))[2]; printf "Permissions are %04o\n", $mode &07777;

I can modify this to be usable:

my $mode = (stat($file))[2]; my $perms = sprintf "%04o", $mode &07777; print "EVIL PERSON with $file" if $perms eq '0777';

I'm sure there are other problems, besides using a magic number, but can someone explain what "&07777" does? (I also don't understand sprintf, but I understand that it takes a sort of "template" and produces results)

The next example is using Fcntl to import symbolic constants. But the examples are using some Perl magic I have not encountered before:

use Fcntl ':mode'; $mode = (stat($filename))[2]; $user_rwx = ($mode & S_IRWXU) >> 6;

My GUESS is that the "&" and ">>" are some sort of binary operators, but I get whatever the users mode is. Can someone please explain what is going on here as well? What is ">>" ? (I tried to google, but couldn't figure out how to search for the symbols or what to call them by name.

Thanks Monks!

Comment on What does ">>" do? (And other stat questions)
Select or Download Code
Re: What does ">>" do? (And other stat questions)
by toolic (Chancellor) on Oct 31, 2013 at 02:42 UTC
      Thanks, this gets me started.
Re: What does ">>" do? (And other stat questions)
by LanX (Canon) on Oct 31, 2013 at 02:43 UTC
    Sorry, you're asking too many questions at the same time to be easily answered in one thread.

    > My GUESS is that the "&" and ">>" are some sort of binary operators, ... I tried to google

    First step, plz try to read the docs and tell us what remains unclear: perldoc perlop

    (BTW: perlop is the second hit for perl binary operator )

    > but can someone explain what "&07777" does

    '&' is not a part of the word but a "binary and" operator. But I agree that the missing space doesn't improve readability.

    > besides using a magic number

    Do you know how file-permissions are managed in unix-like systems?

    Literal octal numbers start with a 0 followed by octal digits. see perlnumber

    see also oct for a discussion of your code.

    Cheers Rolf

    ( addicted to the Perl Programming Language)

      Ok, I think this makes sense:

      $dec_perms = (stat("filename"))[2] & 07777; $oct_perm_str = sprintf "%o", $perms;

      You and the decimal value of file perms from stat against an octal number to get your decimal permissions. Then feed it to sprintf to get octal permissions.

      But why "07777"? I'm sure there's a reason but it seems arbitrary (and perhaps they why is really moot...)

      Hello Rolf

      > Sorry, you're asking too many questions at the same time to be easily answered in one thread.

      I think I agree with you. When I started typing, I really only wanted to know what ">>" was. But as I was typing it became clear to me that I don't understand more than I initially though (or I understand less than I initially thought).

      Apparently I'm lacking some fundamental knowledge which is hampering my understanding of stat on the whole.

      > First step, plz try to read the docs and tell us what remains unclear: perldoc perlop

      Thanks for this, there's usually a perldoc that I've overlooked

      > (BTW: perlop is the second hit for perl binary operator )

      Thanks for this. My search for "perl binary" was clearly insufficient. And the first hit 1 sort of explains bitwise operators. I think the examples are doing EXACTLY the same thing (albeit with values for text formatting and not file permissions, but I think the concept is the same). But here's where I'm stumped. How does 128 become 10000000 amd 16 become 00010000? Is that just the integer converted to a binary number? The "or" makes sense in this case. I think if we & 10000000 and 00010000 we would get 0110111, right? How would this apply to octal numbers?

      > '&' is not a part of the word but a "binary and" operator. But I agree that the missing space doesn't improve readability.

      Ok, cool. So we're doing some binary operation on an integer and an octal "07777"? right? I thought binary operations had to be performed on integers? (And why would binary operations on integers be performed as floating point integers? That's more curiosity and I don't think important to my comprehension of the topic)

      I think I kinda get WHAT a bitwise shift is, e.g. "00000100 << 2" would be 00010000

      In the context of my program, or any program, what does that signify and when/why would I want to do it?

      > Do you know how file-permissions are managed in unix-like systems?

      After this thread, and speaking as an experienced Unix/Linux SysAdmin: apparently not...

      In a nutshell, the permissions are represented as one digit in a three digit octal number. E.g. 0555 (chmod assumes octal so the 0 is often omitted) would be read and execute permissions for user, group, and other. likewise 0777 is the TRUE mark of the beast as it gives read, write, and execute permissions to everyone (and often "nobody" or "www-data"...)

      Ok... so. if 4 is represented in binary as 100, 2 is 010, and 1 is 001, and you "or" 4 and 2 together:

      100 | 010 = 110

      Which is 6

      HOLY CRAP I think it makes sense all of a sudden... And that answers my question about octal numbers, just like regular integers, they're just converted by decimal place? (well... kinda 0111 would be 001001001 right?)

      So WTF is the deal with with "&07777"

      if we're "and"ing I know that and returns the values that are the same... how does this help me? since 07777 is 111111111111 right? What practical implications does this have?

      Literal octal numbers start with a 0 followed by octal digits. see perlnumber

      Oh. An octal number IS an integer. Ok, that answers my question about bitwise operators.

      > see also oct for a discussion of your code

      That's a little bit cleaner. Is there a good way to compare octal numbers? (googling "perl compare octal values" returned your link and some really old links. none of which say you should compare them as strings (with "eq") or as integers. Some experimenting seems to indicate that perl can compare them as numbers, since they are...

      perl -e 'print "yes\n" if "0777" == "0777"' perl -e 'print "yes\n" if "0777" == "0776"'

      Thanks for your help. Even just your responses gave me a target in my research and responding to you helped my understanding greatly. Thanks so much for your help!

      1 http://www.cs.cf.ac.uk/Dave/PERL/node36.html
        again I don't know which of the questions are to be answered.

        All numbers here are integers, they differ only in literal representation - i.e. binary, octal, hex or decimal.

        Internally they are always only the same bits, i.e. you can mix representations in binary operations.

        07777 stands for 4 groups with 3 bits (2**3 =8 => octal).

        the highest group is quite special and include "exotic" things like sticky-bit. The others are for user, group and others with rwx -bits,

        But there are more bits set in mode to code the file-type:

        from stat

        Because the mode contains both the file type and its permissions, you should mask off the file type portion +and (s)printf using a "%o" if you want to see the real perm +issions. $mode = (stat($filename))[2]; printf "Permissions are %04o\n", $mode & 07777;

        Any questions left? =)

        Cheers Rolf

        ( addicted to the Perl Programming Language)

Re: What does ">>" do? (And other stat questions)
by Laurent_R (Parson) on Oct 31, 2013 at 11:05 UTC

    As for the sprintf line, this session under the debugger shows you how the $mode value (coming from stat($file)[2]) might be converted:

    DB<1> @c = stat "data.txt"; DB<2> x @c 0 1946693715 1 6473924464489865 2 33261 3 1 4 1001 5 513 6 0 7 64 8 1375303088 9 1375303088 10 1375303088 11 65536 12 1 DB<3> $mode = $c[2]; DB<4> printf "%04o", $mode ; 100755 DB<5> printf "%04o", $mode & 07777; 0755

    BTW, my "data.txt" does indeed have the 0755 permissions:

    $ ls -l data.txt -rwxr-xr-x 1 Laurent None 64 31 juil. 22:38 data.txt

    In the Unix file permission system, "rwxr-xr-x" is the same as the 0755 octal value.

      Hello,

      Thanks for taking the time to debug and respond.

      Could you please give me a little insight to what this means:

      DB<4> printf "%04o", $mode ; 100755 DB<5> printf "%04o", $mode & 07777; 0755

      I think you're trying to show me what happens when you binary "&" 33261 and 07777? maybe that doesn't make any sense because the 07777 isn't present in DB<4> but is in DB<5>. I read in a link above that "&" has lower precedence, so that would bean that "printf "%04o", $mode" is evaluated first? But that doesn't make any sense since printf would do the printing... Ok, I thought I was starting to understand... But I don't think I do.

        The $mode value is 33261. I wanted to show what happens when you print it with the octal formatting string (prints 100755) and when you do it after having modified it with the binary and (&). And & has a higher precedence than the comma. As you can see below, adding parens to guarantee the right precedence does not modify the output::

        DB<1> $mode = 33261; DB<2> printf "%04o", $mode; 100755 DB<3> printf "%04o", $mode & 07777; 0755 DB<4> printf "%04o", ($mode & 07777); 0755 DB<5>

        From your other answers, I think I can help you further by showing the same numbers as above in binary form:

        DB<5> printf "%04b", $mode ; 1000000111101101 DB<6> printf "%04b", 07777; 111111111111 DB<7>

        So, 33261 is 1000000111101101 in binary representation, and 07777 is 111111111111 (or the equivalent 0000111111111111) in binary representation. If we now do manually a bitwise and (&) between these two numbers, we do this:

        1000000111101101 & 0000111111111111 ================ = 0000000111101101

        We get a 1 in the result only at places where we have a 1 in both numbers above. This is in effect applying a mask to cancel out the four binary digits on the left in the original number. The same operation under the debugger:

        DB<8> $c = $mode & 07777; DB<9> printf "%04b", $c; 111101101 DB<10>

        If I now print that same $c number in its octal representation:

        DB<10> printf "%04o", $c; 0755 DB<11>

        Is it clearer in your mind now?

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (11)
As of 2014-10-20 12:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (76 votes), past polls