第4章 文件和目录
4.2 函数stat、fstat、fstatat和 lstat
#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);
/* 所有4个函数的返回值:若成功,返回0;若出错,返回-1 */
- stat: 根据路径,获取其指向的文件信息
- fstat:根据已经打开的文件描述符,获取其指向的文件信息
- lstat: 与stat类似,除了当路径指向为符号链接时,lstat返回链接本身信息,而stat返回对应的文件信息
- fstatat:为一个相对于当前打开目录(由fd参数指向)的路径名返回文件统计信息。当AT_FDCWD传入fd参数,并且路径参数为相对路径时,不会跟随符号链接,而是返回符号链接本身的信息。如果路径为绝对路径,则fd参数被忽略。
struct stat {
mode_t st_mode; /* file type & mode (permissions) */
ino_t st_ino; /* i-node number (serial number) */
dev_t st_dev; /* device number (file system) */
dev_t st_rdev; /* device number for special files */
nlink_t st_nlink; /* number of links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
off_t st_size; /* size in bytes, for regular files */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last file status change */
blksize_t st_blksize; /* best I/O block size */
blkcnt_t st_blocks; /* number of disk blocks allocated */
};
4.3 文件类型
- 普通文件(regular file):包含了某种形式的数据;
- 目录文件(directory file):包含了其他文件的名字以及指向与这些文件有关信息的指针;
- 块特殊文件(block special file):该类型文件提供对设备(如磁盘)带缓冲的访问,每次访问以固定长度为单位进行;
- 字符特殊文件(character special file):该文件提供对设备不带缓冲的访问,每次访问长度不变。系统中的所有设备要么是字符特殊文件,要么是块特殊文件。
- FIFO:该文件用于进程通信,也称为命名管道(named pipe);
- 套接字(socket):该文件用于进程间的网络通信,也可以用在一台宿主机上进程间的非网络通信。
- 符号链接(symbolic link): 该文件指向另一个文件。
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
struct stat buf;
for (int i = 1; i < argc; ++i) {
if (stat(argv[i], &buf) < 0) {
} else {
if (S_ISREG(buf.st_mode))
printf("regular\n");
else if (S_ISDIR(buf.st_mode))
printf ("directory\n");
else if (S_ISCHR(buf.st_mode))
printf ("character special file\n");
else if (S_ISBLK(buf.st_mode))
printf ("block special file\n");
else if (S_ISFIFO(buf.st_mode))
printf ("FIFOe\n");
else if (S_ISLNK(buf.st_mode))
printf ("symbolic link\n");
else if (S_ISSOCK(buf.st_mode))
printf ("socket\n");
if ((S_ISUID & buf.st_mode) == S_ISUID)
printf("SUID\n");
if ((S_ISGID & buf.st_mode) == S_ISGID)
printf("SGID\n");
}
}
exit(0);
}
4.4 设置用户ID和设置组ID
实际用户ID和实际组ID标识我们究竟是谁。这两个字段取自登陆时的口令文件中的登陆项。有效用户ID和有效组ID则决定了我们的文件访问权限.(接下来只讲这四个) 一般来说,实际用户ID等于有效用户ID,实际组ID等于有效组ID。
每个文件都有一个所有者和组所有者,所有者由stat结构中的st_uid成员表示,组所有者则由st_gid成员表示。在执行一个程序文件时,进程的有效用户ID通常就是实际用户ID,有效组ID通常就是实际组ID。
但可在st_mod中设置一特殊标志,其含义:“当执行此文件时,将进程的有效用户ID设置为文件所有者的用户ID(st_uid)”。与此类似,还可以设置另一位,它使得将执行此文件的进程的有效组ID设置为文件的组所有者ID(st_gid)。
这就是设置用户ID(Set-User-ID)和设置组ID(Set-Group-ID)。
详细具体分析:
4.5 文件的访问权限
2、访问权限的使用方式:
见课本划线部分
3、内核访问访问权限测试流程:
见课本