调用open函数时,是以有效用户而不是实际用户的身份去验证进程对要打开的文件的读写权限。但是有时候我们想知道的是实际用户而非有效用户对某一文件的权限,此时就要用到access函数。
#include<unistd.h>
int access(const char* pathname, int mode);
int faccessat(int fd, const char* pathname, int mode, int flag);
先说简单的access函数,pathname是文件的路径名+文件名,指定要测试的文件;mode则指明测试哪种权限,实际上有4种:
- F_OK 值为0,判断文件是否存在
- R_OK 值为4,判断对文件是否有读权限
- W_OK 值为2,判断对文件是否有写权限
- X_OK 值为1,判断对文件是否有执行权限
对于后三种情况,可以用“或”的方法将多种情况合在一起测试,比如R_OK | W_OK就代表测试进程对文件的读写权限.
对于faccessat函数,其用fd来指定目录,mode的含义不变,而flag可以指定是判断有效用户的权限还是实际用户的权限。
如果flag的值是AF_EACCESS(值为0x200)的话,判断的是有效用户的权限;
如果flag的值是0的话,则跟access一样,判断的是实际用户的权限。
当判断有权限时,返回0,否则返回-1.
举例如下:
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
void err_sys(char *);
void err_sys(char *err_txt)
{
printf("%s\n",err_txt);
exit(1);
}
int main(int argc, char* argv[])
{
// 4.8 access 以实际用户ID测试进程的访问权限
printf("euid = %d,egid = %d,uid = %d, gid = %d\n",geteuid(), getegid(), getuid(), getgid());
if (argc != 2)
err_sys("you should input: %s file_name\n",argv[0]);
//判断实际用户的权限
if(access(argv[1], R_OK | W_OK) < 0)
printf("access error for RW!\n");
else
printf("access OK for RW!\n");
//以有效用户身份打开文件
if(open(argv[1], O_RDWR) < 0)
printf("open error for RW");
else
printf("open ok for RW");
exit (0);
}
执行效果如下:
我们将study4可执行文件设置上“设置用户ID位”和“设置组ID位”。同时study4的用户ID和组ID都是0(root用户)。同时当前目录下,snow.txt文件只对root用户开放写权限。回到普通用户,执行study4,判断其对snow.txt文件的访问权限。
有事设置了“设置用户ID位”和“设置组ID位”,有效用户ID和有效组ID都变成了root,而实际用户ID和实际组ID都是1000,代表hy。
root用户当然能成功的调用open函数,而用户hy没有snow.txt文件的读写权限,所以access失败。