• 正文
  • 相关推荐
申请入驻 产业图谱

飞凌嵌入式ElfBoard-获取文件的状态信息之stat

12/10 13:35
80
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

用来获取文件的详细状态信息。它可以用来检索与文件相关的属性,如文件的权限、所有者、大小、时间戳等信息。

1.头文件

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

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结构体是在<sysy/stat.h>头文件中定义的,其中包含了文件的各种状态信息,

上面的结构体定义基本定义已经在注释中介绍完了,

需要注意的是结构体在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("socketn"); break;

case S_IFLNK:

printf("symbolic linkn"); break;

case S_IFREG:

printf("regular filen"); break;

case S_IFBLK:

printf("block devicen"); break;

case S_IFDIR:

printf("directoryn"); break;

case S_IFCHR:

printf("character devicen"); break;

case S_IFIFO:

printf("FIFOn"); 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 <stdio.h>

#include <stdlib.h>

#include <sys/stat.h>

#include <time.h>

#include <unistd.h>

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: %sn", 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: %ldn", (long)file_stat.st_ino);

printf("File size: %ld bytesn", (long)file_stat.st_size);

// (2) 判断文件的其他用户权限

printf("Readable by others: %sn", (file_stat.st_mode & S_IROTH) ? "Yes" : "No");

printf("Writable by others: %sn", (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编号,第二行输出文件大小,第三行输出其他用户的读权限,第四行是其他用户的写权限,最后三行分别为最后访问时间,最后修改时间,最后一次状态变更时间。

相关推荐