标签:
在前面的两篇,我们了解了IO操作的一些基本操作函数,包括open、read和write。
在本篇我们来学习一下文件系统的其他特性和一个文件的属性,涉及的函数功能包括:
我们还会了解一些文件系统相关的数据结构和符号链接(symbolic link)。
#include <sys/stat.h> int stat(const char *restrict pathname, struct stat *restrict buf ); int fstat(int fd, struct stat *buf); int lstat(const char *restrict pathname, struct stat *restrict buf ); int fstatat(int fd, const char *restrict pathname, struct stat *restrict buf, int flag); //All four return: 0 if OK, −1 on error
函数功能:
stat返回pathname指定文件的信息;
fstat获取在文件描述符fd上打开的文件信息;
lstat的功能和stat函数类似,只是有一种情况有区别,当pathname指定的文件是一个符号链接的时候,lstat函数获取的文件信息是该符号链接的信息,而不是符号链接所指向文件的信息,在后面我们会了解更多关于符号链接的相关内容;
fstatat:文件描述符fd表示一个父目录,pathame指定父目录下得一个子目录,fstatat函数返回该子目录下的文件统计数。flag用来设置是否查询符号链接所指向的文件,如果flag设置为AT_SYMLINK_NOFOLLOW,则fstatat函数只返回该符号链接的相关信息,如果不设置该标志位,则返回该符号链接指向的文件的相关信息。
是一个关键的输出参数,上面的参数将文件属性填充值该结构体内。结构体如下图所示:
结构体中得每个成员都代表文件的某一个属性,我们会逐个了解属性的具体含义。
目前我们了解了两种文件:常规文件(regular files)和文件夹(directory)。
常见的几种文件类型包括:
stat结构体中得st_mode制定了文件的类型。
Example:
#include "apue.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("lstat 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); }
运行截图:
每个进程6个甚至更多的ID和它关联。如下表所示:
简要介绍ID的区别:
一般情况下,effective user ID = real user ID,effective group ID = real group ID.
每个文件都由一个所有者,和一个组所有者,分别对应stat数据结构中得字段:st_uid和st_gid。
如果执行程序时,effective user(group) ID != real user(group) ID,可以通过设置mode中两个bit来实现将effective user(group) ID设置为文件所有者(组),这两个bit叫做:set-user-ID位和set-group-ID位。这两个位包含在stat数据结构中得st_mode字段中,可以通过函数S_ISUID和S_ISGID来测试。
stat数据结构中的st_mode字段中同样包含文件访问权限位。
每个文件有9中权限位:
这些标志位的使用需要注意的事项总结如下:
文件访问权限检测流程:
简单来说,如果进程是该文件的拥有者,则访问是否允许取决于用户访问权限标志位,忽略组权限标志位;如果进程不是该文件的拥有者,但是该进程属于某个有访问权限的组,访问是否允许取决于组权限标志位的设置,忽略other访问权限标志位。
新文件的real user ID为创建该文件的进程的effective user ID。
新文件的real group ID的取值取决于:
access和faccessat函数用于测试当前用户(real user,当前登录用户)对某一文件是否有某种操作权限。
函数声明:
#include <unistd.h> int access(const char* pathname, int mode); int faccessat(int fd, const char* pathname, int mode, int flag);
mode的可取值,当为F_OK,测试文件是否存在。
faccessat函数的相关细节:
Example:
#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"); exit(0); }
测试:
由于本地mac环境搞不定,所以直接截书上的例子吧。
该例中,当切换到root用户,修改了该文件的所有者为root用户,并且设置了set-user-ID,这样当切换到别的用户时,仍可以以RDONLY方式打开文件,但是由于access是测试当前real user的读权限,当切换到其他用户时,access测试不通过,显示Permission denied。
好吧,直接忽略上面这个例子吧,我没能在自己的机器上重现,只是直接随便翻译书上某一段话。如果有某位高手看懂了,请指点。
由于这一章内容比较多,所以打算用三篇来写,这是第一篇,主要介绍了stat函数,access函数,文件类型和各种令人糊涂的ID。
参考资料:
《Advanced Programming in the UNIX Envinronment 3rd》
UNIX高级环境编程(3)Files And Directories - stat函数,文件类型,和各种ID
标签:
原文地址:http://www.cnblogs.com/suzhou/p/4295535.html