I am a beginner to Unix programming and C and I have two questions regarding the struct stat
and its field st_mode
:
When accessing the st_mode
field as below, what type of number is returned( octal, decimal, etc.) ?
struct stat file;
stat( someFilePath, &file);
printf("%d", file.st_mode );
I thought the number is in octal but when I ran this code, and I got the value 33188
. What is the base ?
- I found out that the
st_mode
encodes a 16 bit binary number that represents the file type and file permissions. How do I get the 16-bit number from the above output(esp. when it doesn't seem to be in octal). And which parts of the 16-bit digit encodes which information ?
Thanks for any help.
I think you are mixing concepts here.
In memory, integer values are always in binary, let's call it native format. st_mode
is of type mode_t
and that type is an unspecified integer type, probably int
.
The concept of base, that is decimal, octal or hexadecimal, is useful only when you covert the number in memory in native format to a text representation, (or back from text to native).
For example:
int x = 42;
assigns the number 42 to the integer variable. Since source code is text, the 42
is input as text, and we know that it is a decimal value (no prefix). But note how we do not specify a base for the variable: it does not have one.
This other code:
int x = 0x2A;
is exactly equivalent. Instead of the decimal constant 42
it uses the hexadecimal constant 0x2A
, but that is identical, and x
got the same value on both cases. Likewise:
int x = 052;
is also equivalent, but with an octal constant.
Now to your code. When you do:
printf("%d", file.st_mode);
33188
you tell the program to output the value of that variable as a decimal number. Remember that printf
converts the number from native format to text, so the base of that text matters. If you prefer to see the value as octal, just write:
printf("%o", file.st_mode);
100644
Or in hexadecimal:
printf("%x", file.st_mode);
81A4
The nice thing about octal is that itrepresents exactly 3 bit per octal digit (4 bits per digit for hex.), so with a bit of practise you can see the bits without computations.
For example, your st_mode
is 33188
in decimal or 0100644
in octal. The decimal tells me nothing, but the octal does mean something, because I remember that the last 9 bits (3 octal digits) are the permissions: 3 bits for the owner, 3 bits for the group, 3 bits for other. So:
* Owner: 6 that is rw-
* Group: 4 that is r--
* Other: 4 that is r--
BTW, the last 1 is this constant:
#define S_IFREG 0100000
that just means that it is a regular file.
You printed it as decimal, so you got decimal. If you'd printed it as octal, you'd have gotten octal; ditto for hex.
The st_mode
field is most easily understood when printed as octal.
printf("mode = %07o\n", file.st_mode);
The last three digits are the familiar permissions (644, for example) for chmod
etc. The 4th digit from the right is usually 0 but will be non-zero for set-UID, set-GID or sticky-bit files or directories. The remaining digits identify the type of the file.
You can use the macros from <sys/stat.h>
to dissect the information.