获取文件属性 stat() fstat() lstat()
1 概述
1)linux系统下,一切皆文件,共有7种类型:普通文件、目录文件、管道文件、可执行文件、压缩文件、设备文件(字符、管道和块)和其他文件。
2) linux下通过ls命令查询文件信息,可通过stat相关函数查询出来或stat + 文件名命令
2 函数声明
- int stat(const char *path, struct stat *buf);
- 入参*path: 文件的路径
- 出参*buf: 文件信息
- 返回值: 0 - 成功,-1 - 失败
- int fstat(int fd, struct stat *buf);
- 入参fd: 文件描述符
- 出参*buf: 文件信息
- 返回值: 0 - 成功,-1 - 失败
- int lstat(const char *path, struct stat *buf);
- 入参*path: 文件的路径
- 出参*buf: 文件信息
- 返回值: 0 - 成功,-1 - 失败
说明:
- 执行失败时,error有如下定义:
EBADF: 文件描述词无效
EFAULT:地址空间不可访问
ELOOP:遍历路径时遇到太多的符号连接
ENAMETOOLONG:文件路径名太长
ENOENT:路径名的部分组件不存在或路径名是空字符串
ENOMEM:内存不足
ENOTDIR:路径名的部分组件不是目录 - stat和lstat通过文件路径和文件名访问文件, fstat是通过文件描述符获取文件属性
- 文件本身没有权限限制,文件的上层目录必须有访问权限才能获取到文件属性
- 文件是符号链接时,lstat返回的是该符号链接本身的信息,而stat返回的是该符号链接指向的文件的信息
3 stat结构体
执行man 2 stat查询结构体定义
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection 文件的类型和权限*/
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; /* blocksize 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
};
mode_t st_mode 为16位的short类型,对应的16位标志位
通过与S_IFMT掩码,可获取文件类型
S_IFMT 0170000 //掩码,过滤st_mode中除文件类型以外的信息
S_IFSOCK 0140000 //套接字
S_IFLNK 0120000 //符号链接(软链接)
S_IFREG 0100000 //普通文件
S_IFBLK 0060000 //块设备
S_IFDIR 0040000 //目录文件
S_IFCHR 0020000 //字符设备
S_IFIFO 0010000 //管道
S_ISUID 0004000 //设置用户ID
S_ISGID 0002000 //设置组ID
S_ISVTX 0001000 //粘住位
S_IRWXU 00700 //掩码,过滤st_mode除文件所有者权限以外的信息
S_IRUSR 00400 //用户读权限
S_IWUSR 00200 //用户写权限
S_IXUSR 00100 //用户执行权限
S_IRWXG 00070 //掩码,过滤st_mode除所属组权限以外的信息
S_IRGRP 00040 //读权限
S_IWGRP 00020 //写权限
S_IXGRP 00010 //执行权限
S_IRWXO 00007 //掩码,过滤st_mode除其他*限以外的信息
S_IROTH 00004 //读权限
S_IWOTH 00002 //写权限
S_IXOTH 00001 //执行权限
4 代码示例
示例1:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
void test_stat()
{
struct stat st;
int ret = -1;
ret = stat("test_basic.c", &st);
if(-1 == ret)
{
perror("stat fail.\n");
return;
}
printf("file size: %lld.\n", (long long)st.st_size);
printf("file device: %ld.\n", (long)st.st_dev);
printf("file blocks: %lld.\n", (long long)st.st_blocks);
printf("file node: %ld.\n", (long)st.st_ino);
printf("file hardlink: %ld.\n", (long)st.st_nlink);
printf("file user id: %ld.\n", (long)st.st_uid);
printf("file group id: %ld.\n", (long)st.st_gid);
return;
}
int main(int argc, char *argv[])
{
test_stat();
return 0;
}
gcc test_basic.c -o test_basic 编译
运行结果:
示例2:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
void test_stat02(int argc, char *argv[])
{
struct stat sb;
if (argc != 2) {
fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
exit(EXIT_FAILURE);
}
if (stat(argv[1], &sb) == -1) {
perror("stat");
exit(EXIT_FAILURE);
}
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);
}
int main(int argc, char *argv[])
{
//test_stat();
test_stat02(argc, argv);
return 0;
}
运行结果:
上一篇: Java常用日志框架介绍