linux 文件属性信息(stat/fstat/lstat)

本章主要讲解linux 中 stat函数,另外两个函数fstat和lstat功能和stat函数差不多就不做过多的讲解。

fstat函数与stat函数区别主要在于:fstat只获取普通文件的属性信息,看fstat输入参数便可知
lstat函数与stat函数区别主要在于:lstat获取文件属性中软链接信息是软连接文件本身的属性信息,而stat获取的是软链接文件关联的文件的属性信息

fstat函数和lstat函数原型如下:

int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

1.stat函数介绍

/*************************************************
** description:获取文件属性信息
** parameter:
		** *pathname:文件路径下文件名字,要被获取属性信息的文件
		** *statbuf:获取到的文件属性信息将存放在该内存内
** return:成功:0, 失败:-1;
**************************************************/
int stat(const char *pathname, struct stat *statbuf);


//struct stat
struct stat {
    dev_t       st_dev;        	// 文件的设备编号
    ino_t       st_ino;        	// inode节点
    mode_t      st_mode;      	// 文件的类型和存取的权限, 16位整形数  -> 常用
    nlink_t     st_nlink;     	// 连到该文件的硬连接数目,刚建立的文件值为1
    uid_t       st_uid;       	// 用户ID
    gid_t       st_gid;       	// 组ID
    dev_t       st_rdev;      	// (设备类型)若此文件为设备文件,则为其设备编号
    off_t       st_size;      	// 文件字节数(文件大小)   --> 常用
    blksize_t   st_blksize;   	// 块大小(文件系统的I/O 缓冲区大小)
    blkcnt_t    st_blocks;    	// block的块数
    time_t      st_atime;     	// 最后一次访问时间
    time_t      st_mtime;     	// 最后一次修改时间(文件内容)
    time_t      st_ctime;     	// 最后一次改变时间(指属性)
};

2. 获取文件类型的宏定义函数
文件的类型信息存储在 struct stat 结构体的 st_mode 成员中,它是一个 mode_t 类型,本质上是一个 16 位的整数。Linux API 中为我们提供了相关的宏函数,通过对应的宏函数可以直接判断出文件是不是某种类型

// 类型是存储在结构体的这个成员中: mode_t  st_mode;  
// 这些宏函数中的m 对应的就是结构体成员  st_mode
// 宏函数返回值: 是对应的类型返回-> 1, 不是对应类型返回0

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.) 

3.获取文件权限
在 stat函数获取到的文件属性struct stat结构体中st_mode 元素记录了该文件的权限,st_mode (16bit长度:0-15bit)中每一个bit都有它的含义,0-2bit:其他人权限, 3-5bit:所属组用户权限,6-8bit:所有者权限, 9-11bit:特殊权限, 12-15bit:文件类型。linux中为方便用于获取对应bit的值,已宏定义每一bit,使用宏定义按位与(&)st_mode 即可获取对应bit的状态值。
宏定义如下所示:

关于变量 st_mode: 
- st_mode -- 16位整数
	○ 0-2 bit -- 其他人权限
		- S_IROTH    0x0004  读权限   100
		- S_IWOTH    0x0002  写权限   010
		- S_IXOTH    0x0001  执行权限  001
		- S_IRWXO    0x0007  掩码, 过滤 st_mode中除其他人权限以外的信息
	○ 3-5 bit -- 所属组权限
		- S_IRGRP    0x0020  读权限
		- S_IWGRP    0x0010  写权限
		- S_IXGRP    0x0008  执行权限
		- S_IRWXG    0x0038  掩码, 过滤 st_mode中除所属组权限以外的信息
	○ 6-8 bit -- 文件所有者权限
		- S_IRUSR    0x0100    读权限
		- S_IWUSR    0x0080    写权限
		- S_IXUSR    0x0040    执行权限
		- S_IRWXU    0x01C0    掩码, 过滤 st_mode中除文件所有者权限以外的信息
	○ 12-15 bit -- 文件类型
		- S_IFSOCK   0xC000 套接字
		- S_IFLNK    0xA000 符号链接(软链接)
		- S_IFREG    0x8000 普通文件
		- S_IFBLK    0x6000 块设备
		- S_IFDIR    0x4000 目录
		- S_IFCHR    0x2000 字符设备
		- S_IFIFO    0x1000 管道
		- S_IFMT     0xF000 掩码,过滤 st_mode中除文件类型以外的信息

4.举例代码

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>

