【Linux C | 文件操作】获取文件元数据的几个函数 | stat、fstat、lstat

2024-01-02 21:45:15

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
🤣本文内容🤣:🍭介绍Linux下获取文件元数据的几个函数 | 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。

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏?,支持一波,谢谢 😁😁😁

文章来源:https://blog.csdn.net/wkd_007/article/details/135315604
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。