前面讲了文件的操作,但是我们在操作文件之前,应该先判断文件的属性,比如该文件是属于哪一类文件,用户具有哪些权限等。
关于文件类型和文件权限,可以参考之前的文章:Linux笔记(2)| 进阶命令
1、常用文件属性获取
stat函数
int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* Inode number */
mode_t st_mode; /* File type and mode */
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; /* Block size for filesystem I/O */
blkcnt_t st_blocks; /* Number of 512B blocks allocated */
/* Since Linux 2.6, the kernel supports nanosecond
precision for the following timestamp fields.
For the details before Linux 2.6, see NOTES. */
struct timespec st_atim; /* Time of last access */
struct timespec st_mtim; /* Time of last modification */
struct timespec st_ctim; /* Time of last status change */
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec
};
文件属性中的文件类型标志在structstat结构体的mode_t st_mode元素中,这个元素其实是一个按位来定义的一个位标志(有点类似于ARM CPU的CPSR寄存器的模式位定义)。这个东西有很多个标志位共同构成,记录了很多信息,如果要查找时按位&操作就知道结果了,但是因为这些位定义不容易记住,因此linux系统给大家事先定义好了很多宏来进行相应操作。这些宏可以通过inode查询,譬如S_ISREG宏返回值是1表示这个文件是一个普通文件,如果文件不是普通文件则返回值是0.
S_ISREG(m) is it a regular file?
S_ISDIR(m) directory?
S_ISCHR(m) character device?
S_ISBLK(m) block device?
S_ISFIFO(m) FIFO (named pipe)?
S_ISLNK(m) symbolic link? (Not in POSIX.1-1996.)
S_ISSOCK(m) socket? (Not in POSIX.1-1996.)
例:
stat(pathname, &sb);
if (S_ISREG(sb.st_mode)) {
/* Handle regular file */
}
st_mode中除了记录了文件类型之外,还记录了一个重要信息:文件权限。
linux并没有给文件权限测试提供宏操作,而只是提供了位掩码,所以我们只能用位掩码来自己判断是否具有相应权限。
2、文件权限管理
(1)access函数检查权限设置
int access(const char *pathname, int mode);
文本权限管控其实蛮复杂,一般很难很容易的确定对一个文件是否具有某种权限。设计优秀的软件应该是:在操作某个文件之前先判断当前是否有权限做这个操作,如果有再做如果没有则提供错误信息给用户。
access函数可以测试得到当前执行程序的那个用户在当前那个环境下对目标文件是否具有某种操作权限。
Mode参数可以填F_OK,R_OK,W_OK,X_OK,分别用来判断文件是否存在以及当前用户是否有读、写、执行的权限。
(2)chmod/fchmod与权限修改
chmod是一个linux命令,用来修改文件的各种权限属性。chmod命令只有root用户才有权利去执行修改。
chmod命令其实内部是用linux的一个叫chmod的API实现的。
注意:只有在Linux原生目录中,改变文件权限才有效,在共享文件夹中会不起作用。
(3)chown/fchown/lchown与属主修改
linux中有个chown命令来修改文件属主
chown命令是用chown API实现的,与(2)类似。
3、读取目录文件
DIR *opendir(const char *name);
DIR *fdopendir(int fd);
struct dirent *readdir(DIR *dirp);
struct dirent {
ino_t d_ino; /* Inode number */
off_t d_off; /* Not an offset; see below */
unsigned short d_reclen; /* Length of this record */
unsigned char d_type; /* Type of file; not supported
by all filesystem types */
char d_name[256]; /* Null-terminated filename */
};
(1)opendir打开一个目录后得到一个DIR类型的指针给readdir使用
(2)readdir函数调用一次就会返回一个structdirent类型的指针,这个指针指向一个结构体变量,这个结构体变量里面记录了一个目录项(所谓目录项就是目录中的一个子文件)。
(3)readdir调用一次只能读出一个目录项,要想读出目录中所有的目录项必须多次调用readdir函数。readdir函数内部会记住哪个目录项已经被读过了哪个还没读,所以多次调用后不会重复返回已经返回过的目录项。当readdir函数返回NULL时就表示目录中所有的目录项已经读完了。
主要参考:朱老师物联网大讲堂