Linux中文件主要分为7种类型:
普通文件/目录文件/快特殊文件/字符特殊文件/FIFO/套接字/符号链接。
如果要获取某个文件属于哪种类型,可以通过lstat函数来获取。
#include "apue.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc ,char ** argv)
{
int i ;
struct stat buf;
char * ptr;
for(i = 1 ;i < argc ;i++)
{
printf("%s: " ,argv[i]);
if(lstat(argv[i] ,&buf) < 0)
{
err_ret("lstate error");
continue;
}
if(S_ISREG(buf.st_mode))
ptr = "regular";
else if(S_ISDIR(buf.st_mode))
ptr = "directory";
else if(S_ISCHR(buf.st_mode))
ptr = "character special";
else if(S_ISBLK(buf.st_mode))
ptr = "block special";
else if(S_ISFIFO(buf.st_mode))
ptr = "fifo";
else if(S_ISLNK(buf.st_mode))
ptr = "symbolic link";
else if(S_ISSOCK(buf.st_mode))
ptr = "socket";
else
ptr = "** unknown mode **";
printf("%s\n" ,ptr);
}
exit(0);
}
在Linux中,对于每个进程,都有6个ID与之关联。他们分别是:实际用户ID/实际组ID/有效用户ID/有效组ID/保存的设置用户ID/保存的设置组ID
前4个很好理解,保存的设置用户ID和保存的设置组ID一般是有效用户ID和有效租ID的副本。
通常,有效用户ID等于实际用户ID。但需要注意的是,实际用户ID并不一定和文件的stat结构中的st_uid相等。
实际用户ID是指用户登录Linux系统时的用户ID,而state结构中的st_uid通常是创建该文件的进程的实际用户ID,也就是创建这个文件的用户的ID.
因为每个进程都有6个ID与之关联,而决定其访问文件的权限的是有效用户ID和有效组ID。通常,有效ID等于实际ID。但是,通过设置这个程序文件的设置用户ID位可以使有效用户ID等于stat结构中的uid,从而可能使该程序在运行时取得更高的权限。
另一方面,access函数用来测试实际用户ID是否对某文件具有读/写/可执行权限。
#include <apue.h>
#include <fcntl.h>
int main(int argc ,char * argv[])
{
if(argc != 2)
{
err_quit("usage: a.out <pathname>");
}
if(access(argv[1] ,R_OK) < 0)
err_ret("access error for %s" ,argv[1]);
else
printf("read access OK\n");
if(open(argv[1] ,O_RDONLY) < 0)
err_ret("open error for %s" ,argv[1]);
else
printf("open for reading OK\n");
return 0;
}
这个程序非常简单,access访问的时候,用的是实际用户ID;而open函数用的是有效用户ID.
注意,第一次执行
./a.out /etc/shadow
的时候,输出都是Permisson Denied.
这是因为,当前用户是freeitdog,非root用户,所以实际用户只是一个普通用户,因为从
ls -l /etc/shadow
的结果可以知道,普通用户对这个文件没有读权限,所以输出来都是Permissin Denied。
而后来,首先执行了
chown root a.out
使文件的所有者变成了root,又通过
chmod u+s a.out
设置了设置用户ID位,使得有效用户ID位等于所有者的用户ID,从而open函数可以成功打开/etc/shadow文件,所以可以open Ok.