😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍Linux下获取文件元数据的几个函数 | stat、fstat、lstat🍭
😎金句分享😎:🍭你不能选择最好的,但最好的会来选择你——泰戈尔🍭
本文未经允许,不得转发!!!
目录
- 🎄一、概述
- 🎄二、stat 函数
- 🎄三、fstat 函数
- 🎄四、lstat 函数
- 🎄五、总结
🎄一、概述
文件的元数据包含了一些描述文件的信息,包括文件的访问权限、 上次访问的时间戳、 所有者、 所有组、 文件大小等信息。
本文将介绍获取文件元数据的几个函数:stat、fstat、lstat。
首先看一下获取文件元数据的结构体:
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
};
结构体成员就不逐个解释了,可以看看英文注释。值得一提的是,在Linux内核版本2.6之后,struct stat
结构体支持纳秒级别时间了,使用了成员st_atim、st_mtim、st_ctim
代替了旧的成员st_atime、st_mtime、st_ctime
。
还有一点需要注意:st_mode字段可以通过下面宏来判断文件类型:
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.)
下面这些宏定义了 st_mode 字段各个文件类型的bit位
S_IFMT 0170000 bit mask for the file type bit fields 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 S_ISUID 0004000 set-user-ID bit S_ISGID 0002000 set-group-ID bit (see below) S_ISVTX 0001000 sticky bit (see below) S_IRWXU 00700 mask for file owner permissions S_IRUSR 00400 owner has read permission S_IWUSR 00200 owner has write permission S_IXUSR 00100 owner has execute permission S_IRWXG 00070 mask for group permissions S_IRGRP 00040 group has read permission S_IWGRP 00020 group has write permission S_IXGRP 00010 group has execute permission S_IRWXO 00007 mask for permissions for others (not in group) S_IROTH 00004 others have read permission S_IWOTH 00002 others have write permission S_IXOTH 00001 others have execute permission
🎄二、stat 函数
stat 函数原型:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
成功返回0;失败返回-1
stat 函数根据pathname
路径的文件名,通过statbuf
参数返回此文件的信息结构。
参数:
- pathname:文件路径名称,输入参数
- statbuf:
struct stat
结构信息指针,输出参数、
看例子:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
int main()
{
struct stat s = {0};
int res = stat("a.txt", &s);//s会被填满
if(res == -1)
{
perror("stat");
return -1;
}
printf("inode: %d\n", (int)(s.st_ino));
printf("读写权限:%#o\n", s.st_mode & 0777);
printf("file size %d\n", (int)(s.st_size));
printf("%lu \n",s.st_atim.tv_nsec);
if(S_ISREG(s.st_mode))
{
printf("普通文件");
}
else if(S_ISDIR(s.st_mode))
{
printf("目录文件");
}
else if(S_ISLNK(s.st_mode))
{
printf("软链接文件");
}
printf("\n");
return 0;
}
保存代码后编译,然后在当前目录通过touch a.txt
创建一个a.txt,然后运行。
🎄三、fstat 函数
fstat 函数原型:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int fstat(int fd, struct stat *statbuf);
成功返回0;失败返回-1
fstat 函数根据已打开的fd
文件描述符,通过statbuf
参数返回此文件的信息结构。
参数:
- fd:已打开的
fd
文件描述符,输入参数 - statbuf:
struct stat
结构信息指针,输出参数、
看例子:
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
struct stat s = {0};
int fd = open("a.txt", O_RDWR | O_CREAT | O_TRUNC, 0664);
int res = fstat(fd, &s);//s会被填满
if(res == -1)
{
perror("stat");
return -1;
}
printf("inode: %d\n", (int)(s.st_ino));
printf("读写权限:%#o\n", s.st_mode & 0777);
printf("file size %d\n", (int)(s.st_size));
printf("%lu \n",s.st_atim.tv_nsec);
if(S_ISREG(s.st_mode))
{
printf("普通文件");
}
else if(S_ISDIR(s.st_mode))
{
printf("目录文件");
}
else if(S_ISLNK(s.st_mode))
{
printf("软链接文件");
}
printf("\n");
return 0;
}
🎄四、lstat 函数
lstat 函数原型:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int lstat(const char *pathname, struct stat *statbuf);
成功返回0;失败返回-1
lstat 函数类似于stat
,但是当命名的文件是一个符号链接时,lstat
返回该符号链接的有关信息,而不是由该符号链接引用的文件的信息。
参数:
- path:文件路径名称,输入参数
- buf:
struct stat
结构信息指针,输出参数、
看例子:
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/sysmacros.h>
int main(int argc, char *argv[])
{
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (lstat(argv[1], &sb) == -1) {
perror("lstat");
exit(EXIT_FAILURE);
}
printf("ID of containing device: [%lx,%lx]\n",
(long) major(sb.st_dev), (long) minor(sb.st_dev));
printf("File type: ");
switch (sb.st_mode & S_IFMT) {
case S_IFBLK: printf("block device\n"); break;
case S_IFCHR: printf("character device\n"); break;
case S_IFDIR: printf("directory\n"); break;
case S_IFIFO: printf("FIFO/pipe\n"); break;
case S_IFLNK: printf("symlink\n"); break;
case S_IFREG: printf("regular file\n"); break;
case S_IFSOCK: printf("socket\n"); break;
default: printf("unknown?\n"); break;
}
printf("I-node number: %ld\n", (long) sb.st_ino);
printf("Mode: %lo (octal)\n",
(unsigned long) sb.st_mode);
printf("Link count: %ld\n", (long) sb.st_nlink);
printf("Ownership: UID=%ld GID=%ld\n",
(long) sb.st_uid, (long) sb.st_gid);
printf("Preferred I/O block size: %ld bytes\n",
(long) sb.st_blksize);
printf("File size: %lld bytes\n",
(long long) sb.st_size);
printf("Blocks allocated: %lld\n",
(long long) sb.st_blocks);
printf("Last status change: %s", ctime(&sb.st_ctime));
printf("Last file access: %s", ctime(&sb.st_atime));
printf("Last file modification: %s", ctime(&sb.st_mtime));
exit(EXIT_SUCCESS);
}
上面的代码调用lstat
,并在返回的stat结构中显示选定的字段。
🎄五、总结
本文介绍了struct stat
结构体,以及获取文件元数据的几个函数 :stat、fstat、lstat。
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