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