void stat_st_mode_define(void)
{
	printf("其他人权限:\n");
	printf("S_IROTH:%04X\n", S_IROTH);		//读权限
	printf("S_IWOTH:%04X\n", S_IWOTH);		//写权限
	printf("S_IXOTH:%04X\n", S_IXOTH);		//执行权限
	printf("S_IRWXO:%04X\n\n", S_IRWXO);	//掩码, 过滤 st_mode中除其他人权限以外的信息
	
	printf("所属组权限:\n");
	printf("S_IRGRP:%04X\n", S_IRGRP);		//读权限
	printf("S_IWGRP:%04X\n", S_IWGRP);		//写权限
	printf("S_IXGRP:%04X\n", S_IXGRP);		//执行权限
	printf("S_IRWXG:%04X\n\n", S_IRWXG);	//掩码, 过滤 st_mode中除所属组权限以外的信息
	
	printf("文件所有者权限:\n");
	printf("S_IRUSR:%04X\n", S_IRUSR);		//读权限
	printf("S_IWUSR:%04X\n", S_IWUSR);		//写权限
	printf("S_IXUSR:%04X\n", S_IXUSR);		//执行权限
	printf("S_IRWXU:%04X\n\n", S_IRWXU);	//掩码, 过滤 st_mode中除文件所有者权限以外的信息
	
	printf("文件类型:\n");
	printf("S_IFSOCK:%04X\n", S_IFSOCK);	//套接字
	printf("S_IFLNK:%04X\n", S_IFLNK);		//符号链接(软链接)
	printf("S_IFREG:%04X\n", S_IFREG);		//普通文件
	printf("S_IFBLK:%04X\n", S_IFBLK);		//块设备
	printf("S_IFDIR:%04X\n", S_IFDIR);		//目录
	printf("S_IFCHR:%04X\n", S_IFCHR);		//字符设备
	printf("S_IFIFO:%04X\n", S_IFIFO);		//管道
	printf("S_IFMT:%04X\n\n", S_IFMT);		//掩码,过滤 st_mode中除文件类型以外的信息
}
int main(int argc, char *argv[])
{	

    struct stat myst;
	char perms[12] = {0};

	stat_st_mode_define();

	if(-1 == stat("/home/linux", &myst))
	{
		fprintf(stderr, "stat read file failed :%s\n", strerror(errno));
		return -1;
	}
	
	printf("st_mode:%04X\n", myst.st_mode);
	
	if(S_ISDIR(myst.st_mode))
	{
		printf("文件类型:目录\n");
	}
	
	if(S_ISREG(myst.st_mode))
	{
		printf("文件类型:普通文件\n");
	}
	
    switch(myst.st_mode & S_IFMT)	// 判断文件类型
    {
		case S_IFIFO:
            perms[0] = 'p';
            break;
		case S_IFCHR:
            perms[0] = 'c';
            break;
		case S_IFDIR:
            perms[0] = 'd';
            break;
		case S_IFBLK:
            perms[0] = 'b';
            break;
		case S_IFREG:
            perms[0] = '-';
            break;	
        case S_IFLNK:
            perms[0] = 'l';
            break;
        case S_IFSOCK:
            perms[0] = 's';
            break;
        default:
            perms[0] = '?';
            break;
    }
	
    /*** 判断文件的访问权限 ***/
	
    // 文件所有者
    perms[1] = (myst.st_mode & S_IRUSR) ? 'r' : '-';
    perms[2] = (myst.st_mode & S_IWUSR) ? 'w' : '-';
    perms[3] = (myst.st_mode & S_IXUSR) ? 'x' : '-';
	
    // 文件所属组
    perms[4] = (myst.st_mode & S_IRGRP) ? 'r' : '-';
    perms[5] = (myst.st_mode & S_IWGRP) ? 'w' : '-';
    perms[6] = (myst.st_mode & S_IXGRP) ? 'x' : '-';
	
    // 其他人
    perms[7] = (myst.st_mode & S_IROTH) ? 'r' : '-';
    perms[8] = (myst.st_mode & S_IWOTH) ? 'w' : '-';
    perms[9] = (myst.st_mode & S_IXOTH) ? 'x' : '-';
	
	printf("文件类型与权限:%s\n",(char *)perms);
	printf("linkNum:%ld\n", myst.st_nlink);					// 硬链接计数
	printf("fileUser:%s\n", getpwuid(myst.st_uid)->pw_name);	// 文件所有者
	printf("fileGrp:%s\n", getgrgid(myst.st_gid)->gr_name);	// 文件所属组	
	printf("stat read file size: %d\n", (int)myst.st_size);	// 文件大小 
	
	printf("最后一次访问时间:%s\n", ctime(&myst.st_atime));
	printf("最后一次修改时间(文件内容):%s\n", ctime(&myst.st_mtime));
	printf("最后一次改变时间(指属性):%s\n", ctime(&myst.st_ctime));

	return 0;
}

打印信息如下:

其他人权限:
S_IROTH:0004
S_IWOTH:0002
S_IXOTH:0001
S_IRWXO:0007

所属组权限:
S_IRGRP:0020
S_IWGRP:0010
S_IXGRP:0008
S_IRWXG:0038

文件所有者权限:
S_IRUSR:0100
S_IWUSR:0080
S_IXUSR:0040
S_IRWXU:01C0

文件类型:
S_IFSOCK:C000
S_IFLNK:A000
S_IFREG:8000
S_IFBLK:6000
S_IFDIR:4000
S_IFCHR:2000
S_IFIFO:1000
S_IFMT:F000

st_mode:41ED
文件类型:目录
文件类型与权限:drwxr-xr-x
linkNum:17
fileUser:linux
fileGrp:linux
stat read file size: 4096
最后一次访问时间:Sat Dec 11 09:09:41 2021

最后一次修改时间(文件内容):Sat Dec 11 09:09:01 2021

最后一次改变时间(指属性):Sat Dec 11 09:09:01 2021

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值