嵌入式Linux系统编程 — 3.2 stat、fstat 和 lstat 函数查看文件属性

news2024/11/28 18:37:27

目录

1 文件有哪些属性

2 stat函数

2.1 stat函数简介

2.2 struct stat 结构体

2.3 struct timespec 结构体

2.4 示例程序

3  fstat 和 lstat 函数

3.1 fstat 函数

3.2 lstat 函数


1 文件有哪些属性

Linux文件属性是对文件和目录的元数据描述,包括文件类型、权限设置、所有者、所属组、文件大小、修改时间、状态更改时间、访问时间、inode号、链接数以及文件系统等,这些属性通过命令如ls -lstat可以查看,它们定义了文件的访问权限和存储细节,是Linux系统管理文件的基础。

2 stat函数

2.1 stat函数简介

Linux 下可以使用 stat 命令查看文件的属性,命令内部就是通过调用 stat()函数来获取文件属性的, stat 函数是 Linux 中的系统调用,用于获取文件相关的信息,函数原型如下所示(可通过"man 2 stat"命令查看) :

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *buf);

pathname: 用于指定一个需要查看属性的文件路径。
buf: struct stat 类型指针,用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 structstat 变量的指针, 获取到的文件属性信息就记录在 struct stat 结构体中,结构体含义见2.2节。
返回值: 成功返回 0;失败返回-1,并设置 error。

2.2 struct stat 结构体

struct stat结构体用于存储由stat()系统调用返回的文件信息,在<sys/stat.h>头文件中申明,结构体内容如下所示:

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; /* 设备号(指针对设备文件) */
    off_t st_size; /* 文件大小(以字节为单位) */
    blksize_t st_blksize; /* 文件内容存储的块大小 */
    blkcnt_t st_blocks; /* 文件内容所占块数 */
    struct timespec st_atim; /* 文件最后被访问的时间 */
    struct timespec st_mtim; /* 文件内容最后被修改的时间 */
    struct timespec st_ctim; /* 文件状态最后被改变的时间 */
};

关于st_mode参数可参考文章4.1节:嵌入式Linux系统编程 — 1.1 文件I/O基础-CSDN博客

t_mode参数中包含“文件类型”,“文件类型”用4 个 bit 位表示,并有相应的宏定义, 这 4 个 bit 位用于描述该文件的类型,譬如该文件是普通文件、还是链接文件、亦或者是一个目录等,那么就可以通过这 4 个 bit 位数据判断出来,如下所示:

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(管道文件)

上面这些数字使用的是八进制方式来表示的,在 C 语言中,八进制方式表示一个数字需要在数字前面添加一个 0。所以由上面可知,当“文件类型”这 4 个 bit 位对应的数字是 14(八进制)时,表
示该文件是一个套接字文件。

所以通过 st_mode 变量可以判断文件类型,如下(假设 st 是 struct stat 类型变量) :

/* 判断是不是普通文件 */
if ((st.st_mode & S_IFMT) == S_IFREG) {
    /* 是 */
}
/* 判断是不是链接文件 */
if ((st.st_mode & S_IFMT) == S_IFLNK) {
    /* 是 */
}

除了这样判断之外,我们还可以使用 Linux 系统封装好的宏来进行判断,如下所示(m 是 st_mode变量) :

S_ISREG(m) #判断是不是普通文件,如果是返回 true,否则返回 false
S_ISDIR(m) #判断是不是目录,如果是返回 true,否则返回 false
S_ISCHR(m) #判断是不是字符设备文件,如果是返回 true,否则返回 false
S_ISBLK(m) #判断是不是块设备文件,如果是返回 true,否则返回 false
S_ISFIFO(m) #判断是不是管道文件,如果是返回 true,否则返回 false
S_ISLNK(m) #判断是不是链接文件,如果是返回 true,否则返回 false
S_ISSOCK(m) #判断是不是套接字文件,如果是返回 true,否则返回 false

有了这些宏之后,就可以通过如下方式来判断文件类型了:

/* 判断是不是普通文件 */
if (S_ISREG(st.st_mode)) {
    /* 是 */
}

/* 判断是不是目录 */
if (S_ISDIR(st.st_mode)) {
    /* 是 */
}

2.3 struct timespec 结构体

