通过文件属性实现linux下 “ls -l“ 功能

结构体介绍

struct stat
{
dev_t st_dev; /* ID of device containing file -文件所在设备的ID*/
ino_t st_ino; /* inode number -inode节点号*/
mode_t st_mode; /* protection -保护模式?/
nlink_t st_nlink; /
number of hard links -链向此文件的连接数(硬连接)/
uid_t st_uid; /
user ID of owner -user id*/
gid_t st_gid; /* group ID of owner - group id*/
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 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 - */
};

stat结构体是文件(夹)信息的结构体

实现思路:

ls - l 结构

ls -l 示例
解释:

  1. 第一列共10位,第1位表示文档类型,d表示目录,-表示文件,l表示链接文件,d表示可随机存取的设备,如U盘等,c表示一次性读取设备,如鼠标、键盘等。后9位,依次对应三种身份所拥有的权限,身份顺序为:owner、group、others,权限顺序为:readable、writable、excutable。如:-r-xr-x—的含义为当前文档是一个文件,拥有者可读、可执行,同一个群组下的用户,可读、可执行,其他人没有任何权限。
  2. 第二列表示链接数,表示有多少个文件链接到inode号码。
  3. 第三列表示拥有者
  4. 第四列表示所属群组
  5. 第五列表示文档容量大小,单位字节
  6. 第六列表示文档最后修改时间,注意不是文档的创建时间哦
  7. 第七列表示文档名称。以点(.)开头的是隐藏文档

具体实现

主函数

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

int main(int argc,char* argv[])    //通过一个参数传入文件名
{
	if(argc < 2)
	{
		printf("please enter %s file",argv[0]);
		return -1;
	}
	struct stat buf;
	int ret;
	ret = stat(argv[1],&buf);
	if(0 != ret)
	{
		perror("stat");
		return -1;
	}
	fltype(&buf);                  //输出文件类型
	flmode(&buf);                  //输出文件权限
	printf("%ld ",buf.st_nlink);   //输出文件链接数
	fluser(&buf);                  //输出文件拥有者和所属群组
	printf("%ld ",buf.st_size);    //输出文件大小
	fltime(&buf);                  //输出文件修改时间
	printf("%s\n",argv[1]);        //输出文件名
	return 0;
} 

得到文件类型


void fltype(struct stat* buf)
{
	 
	if((buf->st_mode & S_IFMT) == S_IFREG) printf("-");//普通文件
	else if((buf->st_mode & S_IFMT) == S_IFSOCK) printf("s");//套接字文件
	else if((buf->st_mode & S_IFMT) == S_IFBLK) printf("b"); //块设备文件 
	else if((buf->st_mode & S_IFMT) == S_IFDIR) printf("d"); //目录文件
	else if((buf->st_mode & S_IFMT) == S_IFCHR) printf("c"); //字符设备文件
	else if((buf->st_mode & S_IFMT) == S_IFIFO) printf("p");//管道文件
	else if((buf->st_mode & S_IFMT) == S_IFLNK) printf("l");//链接文件

	else printf("未知文件类型");
}

#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#define S_ISBLK(m) (((m) & S_IFMT) == S_IFBLK)
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
#define S_ISNAM(m) (((m) & S_IFMT) == S_IFNAM)
#if !defined(_M_XOUT)
#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
定义有如上宏,上述代码也可用宏替换

得到文件权限

void flmode(struct stat* buf)
{
	for(int i = 8;i >= 0;i--)
	{
		if(buf->st_mode & 1 << i)
		{
			if(i % 3 == 2) printf("r");
			else if(i % 3 == 1) printf("w");
			else printf("x");
		}
		else printf("-");
	}
	printf(" ");
}

解释:
rwxrwxrwx 对应 111111111,九位数分别对应相应权限,1为有权限,0为无权限,上图中rw-r–r–对应110100100,博主通过按位与对比实现

得到文件拥有者和群组

void fluser(struct stat* buf)
{
	struct passwd *p_uid = getpwuid(buf->st_uid);//通过uid查找用户信息并保存在passwd结构体中
	printf("%s ",p_uid->pw_name);
	struct group *g_gid = getgrgid(buf->st_gid);通过gid查找群组信息并保存在group结构体中
	printf("%s ",g_gid->gr_name);

}

得到上一次修改时间

oid fltime(struct stat* buf)
{
	struct tm *tp = localtime(&buf->st_mtime);
	printf("%2d月%3d%3d:%02d ",
			tp->tm_mon + 1,
			tp->tm_mday,
			tp->tm_hour,
			tp->tm_min,
			tp->tm_sec);
}

结果展示:

结果展示

利用stat结构体的文件信息实现了ls -l的部分功能,主要是加强对stat结构体的理解

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值