access(2) - Linux 手册页

名称

access - 检查真实用户对文件的权限

概要

#include <unistd.h>
int access(const char *pathname, int mode);

描述

access() 检查调用进程是否可以访问文件 pathname。如果 pathname 是一个符号链接,则会进行去引用。

mode 指定要执行的可访问性检查,其值为 F_OK,或者是由 R_OKW_OKX_OK 中的一个或多个按位或运算组成的掩码。F_OK 测试文件是否存在。R_OKW_OKX_OK 测试文件是否存在以及是否授予读取、写入和执行权限,分别。

检查是使用调用进程的真实 UID 和 GID 完成的,而不是像实际尝试对文件执行操作(例如,open(2))时使用的有效 ID。这允许设置用户 ID 的程序轻松确定调用用户的权限。

如果调用进程具有特权(即,其真实 UID 为零),则对于普通文件,如果文件所有者、组或其他人启用了执行权限,则 X_OK 检查将成功。

返回值

如果成功(授予了所有请求的权限),则返回零。如果发生错误(mode 中的至少一位请求了被拒绝的权限,或者发生了其他错误),则返回 -1,并且 errno 会被适当地设置。

错误

access() 在以下情况下会失败:
EACCES
请求的访问将被拒绝,或者 pathname 的路径前缀中的某个目录的搜索权限被拒绝。(请参阅 path_resolution(7)。)
ELOOP
在解析 pathname 时遇到了过多的符号链接。
ENAMETOOLONG
pathname 太长。
ENOENT
pathname 的一个组件不存在或是一个断开的符号链接。
ENOTDIR
用作 pathname 中目录的组件实际上不是一个目录。
EROFS
请求对只读文件系统上的文件进行写入权限。

access() 可能会失败,如果

EFAULT
pathname 指向可访问地址空间之外。
EINVAL
mode 指定不正确。
EIO
发生了 I/O 错误。
ENOMEM
内核内存不足。
ETXTBSY
请求对正在执行的可执行文件进行写入访问。

符合

SVr4, 4.3BSD, POSIX.1-2001。

说明

警告:使用 access() 检查用户是否有权,例如,打开一个文件,然后再实际使用 open(2) 执行此操作,会产生安全漏洞,因为用户可能会利用检查和打开文件之间的时间间隔来操纵它。因此,应避免使用此系统调用。(在刚刚描述的示例中,更安全的替代方法是暂时将进程的有效用户 ID 切换到真实 ID,然后调用 open(2)。)

access() 始终会去引用符号链接。如果您需要检查符号链接的权限,请使用 faccessat(2) 并使用 AT_SYMLINK_NOFOLLOW 标志。

access() 如果 mode 中的任何访问类型被拒绝,即使 mode 中的其他一些访问类型被允许,也会返回错误。

如果调用进程具有适当的权限(即,是超级用户),那么 POSIX.1-2001 允许实现即使未设置任何执行文件权限位,也指示 X_OK 检查成功。Linux 不这样做。

只有在 pathname 的路径前缀中的每个目录上授予搜索(即,执行)访问权限的情况下,文件才能被访问。如果任何目录无法访问,则 access() 调用将失败,而不管文件本身的权限如何。

仅检查访问位,不检查文件类型或内容。因此,如果发现某个目录是可写的,这可能意味着可以在该目录中创建文件,而不是可以将该目录作为文件写入。类似地,DOS 文件可能被发现是“可执行的”,但 execve(2) 调用仍然会失败。

access() 在启用了 UID 映射的 NFS 文件系统上可能无法正常工作,因为 UID 映射是在服务器上完成的,并且对检查权限的客户端隐藏。FUSE 挂载也可能出现类似的问题。

错误

在内核 2.4(及更早版本)中,处理超级用户的 X_OK 测试存在一些奇怪之处。如果非目录文件的所有执行权限类别都已禁用,那么返回 -1 的唯一 access() 测试是在 mode 指定为仅 X_OK 时;如果 R_OKW_OK 也指定在 mode 中,那么 access() 将返回 0 以供此类文件使用。早期的 2.6 内核(包括 2.6.3)也以与内核 2.4 相同的方式运行。

在内核 2.6.20 之前,access() 忽略了 MS_NOEXEC 标志的效果,如果它被用于 mount(2) 底层文件系统。从内核 2.6.20 开始,access() 遵守此标志。

参见

chmod(2), chown(2), faccessat(2), open(2), setgid(2), setuid(2), stat(2), euidaccess(3), credentials(7), path_resolution(7)

引用自

access(1), acl_extended_fd(3), acl_extended_file_nofollow(3), cpuset(7), csh(1), explain(1), explain(3), explain_access(3), explain_access_or_die(3), find(1), kpseaccess(1), lam_rfposix(2), lcreate(1), lsof(8), nash(8), perl561delta(1), perl56delta(1), remind(1), spufs(2), spufs(7)