access(2) (was: Writing to A NON-Existing File in "C")

Richard A. O'Keefe ok at quintus.UUCP
Sat Apr 23 11:18:29 AEST 1988


Recently we've heard again the negative reason not to use access(2):
it doesn't do what you'd expect if a program runs set[ug]id, and any
useful program might be run as a tool by a set[ug]id suite.

There is also a positive reason why it is better to use stat(2).
While you _can_ read a directory in UNIX, it usually doesn't make
sense.  (Some versions of UNIX now support only the BSD directory(3)
routines.)  And of course write access to a directory doesn't mean
that you can _write_ on it.  So if you want to know whether a given
path name identifies a _file_ that you can read/write/whatever, you
have to call stat(2) _anyway_ in order to find out what sort of thing
the path name identifies.  When I first ran into the access(2) problem,
I wrote two functions
	eaccess(char *path, int mode)		 /* "effective" access */
	saccess(struct stat *stat_buf, int mode) /* "stat"      access */
and was chagrined to discover that saccess() was the one I almost always
wanted, so using access(2) had been costing me an extra system call to
no good purpose.

I have wondered about posting this code to comp.sources.unix, but it
strikes me that it might be better still to extend the specification
slightly:  if the S_IFDIR bit were set in the mode, the path would
have to identify a directory, or if the S_IFREG bit were set in the
mode, the path would have to identify something other than a directory.
The test would be

	if ((stat_buf->st_mode & S_IFMT) == S_IFDIR) {
	    if (mode & S_IFREG) { errno = EISDIR;  return -1; }
	} else {
	    if (mode & S_IFDIR) { errno = ENOTDIR; return -1; }
	}

What do you think?



More information about the Comp.unix.wizards mailing list