1

The following line should be testing whether the current file is a directory or not:

if ((stbuf.st_mode & S_IFMT) == S_IFDIR)
      //file is a directory.

where stbuf is of type

 struct stat            /* inode information returned by stat */
 {
      dev_t st_dev;     /* device of inode */
      ino_t st_ino;     /* inode number */
      short st_mode;    /* mode bits */
      short st_nlink;   /* number of links to file */
      short st_uid;     /* owners user id */
      short st_gid;     /* owners group id */
      dev_t st_rdev;    /* for special files */
      off_t st_size;    /* file size in characters */
      time_t st_atime;  /* time last accessed */
      time_t st_mtime;  /* time last modified */
      time_t st_ctime;  /* time originally created */
 };

and S_IFMT and S_IFDIR are defined as

#define S_IFMT 0160000  /* type of file: */
#define S_IFDIR 0040000 /* directory */

I can't understand how the statement given above will work? Please can anyone explain logic behind it.
Thanks.

Levon
  • 138,105
  • 33
  • 200
  • 191
mohit
  • 5,696
  • 3
  • 24
  • 37

3 Answers3

3

It basically says if you take all of the bits of stbuf.st_mode and lined them up above the bits in S_IFMT. You are going to generate a third row, the result of the AND operation. See the following truth table for the AND operation, the output is only 1 if both inputs are 1.

input1| input2| output
------+-------+-------
  0   |   0   |   0
  0   |   1   |   0
  1   |   0   |   0
  1   |   1   |   1

For each of the corresponding bit positions, put a 0 below the numbers, unless both of the corresponding bits in a given position are 1, in which case you record a 1.

Maybe this visual image will be helpful:

st_mode   |  0100 0000 0000 0000 0000 0000 0000 0000
S_IFMT    |  1110 0000 0000 0000 0000 0000 0000 0000
bitwise & |===========================================
result    |  0100 0000 0000 0000 0000 0000 0000 0000

Compare this resulting bit pattern with the one for S_IFDIR. If they are equal you have a directory.

Maybe this SO question Using Struct Stat() will also help. Finally, the stat(3) man page also has some sample code in addition to all of the gory details of this struct.

Community
  • 1
  • 1
Levon
  • 138,105
  • 33
  • 200
  • 191
  • @sixlettervariables Wow .. thanks for the edit, that is awesome. I first didn't even recognize my answer :-) .. and you beat me to it (I was working on a smaller example). Really improves the answer. – Levon Jun 20 '12 at 16:30
  • I was going to answer with a piece of ASCII art, but you'd already explained it well enough. – user7116 Jun 20 '12 at 16:32
  • @sixlettervariables Thanks again, I hope your picture and my words combined will be helpful to OP (and anyone else who comes across this) – Levon Jun 20 '12 at 16:33
2

The bitwise AND is getting the bits concerned with the particular setting S_IFDIR.

If the result is S_IFDIR then that flag is set. 0160000 is in octal and represents the top 3 bits of the integer. 0040000 is the second bit, so they overlap.

andrews_nz
  • 175
  • 1
  • 9
2

For each pair of corresponding bits from the source and the mask, the logical AND operation gives an on bit (1) if and only if both bits were set to 1. This means all bits not turned on in the mask are zeroed. Suppose you have a single byte with bits abcdefgh where each of the letters is a bit, so either 0 or 1. If you have a mask whose value is e.g. 00111000, AND-ing the two will result in 00cde000. Thus, using the mask, you "cut out" just a substring of the bits. Often, the mask has only one bit set, in which case you will be testing a single bit. In your example, the mask is S_IFMT. Now you can take a number of values encooded in the space of the 3 bits the mask leaves untouched, like 00101000, 00011000 or anything that has all its 1 bits inside the space separated by the mask (this is what your S_IFDIR is in your example), and you can compare against the. So, if plain words the whole operations means "take a substring of the bits of a variable and check if it is one of the predefined values". This all is done for space effciency, if it were not important, the designers would probably have defined a separate variable for the mode field.

Michał Kosmulski
  • 9,855
  • 1
  • 32
  • 51