一、struct stat 概述
struct stat
是一个 C 语言中的结构体,它包含了 Unix 和类 Unix 系统中文件状态的所有信息。struct stat
用于查询文件的各种属性信息,比如大小、权限、时间戳等。在 Unix 和类 Unix 系统中,struct stat
结构体十分常见和有用。
stat
系统调用是 Unix 和类 Unix 系统中最常用的系统调用之一。它用于获取文件的元数据,并将其存储在 struct stat
结构体中。元数据包括文件类型、大小、属性、访问时间、修改时间等。struct stat
结构体定义如下:
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 */
time_t st_atime; /* Time of last access */
time_t st_mtime; /* Time of last modification */
time_t st_ctime; /* Time of last status change */
};
我们可以通过 Manipulating File Attributes 和 Stat() 两篇官方文档了解如何使用 struct stat
获取文件信息。
二、使用 StructStatVfs 获取文件系统信息
struct stat
不仅可以用于获取文件的属性信息,还可以用于获取文件系统的相关信息。可以使用下面列出的函数来获取完全的 stat
结构,也可以使用较简单的基本信息函数(如 st_size
、st_mtime
等)来获取部分信息。
1. statvfs()
statvfs()
函数是一个 Unix 系统调用,用于检索文件系统的状态(特别是容量)。它返回一个 struct statvfs
结构体,其中包含文件系统的各种信息。struct statvfs
定义如下:
struct statvfs {
unsigned long f_bsize; /* file system block size */
unsigned long f_frsize; /* fragment size */
fsblkcnt_t f_blocks; /* size of fs in f_frsize units */
fsblkcnt_t f_bfree; /* free blocks in fs */
fsblkcnt_t f_bavail; /* free blocks avail to non-superuser */
fsfilcnt_t f_files; /* total file nodes in file system */
fsfilcnt_t f_ffree; /* free file nodes in fs */
fsfilcnt_t f_favail; /* free file nodes avail to non-superuser */
unsigned long f_fsid; /* file system id */
unsigned long f_flag; /* mount flags */
unsigned long f_namemax; /* maximum filename length */
};
我们可以使用下面这个使用案例看一下如何使用 statvfs()
函数,使用该函数返回当前文件系统(root 文件系统)的容量信息。
#include <stdio.h>
#include <sys/statvfs.h>
int main() {
struct statvfs stats;
statvfs("/", &stats);
printf("File system block size: %ld\n", stats.f_bsize);
printf("Fragment size: %ld\n", stats.f_frsize);
printf("Total blocks (in f_frsize units): %ld\n", stats.f_blocks);
printf("Free blocks available to non-superuser: %ld\n", stats.f_bavail);
printf("Total file nodes (in f_frsize units): %ld\n", stats.f_files);
printf("Free file nodes (in f_frsize units): %ld\n", stats.f_ffree);
printf("Max filename length: %ld\n", stats.f_namemax);
return 0;
}
2. fstatvfs()
fstatvfs()
函数也是用于检索文件系统的状态(特别是容量)。它和 statvfs()
函数的用法几乎一模一样,只是它使用的是文件描述符(fd)来代替文件名。我们可以使用下面这个使用案例看一下如何使用 fstatvfs()
函数,使用该函数返回当前进程所在文件系统的容量信息。
#include <stdio.h>
#include <sys/statvfs.h>
#include <unistd.h>
int main() {
int fd;
struct statvfs stats;
fd = open(".", O_RDONLY);
fstatvfs(fd, &stats);
close(fd);
printf("File system block size: %ld\n", stats.f_bsize);
printf("Fragment size: %ld\n", stats.f_frsize);
printf("Total blocks (in f_frsize units): %ld\n", stats.f_blocks);
printf("Free blocks available to non-superuser: %ld\n", stats.f_bavail);
printf("Total file nodes (in f_frsize units): %ld\n", stats.f_files);
printf("Free file nodes (in f_frsize units): %ld\n", stats.f_ffree);
printf("Max filename length: %ld\n", stats.f_namemax);
return 0;
}
三、使用 StructStat 获取文件信息
我们可以使用下面列出的使用案例来获取文件的信息:
#include <stdio.h>
#include <sys/stat.h>
int main() {
struct stat sb;
if (stat("/etc/passwd", &sb) == -1) {
perror("stat");
return 1;
}
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));
return 0;
}
四、使用 StructStat 在 Windows 系统中获取文件信息
在 Windows 系统中,我们可以使用下面列出的使用案例来获取文件的信息:
#include <windows.h>
#include <stdio.h>
#include <sys/stat.h>
int main() {
struct _stat buffer;
int status;
status = _stat("C:\\file.txt", &buffer);
if (status == 0) {
printf("File size: %ld bytes\n", buffer.st_size);
printf("Creation date: %s", ctime(&buffer.st_ctime));
printf("Modification date: %s", ctime(&buffer.st_mtime));
printf("Access date: %s", ctime(&buffer.st_atime));
} else {
printf("File not found");
}
return 0;
}
五、使用 StructStat 在 MacOS 系统中获取文件信息
在 MacOS 系统中,我们可以使用下面的使用案例来获取文件的信息:
#include <sys/stat.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
int main() {
struct stat statbuf;
if (stat("/etc/passwd", &statbuf) == -1) {
perror("stat");
return -1;
}
printf("Size: %lld\n", statbuf.st_size);
printf("User ID: %d\n", statbuf.st_uid);
printf("Group ID: %d\n", statbuf.st_gid);
return 0;
}
六、小结
利用 struct stat
结构体可以轻松地获取到文件系统和文件的各种属性信息,可以方便地实现类 Unix 操作系统在使用过程中的代码控制。