access(2) - Linux 手册页
名称
access - 检查真实用户对文件的权限概要
#include <unistd.h> int access(const char *pathname, int mode);
描述
mode 指定要执行的可访问性检查,其值为 F_OK,或者是由 R_OK、W_OK 和 X_OK 中的一个或多个按位或运算组成的掩码。F_OK 测试文件是否存在。R_OK、W_OK 和 X_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_OK 或 W_OK 也指定在 mode 中,那么 access() 将返回 0 以供此类文件使用。早期的 2.6 内核(包括 2.6.3)也以与内核 2.4 相同的方式运行。在内核 2.6.20 之前,access() 忽略了 MS_NOEXEC 标志的效果,如果它被用于 mount(2) 底层文件系统。从内核 2.6.20 开始,access() 遵守此标志。