该结构体定义在<time.h>头文件中, 是 Linux 系统中时间相关的结构体,结构体内容如下所示:

struct timespec
{
    time_t tv_sec; /* 秒 */
    syscall_slong_t tv_nsec; /* 纳秒 */
};
  • tv_sec:表示自1970年1月1日(UTC时间)以来的秒数,这是一个time_t类型的值。
  • tv_nsec:表示tv_sec之后的纳秒数,范围从0到999,999,999。这个字段用于提供比秒更精确的时间度量。

2.4 示例程序

下面的代码通过命令行接收一个文件名作为参数,并使用stat系统调用来获取该文件的状态信息。

#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <time.h>

// 函数用于将time_t类型的时间转换为可读的字符串格式并打印
void print_time(time_t time) {
    struct tm *tm_info; // 用于存储本地时间信息的结构体
    char buffer[26];    // 用于存储格式化时间的字符串

    tm_info = localtime(&time); // 将time_t转换为本地时间
    strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", tm_info); // 格式化时间
    printf("%s\n", buffer); // 打印格式化后的时间字符串
}

int main(int argc, char *argv[]) {
    struct stat file_stat; // 用于存储文件状态的结构体

    // 检查命令行参数数量,确保有文件名提供
    if (argc < 2) {
        printf("Usage: %s <filename>\n", argv[0]);
        return 1;
    }

    // 使用stat系统调用来获取文件状态
    if (stat(argv[1], &file_stat) == -1) {
        perror("Error getting file status"); // 打印错误信息
        return 1;
    }

    // 打印文件的inode节点编号和文件大小
    printf("Inode: %ld\n", (long)file_stat.st_ino);
    printf("Size: %lld bytes\n", (long long)file_stat.st_size);

    // 判断文件类型并打印
    switch (file_stat.st_mode & S_IFMT) {
        case S_IFREG:
            printf("Regular file\n");
            break;
        case S_IFDIR:
            printf("Directory\n");
            break;
        // 可以添加更多的文件类型判断
        default:
            printf("Unknown type\n");
    }

    // 检查其他用户的权限
    if (file_stat.st_mode & S_IROTH && file_stat.st_mode & S_IWOTH)
        printf("Other users have read and write permissions\n");
    else
        printf("Other users do not have read and write permissions\n");

    // 打印文件的时间属性
    printf("Last accessed: ");
    print_time(file_stat.st_atime);
    printf("Last modified: ");
    print_time(file_stat.st_mtime);
    printf("Status was last changed: ");
    print_time(file_stat.st_ctime);
    printf("\n");

    return 0;
}

程序定义了一个print_time函数,用于将time_t类型的时间戳转换为易读的日期和时间字符串格式,并将其打印出来。在main函数中,首先检查是否提供了足够的命令行参数,然后获取文件状态,打印文件的inode编号、大小、类型以及其他用户的读写权限。最后,程序调用print_time函数打印文件的最后访问时间、最后修改时间和状态最后改变时间。程序运行结果如下:

3  fstat 和 lstat 函数

3.1 fstat 函数

除了 stat 函数之外,还可以使用 fstat 和 lstat 两个系统调用来获取文件属性信息。

fstat 与 stat 区别在于, stat 是从文件名出发得到文件属性信息,不需要先打开文件;而 fstat 函数则是从文件描述符出发得到文件属性信息,所以使用 fstat 函数之前需要先打开文件得到文件描述符。

#include <sys/stat.h>
#include <unistd.h>

int fstat(int filedes, struct stat *buf);
  • filedes:指定要获取状态的文件描述符。
  • buf:指向一个 struct stat 结构体的指针,该结构体用于接收文件的状态信息。

fstat 函数使用示例如下:

#include <stdio.h>
#include <sys/stat.h>

int main() {
    FILE *file = fopen("example.txt", "w"); // 使用标准I/O库打开文件
    if (file == NULL) {
        perror("Failed to open file");
        return 1;
    }

    struct stat file_stat;
    if (fstat(fileno(file), &file_stat) == -1) { // 使用文件流获取文件描述符并获取状态信息
        perror("Failed to get file status");
        fclose(file);
        return 1;
    }

    printf("File size: %lld bytes\n", (long long)file_stat.st_size);

    fclose(file); // 使用标准I/O库关闭文件
    return 0;
}

