|
用来获取文件的详细状态信息。它可以用来检索与文件相关的属性,如文件的权限、所有者、大小、时间戳等信息。 1.头文件 #include #include #include 2.函数原型 int stat(const char *pathname, struct stat *statbuf); 3.参数 pathname:输入参数,指需要获取状态信息的文件或者目录的路径名字 stabuf:输出参数,用来存储获取到的文件状态信息的结构体指针 4.返回值 成功:返回值为0,并且在struct stat结构体中被填充为指定的文件或者目录的详细状态信息。 失败:返回值为-1,并且在errno变量返回错误的原因,如文件不存在、权限不足或者无效的路径等。 struct stat结构体介绍: struct stat { dev_t st_dev; /* 设备 ID,即包含文件的设备编号 */ ino_t st_ino; /* inode 号 */ mode_t st_mode; /* 文件类型和权限模式 */ nlink_t st_nlink; /* 硬链接数 */ uid_t st_uid; /* 文件所有者的用户 ID */ gid_t st_gid; /* 文件所有者的组 ID */ dev_t st_rdev; /* 如果是特殊文件,包含设备 ID */ off_t st_size; /* 文件大小,以字节为单位 */ blksize_t st_blksize; /* 文件系统 I/O 的块大小 */ blkcnt_t st_blocks; /* 文件所占据的 512B 块数 */
/* 自 Linux 2.6 起,以下时间戳字段支持纳秒精度 */ struct timespec st_atim; /* 最后访问时间 */ struct timespec st_mtim; /* 最后修改时间 */ struct timespec st_ctim; /* 最后状态改变时间 */
/* 以下宏定义用于向后兼容早期版本 */ #define st_atime st_atim.tv_sec /* 最后访问时间,秒部分 */ #define st_mtime st_mtim.tv_sec /* 最后修改时间,秒部分 */ #define st_ctime st_ctim.tv_sec /* 最后状态改变时间,秒部分 */ }; struct stat结构体是在头文件中定义的,其中包含了文件的各种状态信息, 上面的结构体定义基本定义已经在注释中介绍完了, 需要注意的是结构体在struct timespec结构体部分,是在Linux2.6内核之后才支持的结构体定义,在旧版本的内核中并使用的是time_t类型的结构体来储存的时间(秒),这样的操作是为了确保新版本与旧版的内核做到兼容,使用时可以直接使用st_atime、st_mtime、st_ctime宏定义来获取文件的各个时间状态。 1)st_mode字段 st_mode字段本质上是一个32位无符号整形数据,该变量主要记录了文件的类型、文件的权限信息,虽然st_mode是一个32位的无符号整形数据,但实际只用到了低16位,下面就是低16位所代表的含义。 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 文件类型 文件特殊权限(S) 文件所有者权限(U) 同组用户权限(G) 其他用户权限(O) 文件类型为4bit,对应的为15-12位,用来描述是普通文件、链接文件、目录等文件状态。剩下的11-0位分别对应文件的特殊权限(S)、文件所有者权限(U),同组用户权限(G)、其他用户权限(O)。 2)文件类型宏定义 S_IFMT 0170000 文件类型字段掩码位 S_IFSOCK 0140000 socket(套接字文件) S_IFLNK 0120000 symbolic link(链接文件) S_IFREG 0100000 regular file(普通文件) S_IFBLK 0060000 block device(块设备文件) S_IFDIR 0040000 directory(目录) S_IFCHR 0020000 character device(字符设备文件) S_IFIFO 0010000 FIFO(管道文件) 3)文件特殊权限(S) S_ISUID 04000 /* Set user ID on execution. */ S_ISGID 02000 /* Set group ID on execution. */ S_ISVTX 01000 /* Save swapped text after use (sticky). */ 4)文件所有者权限(U)的宏定义 S_IRUSR 00400 /* Read by owner. */ S_IWUSR 00200 /* Write by owner. */ S_IXUSR 00100 /* Execute by owner. */ S_IRWXU 00700 /* Read, write, and execute by owner. */ 5)同组用户权限(G)宏定义 S_IRGRP 00040 /* Read by group. */ S_IWGRP 00020 /* Write by group. */ S_IXGRP 00010 /* Execute by group. */ S_IRWXG 00070 /* Read, write, and execute by group. */ 6)其他用户权限(O)宏定义 S_IROTH 00004 /* Read by others. */ S_IWOTH 00002 /* Write by others. */ S_IXOTH 00001 /* Execute by others. */ S_IRWXO 00007 /* Read, write, and execute by others. */ 这里所有数字都是以八进制表示的,所以在数字面都由0(零)来开头,就以套接字文件为例,一共是7位数,从左到右,也就是从高位到低位来说,第一位对应表示八进制,第二、三位表示文件类型,因文件类型由四位二进制数字组成,最大为15,换算成八进制为17,所以需要占两位,这里定义14(八进制)为套接字文件。第四位表示文件特殊权限(S),第五位表示文件所有者权限(U),第六位表示同组用户权限(G),第七位表示其他用户权限(O)。这样就共同组成了代表套接字文件宏定义所代表的数值:0140000。在这里使用的是八进制数字。 以S_IFMT的宏定义为例,介绍一下S_IFMT函数在实际使用中的作用。 使用一个switch语句做一个简单的例程来识别文件的类型: switch (file_stat.st_mode & S_IFMT) { case S_IFSOCK: printf("socket\n"); break; case S_IFLNK: printf("symbolic link\n"); break; case S_IFREG: printf("regular file\n"); break; case S_IFBLK: printf("block device\n"); break; case S_IFDIR: printf("directory\n"); break; case S_IFCHR: printf("character device\n"); break; case S_IFIFO: printf("FIFO\n"); break; } 除了这种方式,Linux系统还提供了封装好的宏,直接调用来判断文件类型,下面的mode是st_mode变量。 S_ISSOCK(mode) #判断是否为套接字文件 S_ISLNK(mode) #判断是否为链接文件 S_ISREG(mode) #判断是否为普通文件 S_ISBLK(mode) #判断是否为块设备文件 S_ISDIR(mode) #判断是否为目录 S_ISCHR(mode) #判断是否为字符设备文件 S_ISFIFO(mode) #判断是否为管道文件 注:以上的宏定义正确返回值为true,否则返回false。 用这些宏就可以来判断文件属性了。 5.示例:(使用stat函数获取文件属性) #include #include #include #include #include
void print_time(const char *label, time_t time) { struct tm *tm_info; char buffer[26];
tm_info = localtime(&time); strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_info); printf("%s: %s\n", label, buffer); }
int main() { struct stat file_stat; const char *filename = "example.txt"; // 替换为你的文件名
// 获取文件状态信息 if (stat(filename, &file_stat) == -1) { perror("stat"); exit(EXIT_FAILURE); }
// (1) 获取文件的 inode 节点编号和文件大小 printf("Inode number: %ld\n", (long)file_stat.st_ino); printf("File size: %ld bytes\n", (long)file_stat.st_size);
// (2) 判断文件的其他用户权限 printf("Readable by others: %s\n", (file_stat.st_mode & S_IROTH) ? "Yes" : "No"); printf("Writable by others: %s\n", (file_stat.st_mode & S_IWOTH) ? "Yes" : "No");
// (3) 获取文件的时间属性 print_time("Last access time", file_stat.st_atime); print_time("Last modification time", file_stat.st_mtime); print_time("Last status change time", file_stat.st_ctime);
return 0; } 6.测试结果 Inode number: 5254391 File size: 12 bytes Readable by others: Yes Writable by others: No Last access time: 2024-08-09 11:12:18 Last modification time: 2024-08-09 11:11:50 Last status change time: 2024-08-09 11:11:50 第一行输出了inode编号,第二行输出文件大小,第三行输出其他用户的读权限,第四行是其他用户的写权限,最后三行分别为最后访问时间,最后修改时间,最后一次状态变更时间。
|