ACCESS(2)

๐Ÿ“ฆ version 15.1, in freebsd 14.5, freebsd 15.1

๐Ÿ’… ACCESS(2) โ€” okay so, checking if a file will let you in โœจ

bestie welcome to the <syscall> where we vibe check a file before we commit ๐Ÿ’– this one lives in the System Calls Manual, and it's genuinely one of the most "wait, is this thing even telling me the truth" pages in the whole manual. buckle up ๐ŸŽ€


๐Ÿฆ‹ NAME ๐Ÿฆ‹

access, eaccess, faccessat โ€” check accessibility of a file ๐Ÿ‘‘


๐ŸŒธ LIBRARY ๐ŸŒธ

Standard C Library (libc, -lc) โ€” she's a libc girlie, no cap.


โœจ SYNOPSIS โœจ

#include <unistd.h>

int
access(const char *path, int mode);

int
eaccess(const char *path, int mode);

int
faccessat(int fd, const char *path, int mode, int flag);

like, three whole entry points, all doing the same "can I get in tho" energy ๐Ÿ™ˆ


๐Ÿซถ DESCRIPTION ๐Ÿซถ

So the access(), eaccess() and faccessat() system calls report whether an attempt to access the file designated by their path in the manner described by their mode argument is likely to succeed. Note the word likely, because this is not a promise, it's a vibe ๐Ÿ”ฎ

The value of mode is either:

  • the bitwise-inclusive OR of the desired permissions โ€” R_OK for read permission, W_OK for write permission, and X_OK for execute / search permission
  • or F_OK to simply check whether the file exists

<img>literally just "does this exist" energy, she's so real for that.

Now here's the part where I need you to listen, bestie, because this is the iconique caveat of the whole page ๐Ÿ˜ญ For a number of reasons, these system calls cannot be relied upon to give a correct and definitive answer. They can at best provide an early indication of the expected outcome, to be confirmed by actually attempting the operation. That's it. That's the whole deal.

For existence checks, either stat(2) or lstat(2) should be used instead. See also "SECURITY CONSIDERATIONS" below. โš ๏ธ

๐Ÿงš the access() vs eaccess() of it all ๐Ÿงš

The eaccess() system call uses the effective user ID and the group access list to authorize the request ๐ŸŽ€

The access() system call uses the real user ID in place of the effective user ID, the real group ID in place of the effective group ID, and the rest of the group access list.

Like... they're siblings, but one of them is using her real ID and the other is using her effective ID and if you mix them up you're gonna have a bad time ๐Ÿ’€

See the "DEFINITIONS" section of intro(2) for additional information on file access permissions and real vs. effective user and group IDs โ€” genuinely worth the read, iykyk.

๐ŸŒˆ faccessat() and the relative path situation ๐ŸŒˆ

The faccessat() system call is equivalent to access() except in the case where path specifies a relative path. In this case the file whose accessibility is to be determined is located relative to the directory associated with the file descriptor fd instead of the current working directory. main character energy: she doesn't do "current working directory", she does "this directory, actually" ๐Ÿ’…

If faccessat() is passed the special value AT_FDCWD in the fd parameter, the current working directory is used and the behavior is identical to a call to access() โ€” so, the classic behaviour, no notes ๐Ÿ‘‘

Values for flag are constructed by a bitwise-inclusive OR of flags from the following list, defined in <fcntl.h>:

โญ the flag list โญ

  • AT_EACCESS โ€” The checks are performed using the effective user and group IDs, like eaccess(), instead of the real user and group ID, like access(). so it's the effective-ID girlie version of the check ๏ฟฝ
  • AT_RESOLVE_BENEATH โ€” Only walk paths below the directory specified by the fd descriptor. See the description of the O_RESOLVE_BENEATH flag in the open(2) manual page. no escaping the enclosure, she stays in her lane ๐Ÿšง
  • AT_EMPTY_PATH โ€” If the path argument is an empty string, operate on the file or directory referenced by the descriptor fd. If fd is equal to AT_FDCWD, operate on the current working directory. empty string? we're going off the fd then, periodt ๐ŸŽ€
  • AT_SYMLINK_NOFOLLOW โ€” If path names a symbolic link, access of the symbolic link is evaluated. we're judging the link itself, not where she points, and honestly? iconic ๐Ÿฆ‹

And one last thing before we move on, bestie, because this is the one that always trips people up ๐Ÿ˜ญ

Even if a process's real or effective user has appropriate privileges and indicates success for X_OK, the file may not actually have execute permission bits set. Likewise for R_OK and W_OK. so like... the check says yes and the file says no and there's nothing you can do about it but respect her honesty ๐Ÿซถ