代码使用 fstat 函数通过 fopen 得到的文件流获取文件状态信息,包括文件大小。然后,它打印出文件的大小。运行结果如下:

3.2 lstat 函数

lstat()与 stat、 fstat 的区别在于,对于符号链接文件, stat、 fstat 查阅的是符号链接文件所指向的文件对应的文件属性信息,而 lstat 查阅的是符号链接文件本身的属性信息。lstat 函数原型如下所示:

#include <sys/stat.h>
#include <unistd.h>

int lstat(const char *path, struct stat *buf);
  • path:指定要获取状态的文件或链接的路径。
  • buf:指向一个 struct stat 结构体的指针,该结构体用于接收文件或链接的状态信息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1802478.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

浅谈安全用电管理系统对重要用户的安全管理

1用电安全管理的重要性   随着社会经济的不断发展&#xff0c;电网建设力度的不断加大&#xff0c;供电的可靠性和供电质量日益提高&#xff0c;电网结构也在不断完善。但在电网具备供电的条件下&#xff0c;部分高危和重要电力用户未按规定实现双回路电源线路供电&#xff1…

问题:设备管理指标为完好率不低于( ),待修率不高于5%,事故率不高于1%。 #知识分享#经验分享#经验分享

问题&#xff1a;设备管理指标为完好率不低于( )&#xff0c;待修率不高于5%&#xff0c;事故率不高于1%。 A、100% B、95% C、90% D、80% 参考答案如图所示

自动驾驶---Control之LQR控制

1 前言 在前面的系列博客文章中为读者阐述了很多规划相关的知识&#xff08;可参考下面专栏&#xff09;&#xff0c;本篇博客带领读者朋友们了解控制相关的知识&#xff0c;后续仍会撰写规控相关文档。 在控制理论的发展过程中&#xff0c;人们逐渐认识到对于线性动态系统的控…

vue数组在浏览器里可以看到值, 但是length为空

arr数组 length为0, 检查了代码在created 里调用了 this.getEnergyList(); 和 this.initChart(); 问题就在这里, this.initChart用到了getEnergyList里的数据, 造成了数据异步, 把this.initChart(); 放入 this.getEnergyList(); 方法里即可解决问题

Elasticsearch 认证模拟题 - 13

一、题目 集群中有索引 task3&#xff0c;用 oa、OA、Oa、oA 查询结构是 4 条&#xff0c;使用 dingding 的查询结果是 1 条。通过 reindex 索引 task3 为 task3_new&#xff0c;能够使 task3_new 满足以下查询条件。 使用 oa、OA、Oa、oA、0A、dingding 查询都能够返回 6 条…

【计算机视觉】数字图像处理基础:以像素为单位的图像基本运算(点运算、代数运算、逻辑运算、几何运算、插值)

0、前言 在上篇文章中&#xff0c;我们对什么是数字图像、以及数字图像的组成&#xff08;离散的像素点&#xff09;进行了讲解&#x1f517;【计算机视觉】数字图像处理基础知识&#xff1a;模拟和数字图像、采样量化、像素的基本关系、灰度直方图、图像的分类。 我们知道&a…

Ruoyi-Vue-Plus 下载启动后菜单无法点击展开,

1.Ruoyi-Vue-Plus框架下载后运行 2.使用mock数据 3.进入页面后无法点击菜单 本以为是动态路由或者菜单逻辑出了问题&#xff0c;最后发现是websocket的问题 解决办法 把这两行代码注释 页面菜单即可点击。 以上。

蓝屏绿屏黑屏?别急,有它们仨【送源码】

使用Windows系统的电脑时&#xff0c;可能会碰到各种问题&#xff0c;导致系统无法正常使用。 这些问题都有一个统一的专业叫法就是bug&#xff01; 系统一旦出现bug&#xff0c;最明显的特点就是&#xff0c; ①电脑蓝屏 电脑蓝屏是最经典的&#xff0c;从XP时代一直延续到…

数据结构之快速排序算法(快排)【图文详解】

P. S.&#xff1a;以下代码均在VS2019环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

Cesium开发环境搭建(一)

