What is wrong with this code ?
Guy Harris
guy at auspex.UUCP
Sun Dec 17 06:35:18 AEST 1989
(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)
More information about the Comp.unix.questions
mailing list