๐Ÿ’– RETURN VALUES ๐Ÿ’–

Upon successful completion, the value 0 is returned ๐ŸŽ‰

Otherwise the value -1 is returned and the global variable errno is set to indicate the error. sad girl hours, check your errno ๐Ÿ’€


๐Ÿ”ฅ ERRORS ๐Ÿ”ฅ

The access(), eaccess(), and faccessat() system calls may fail if:

  • [EINVAL] โ€” The value of the mode argument is invalid. you gave her a mode she doesn't recognize, be so fr ๐Ÿ™ˆ
  • [ENOTDIR] โ€” A component of the path prefix is not a directory. that's a file in your path bestie, it's giving confused ๐Ÿ’€
  • [ENAMETOOLONG] โ€” A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. girl that path is long ๐Ÿ˜ญ
  • [ENOENT] โ€” The named file does not exist. she's not there. she never was. rip ๐Ÿชฆ
  • [ELOOP] โ€” Too many symbolic links were encountered in translating the pathname. the symlinks are in a loop and they're not getting out ๐Ÿ”
  • [EROFS] โ€” Write access is requested for a file on a read-only file system. read-only means read-only, she said what she said ๐Ÿšซ
  • [ETXTBSY] โ€” Write access is requested for a pure procedure (shared text) file presently being executed. you want to write to a file that's literally running right now?? no ma'am ๐Ÿ˜ค
  • [EACCES] โ€” Permission bits of the file mode do not permit the requested access, or search permission is denied on a component of the path prefix. the classic "no" ๐Ÿ’…
  • [EFAULT] โ€” The path argument points outside the process's allocated address space. she's pointing into the void, that's not even your memory ๐Ÿซ 
  • [EIO] โ€” An I/O error occurred while reading from or writing to the file system. the disk is having a moment ๐Ÿ’€
  • [EINTEGRITY] โ€” Corrupted data was detected while reading from the file system. something is wrong in there, do not trust it โš ๏ธ

๐ŸŽ€ and also, faccessat() may fail if ๐ŸŽ€

  • [EBADF] โ€” The path argument does not specify an absolute path and the fd argument is neither AT_FDCWD nor a valid file descriptor. you forgot to give her a real fd, bestie ๐Ÿ˜ญ
  • [EINVAL] โ€” The value of the flag argument is not valid. those flags aren't flags she knows ๐Ÿ™ˆ
  • [ENOTDIR] โ€” The path argument is not an absolute path and fd is neither AT_FDCWD nor a file descriptor associated with a directory. that fd isn't a directory fd, that's the whole problem ๐Ÿซ 
  • [ENOTCAPABLE] โ€” path is an absolute path, or contained a ".." component leading to a directory outside of the directory hierarchy specified by fd, and the process is in capability mode. you tried to sneak out with a ".." and the capability mode said absolutely not ๐Ÿšง๐Ÿ”ฅ

๐ŸŒˆ SEE ALSO ๐ŸŒˆ

chmod(2), intro(2), stat(2) โ€” go read these too, they're the supporting cast and they ate ๐Ÿ’…


โญ STANDARDS โญ

The access() system call is expected to conform to ISO/IEC 9945-1:1990 ("POSIX.1") ๐Ÿ‘‘

The faccessat() system call follows The Open Group Extended API Set 2 specification ๐ŸŽ€


๐Ÿฆ‹ HISTORY ๐Ÿฆ‹

The access() function appeared in Version 7 AT&T UNIX โ€” she's an elder, she's been doing this since forever, respect her ๐Ÿซถ

The faccessat() system call appeared in FreeBSD 8.0 โ€” the newer sibling, still iconic โœจ


๐Ÿ’€ SECURITY CONSIDERATIONS ๐Ÿ’€

okay bestie this is the serious one, pay attention โš ๏ธ

The access(), eaccess(), and faccessat() system calls are subject to time-of-check-to-time-of-use races and should not be relied upon for file permission enforcement purposes. like genuinely, do not build your security on this, it will fold ๐Ÿ˜ญ

Instead, applications should perform the desired action using the requesting user's credentials โ€” that's the move, that's the whole thing ๐Ÿซถ

fr fr: check-then-use is a race condition and races are how you get got. don't do it ๐Ÿ’…

and that's the page!! she's from Debian, dated August 11, 2024, and she's filed under ACCESS(2) in the System Calls Manual โ€” go check those permissions responsibly, bestie, ily, bye ๐ŸŽ€๐Ÿ’–โœจ

๐Ÿ“ฆ where this page comes from