1.下载安装Node.js 进入官网地址下载安装包 Node.js — Download Node.js https://cdn.npmmirror.com/binaries/node/ 选择对应你系统的Node.js版本&#xff0c;这里我选择的是Windows系统、64位 安装完成后&#xff0c;WINR&#xff0c;输入node --version&#xff0c;显示…

全网最强下载神器IDM之如何用IDM下载百度网盘文件不限速 如何用IDM下载百度云资源 IDM激活码免费版下载安装

百度网盘是比较早的网盘类应用&#xff0c;用户群体比较多&#xff0c;但百度网盘对于非会员用户限速比较严重。IDM是非常好用的下载工具&#xff0c;那么我们如何用IDM下载百度网盘文件不限速&#xff1f;我们可以通过多种方法使用IDM下载百度网盘文件。下面我们就来看如何用I…

Windows11系统 和Android 调试桥(Android Debug Bridge,ADB)工具安装,app抓取日志内容

文章目录 目录 文章目录 安装流程 小结 概要安装流程技术细节小结 概要 Android调试桥&#xff08;ADB&#xff09;是一种多功能命令行工具&#xff0c;它允许开发者与连接到计算机上的Android设备进行通信和控制。ADB工具的作用包括但不限于&#xff1a; 安装和卸载应用程序&…

【纯血鸿蒙】——自适应布局如何实现?

界面级一多能力有 2 类&#xff1a; 自适应布局: 略微调整界面结构 响应式布局&#xff1a;比较大的界面调整 本文章先主要讲解自适应布局&#xff0c;响应式布局再后面文章再细讲。话不多说&#xff0c;开始了。 自适应布局 针对常见的开发场景&#xff0c;方舟开发框架提…

VS(visual studio)搭建QT开发环境插件安装

优先安装QT Qt6 官网QtCreator 下载与安装方法win10_qt6下载-CSDN博客 如果安装vs2019,打开installer,安装c环境 选择c 下载vsix后&#xff0c;双击安装即可。 插件下载&#xff1a; Index of /qtproject/official_releases/vsaddin/ 创建QT项目&#xff1a; 创建完成&…

力扣560. 和为 K 的子数组

Problem: 560. 和为 K 的子数组 文章目录 题目描述思路复杂度Code 题目描述 思路 1.初始化一个哈希表preSum&#xff0c;用于记录前缀和及其出现次数,ans记录和为k的子数组数量、sum_i记录当前前缀和&#xff1b; 2.将前缀和为 0 的情况存入哈希表&#xff0c;表示前缀和为 0 出…

Spring boot项目

一. Spring boot 安装地址 https://start.spring.io/ 二. 选择 三. idea配置 找到下载的文件解压缩&#xff0c;打开pom.xml(选择从idea打开)

Django与MySQL:配置数据库的详细步骤

文章目录 Django-MySQL 配置配置完执行数据迁移&#xff0c;如果报错: Error loading MySQLdb module&#xff0c; Django-MySQL 配置 # settings.pyDATABASES {# 默认配置sqlite3数据库# default: {# ENGINE: django.db.backends.sqlite3,# NAME: BASE_DIR / db.sqli…

初识BootLoader(二)

BootLoader的功能 BootLoader&#xff0c;通常是驻留在ECU非易失性存储器&#xff08;NVM&#xff0c;None Valitale Momory&#xff09;中的一段程序加载代码&#xff0c;每次ECU复位后&#xff0c;都会运行bootloader。它会检查是否有来自通信总线的远程程序加载请求&#x…

一个 buffer 使用的负反馈实例

端到端拥塞控制其实就是负反馈的实施。典型的做法是识别到一系列标志性事件&#xff0c;比如丢包&#xff0c;时延增加等&#xff0c;然后对这些事件做反应&#xff0c;进而形成负反馈&#xff0c;但 inflight 守恒是一种完全不同的做法&#xff0c;它将负反馈平铺到了整个传输…

所谓自律,就是去对抗那些廉价的快乐

所谓自律&#xff0c;就是去对抗那些廉价的快乐 以下文章来源于洞见 &#xff0c;作者洞见 导语 打败内心那只及时享乐的猴子。 董宇辉说过这样一句话&#xff1a;“廉价的快乐是直接给你想要的东西&#xff0c;高等的快乐则会给你设置重重阻碍。” 廉价的快乐&#xff0c;就…