guy@auspex.UUCP (Guy Harris) (12/17/89)
(What's wrong with the original code is an error in using C; what's wrong with the reply to which I'm following up is an error in using UNIX - a real doozy at that, and one that I see all too often - so I'm moving that particular thread of the discussion to "comp.unix.questions".) >> if (nfile.st_mode & S_IFMT == S_IFREG) >> else if (nfile.st_mode & S_IFMT == S_IEXEC) > >Additionally, we don't want to mask permissions against S_IFMT. That is true, but: >For that matter, we don't need to mask type against S_IFMT. Bzzzt! Sorry, wrong answer. You *do* need to mask type against S_IFMT: >Don't we really want >if (nfile.st_mode & S_IFREG) > printf(...); >else if (nfile.st_mode & S_IFDIR) > printf(...); No, we don't - not one bit (no pun intended :-)). From the SunOS 4.0.3 <sys/stat.h>, the values in which reflect those in every other AT&T-derived UNIX I know of (except possibly for some of the newer mode bits, but I suspect that S_IFLNK is the same in S5R4 and 4.xBSD....) #define S_IFMT 0170000 /* type of file */ #define S_IFDIR 0040000 /* directory */ #define S_IFCHR 0020000 /* character special */ #define S_IFBLK 0060000 /* block special */ #define S_IFREG 0100000 /* regular */ #define S_IFLNK 0120000 /* symbolic link */ #define S_IFSOCK 0140000/* socket */ #define S_IFIFO 0010000 /* fifo */ The astute reader will note that if (nfile.st_mode & S_IFREG) will test whether the 0100000 bit is on in "st_mode". The astute reader will *also* note that this bit is on in the following values: S_IFLNK S_IFSOCK so the test above will say "true" for symbolic links and "socket files". They don't count as regular files in *my* book.... The astute reader will further node that else if (nfile.st_mode & S_IFDIR) will test whether the 004000 bit is on in "st_mode", and that said bit is on in the following values: S_IFBLK S_IFSOCK and will, in addition, note that a block special file is *not* a directory. Folks, the S_IF... values are *NOT* flag bits! They are values for a bit field, said bit field being defined by the S_IFMT value. You must *NOT* test whether a file is of type S_IFXXX by doing if (xxx.st_mode & S_IFXXX) because you run the risk of getting false positives. You must test whether a file is of type S_IFXXX by doing if ((xxx.st_mode & S_IFMT) == S_IFXXX)