欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

获取文件属性 stat() fstat() lstat()

程序员文章站 2022-05-24 15:29:25
...

1 概述

1)linux系统下,一切皆文件,共有7种类型:普通文件、目录文件、管道文件、可执行文件、压缩文件、设备文件(字符、管道和块)和其他文件。
2) linux下通过ls命令查询文件信息,可通过stat相关函数查询出来或stat + 文件名命令

2 函数声明

  1. int stat(const char *path, struct stat *buf);
    • 入参*path: 文件的路径
    • 出参*buf: 文件信息
    • 返回值: 0 - 成功,-1 - 失败
  2. int fstat(int fd, struct stat *buf);
    • 入参fd: 文件描述符
    • 出参*buf: 文件信息
    • 返回值: 0 - 成功,-1 - 失败
  3. 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位标志位
获取文件属性 stat() fstat() lstat()通过与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 编译
运行结果:
获取文件属性 stat() fstat() lstat()示例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;
}

运行结果:
获取文件属性 stat() fstat() lstat()

相关标签: linux函数