But when you want to make the permissions variable, you need to oct it. Can anyone explain why?
The best explanation is in the documentation (perlfunc, in this case), which says, in part
The first element of the list must be the numerical mode, which should probably be an octal number, and which definitely should not a string of octal digits: 0644 is okay, '0644' is not.
It's the bit pattern behind the number that is significant. Octal is used by convention, because the bits that chmod() cares about when specifying file protection are in three groups of three* -- a natural fit for octal. You could just as well specify them in hex or in decimal, though doing so obscures the intent of the operation.
chmod 0777, $file;
chmod 0x1FF, $file;
chmod 511, $file;
are equivalent.
*Additional bits are used for non-protection stuff like setuid, but it's the 9 low-order protection bits that people usually care about.
| [reply] [d/l] |
chmod 0755, $file;
# and not
chmod '0755', $file;
It is because my variable $chmod is regarded as a string and not a number, that is fails.
Why doesn't a trick like this work then?
$chmod='0644';
chmod $chmod+0, $file;
Please note that it is friday today, and this might explain my stuped questions :-)
---------------------------
Dr. Mark Ceulemans
Senior Consultant
IT Masters, Belgium
| [reply] [d/l] [select] |
Why doesn't a trick like this work then?
$chmod='0644';
chmod $chmod+0, $file;
It doesn't work because "leading zero means octal" applies only to numbers, not strings of numeric digits.
Try this:
print 0644, " != ", '0644' + 0, "\n";
This is all described in the on-line doc, in perldata.
| [reply] [d/l] [select] |
The short answer is that you're using chmod incorrectly in the short example. In fact, you're doing exactly what chmod's docs say you shouldn't do: using a string of octal digits. The short example should read chmod 0755, $file;, NOT chmod '0755', $file;. The first arg to chmod should be a number. I'm amazed that works at all.
The long answer is a little more complicated, and involves the abstraction of a number. Basicly, there are many different ways to write a number, all of which perl's parser reads and translates into an abstraction that we call a number: a bunch of bits somewhere on a chip in your system. Exactly what bits are set doesn't depend on how the number is written, only on it's value. 0x1ED, 0755, 493, 0b111101101 and even 4_9_3 are all the same thing to perl, an abstraction called a number, which has the value of 493, along with a bunch of housekeeping information. To whit, if we try to print out a slightly more literal interpretation of this abstraction then what you get with just a plain print, it'll look the same, regardless of how you happened to spell the number:
>perl -MDevel::Peek -e "$n=0755; Dump $n"
SV = IV(0x1928478) at 0x19245ac
REFCNT = 1
FLAGS = (IOK,pIOK)
IV = 493
OTOH, if you put somthing in quotes, it isn't a number, it's a bunch of characters that happen to look like a number to any humans that might happen to be looking at it. Now, perl will try to do the right thing between the to -- perl is losely typed (or untyped, depending on who you ask). However, while "493"+1==494 and 0755+1==494, "0755"+1==756. Why? Because "0755" isn't interpreted as a number when it appears in your program, it's interpreted as a string. While perl allows you to specify literal numbers in your program in quite a number of different formats, it's a little more strict in what, and how, it'll consider a number when converting from a string to a number. Specificly, it allows leading '-'s, digits '0'-'9', and '.'. It assumes all strings being converted from numbers are decimal, written in standard English notation with no ','s or other formatting characters. (It also assumes that the decimal seperator is '.', not ',', as found in German and a fair number of other languages.)
This means that '0755'+0 is 755, not 493.
As to your confusion in the long form of the program, you seem to be confused about the snippet in the docs of chmod. I can't say I blame you, it's not clear what's going on. The masking with &0777 is all that you need. The reason is that the UNIX "mode" value encodes both the type of file (regular, dir, symlink, chardev, blockdev, FIFO...), and the permissions (read, write, execute, misc / user, group, other). If you're going to be calling chmod, you only want the permissions part, so you "mask" them, by doing a bitwise and, which will return 1 bits only where both the first AND the second argument have a 1 bit. &0777 will give you only the permissions, and not the mode, from the return of stat. The note about using printf's %04o format is to get the number into a nice user-readable (mildly readable, anyway) string of digits -- not a number anymore. The oct() function takes that string of digits, and turns it back into a number.
I hope my writing is coherent enough that this clears things up, instead of making them more murky.
Update: Fixed silly errors. Yeah, adding one doesn't give you back the same thing!
Warning: Unless otherwise stated, code is untested. Do not use without understanding. Code is posted in the hopes it is useful, but without warranty. All copyrights are relinquished into the public domain unless otherwise stated. I am not an angel. I am capable of error, and err on a fairly regular basis. If I made a mistake, please let me know (such as by replying to this node).
| [reply] [d/l] [select] |