文件和目录(一)
4.1 4个stat函数
#include <sys/stat.h> int stat(const char *pathname, struct stat *buf); int fstat(int fd, struct stat *buf); int lstat(const char *pathname, struct stat *buf); int fstatat(int fd, const char *pathname,struct stat *buf, int flag); 返回值:成功返回0,错处返回-1 |
(2) fstat函数获取已打开描述符fd上相关信息。
(3) lstat函数返回该符号链接的有关信息,而不是由该符号链接引用的文件的信息。
(4) fstatat函数为一个相对于当前打开目录的路径名返回的文件信息。flag参数控制着是否跟随这一个符号链接。当标志设置为AT_SYMLINK_NOFOLLOW时,则不会跟随符号链接。
4.2 stat结构体
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* inode number */ mode_t st_mode; /* protection */ nlink_t st_nlink; /* number of hard links */ uid_t st_uid; /* user ID of owner */ gid_t st_gid; /* group ID of owner */ dev_t st_rdev; /* device ID (if special file) */ off_t st_size; /* total size, in bytes */ blksize_t st_blksize; /* blocksize for file system I/O */ blkcnt_t st_blocks; /* number of 512B blocks allocated */ time_t st_atime; /* time of last access */ time_t st_mtime; /* time of last modification */ time_t st_ctime; /* time of last status change */ }; |
4.3 文件类型
Unix/Linux系统中,文件有7种类型:(1) 普通文件(regular file)。至于普通文件是文本文件还是二进制数据,对于内核而言没有区别,关键在于解释这个文件的应用程序。
(2) 目录文件(directory file)。这种文件包含了其他文件的名字以及指向与这些文件有关信息的指针。
(3) 块特殊文件(block special file)。这种类型的文件提供对设备带缓冲的访问,每次访问以固定长度为单位进行。
(4) 字符特殊文件(character special file)。这种类型的文件提供对设备不带缓冲的访问,每次访问长度可变。
(5) FIFO。用于进程间通信,也叫管道(pipe)。
(6) 套接字(socket)。这种类型的文件用于进程间的网络通信。
(7) 符号链接(symbolic link)。这种类型的文件指向另一个文件。
文件类型信息保存在stat结构的st_mode成员中,可以使用下面的宏来确定文件类型。
宏 |
文件类型 |
S_ISREG() |
普通文件 |
S_ISDIR() |
目录文件 |
S_ISCHR() |
字符特殊文件 |
S_ISBLK() |
块特殊文件 |
S_ISFIFO() |
FIFO或管道 |
S_ISLNK() |
符号链接 |
S_ISSOCK() |
套接字 |
#define S_ISDIR (mode) ( ( (mode) & S_IFMT) ) == S_IFDIR)
4.4 文件访问权限
4.4.1 文件的9个访问权限位
stat结构中的成员st_mode值也包含对了文件的访问权限为。每个文件有9个访问权限位: st_mode屏蔽 |
含义 |
S_IRUSR S_IWUSR S_IXUSR |
用户读 用户写 用户执行 |
S_IRGRP S_IWGRP S_IXGRP |
组读 组写 组执行 |
S_IROTH S_IWOTH S_IXOTH |
其他读 其他写 其他执行 |
(2) 对目录具有写权限和执行权限,才能在目录中创建一个文件。
(3) 如果要删除一个现有文件,必须对包含该文件的目录具有写权限和执行权限,但对该文件本身则不需要读、写权限。
4.4.2 内核文件访问权限测试
进程每次打开、创建或删除一个文件时,内核就进行文件访问权限测试:(1) 若进程的有效用户ID是0(超级用户),则允许访问。
(2) 若进程的有效用户ID等于文件的所有者ID(也就是进程拥有此文件),那么如果所有者适当的访问权限为被设置,则允许访问,否则拒绝访问。
(3) 若进程的有效组ID或进程的附属组ID之一等于文件的组ID,那么如果适当的访问权限位被设置,则允许访问,否则拒绝访问。
(4) 若其他用户适当的访问权限为被设置,则允许访问,否则拒绝访问。
4.5 access和faccessat函数
当一个进程使用设置用户ID或设置组ID功能作为另一个用户(或组)运行时,希望按其实际用户ID和实际组ID来测试其访问权限,就需要使用access或faccessat函数。 #include <unistd.h> int access(const char *pathname, int mode); int faccessat(int fd, const char *pathname, int mode, int flag); 返回值:成功返回0,错误返回-1 |
mode |
说明 |
F_OK |
测试文件是否存在(access函数) |
R_OK |
测试读权限 |
W_OK |
测试写权限 |
X_OK |
测试执行权限 |
4.6 umask函数
#include <sys/stat/h> mode_t umask(mode_t cmask); 返回值:之前的文件模式创建屏蔽字 |
cmask是4.4.1中列出的9个常量中的若干个按位或组成的。
4.7 更改文件访问权限:chmod、fchmod和fchmodat
#include <sys/stat.h> int chmod(const char *pathname, mode_t mode); int fchmod(int fd, mode_t mode); int fchmodat(int fd,const char *pathname, mode_t mode,int flag); 返回值:成功返回0,出错返回-1 |
参数mode所示常量的按位或:
mode |
说明 |
S_ISUID S_ISGID S_ISVTX |
执行时设置用户ID 执行时设置组ID 保存正文(粘着位) |
S_IRWXU S_IRUSR S_IWUSR S_IXUSR |
用户读写执行 用户读 用户写 用户执行 |
S_IRWXG S_IRGRP S_IWGRP S_IXGRP |
组读写执行 组读 组写 组执行 |
S_IRWXO S_IROTH S_IWOTH S_IXOTH |
其他读写执行 其他读 其他写 其他执行 |