穿透
穿透软链接:直接查看[原始文件]的状态信息
不穿透(追踪)软链接:查看的是当前软连接文件的信息
int stat(const char *pathname, struct stat *buf);
int lstat(const char *pathname, struct stat *buf);
int fstat(int fd, struct stat *buf); //参数fd
lstat
lstat和stat的区别:lstat不穿透,stat穿透
stat
int stat(const char *restrict path, struct stat *restrict buf);
返回值:
成功:0
失败:-1,errno被设置为合适的值
struct stat {
dev_t st_dev; /* ID of device containing file */文件设备编号
ino_t st_ino; /* inode number */节点
mode_t st_mode; 文件类型和存取权限
nlink_t st_nlink;/* number of hard links */硬链接数
uid_t st_uid; 用户ID
gid_t st_gid; 组ID
dev_t st_rdev; /* device ID (if special file) */设备编号(if is 设备文件)
off_t st_size; 文件字节数(文件大小)
blksize_t st_blksize; /* blocksize for filesystem I/O */块大小
blkcnt_t st_blocks; /* number of 512B blocks allocated */块数
struct timespec st_atim; /* time of last access */最后一次访问时间
struct timespec st_mtim; 最后一次修改时间
struct timespec st_ctim; /* time of last status change */最后一次改变时间
};
mode_t st_mode; 文件类型和存取权限的解读,是16bit的整数
文件类型 特殊权限位 User Group Others
占据位数 4 3 3 3 3
gus rwx rwx rwx
0-2bit——其他人权限
S_IROTH 00004 读权限
S_IWOTH 00002 写权限
S_IXOTH 00001 执行权限
S_IRWXO 00007 掩码,过滤st_mode中除其他人权限以外的信息
3-5bit——所属组权限
S_IRGRP 00040 读权限
S_IWGRP 00020 写权限
S_IXGRP 00010 执行权限
S_IRWXG 00070 掩码,过滤st_mode中除所属组权限以外的信息
6-8bit——所有者权限
S_IRUSR 00040 读权限
S_IWUSR 00020 写权限
S_IXUSR 00010 执行权限
S_IRWXU 00070 掩码,过滤st_mode中除所有者权限以外的信息
12-15——文件类型
S_IFSOCK 0140000套接字
S_IFLNK 0120000符号链接(软连接)
S_IFREG 0100000普通文件
S_IFDIR 0040000目录
S_IFCHR 0020000字符设备
S_IFIFO 0010000管道
S_IFMT 0170000掩码,过滤st_mode中除文件类型以外的信息
判断文件类型:
(st_mode & S_IFMT)==S_IFREG 判断文件是否为普通文件
[例]打印文件所有者对文件的访问权限; 判断文件是否为普通文件
int main(){
struct stat st;
int ret=stat("test",&st);
if(ret==-1){
perror("stat fail");
exit(1);
}
//文件大小
printf("file size = %d\n",st.st_size);
//判断文件是否为普通文件
if((st.st_mode & S_IFMT) == S_IFREG)
printf("file是普通文件\n");
else
printf("file不是普通文件\n");
//获取文件的user的访问权限
printf("the user's rwx is :");
if(st.st_mode & S_IRUSR)
printf("r");
else
printf("-");
if(st.st_mode & S_IWUSR)
printf("w");
else
printf("-");
if(st.st_mode & S_IXUSR)
printf("x");
else
printf("-");
printf("\n");
return 0;
}
综合案例
使用lstat函数,实现ls -l
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <string.h>
#include <time.h>
#include <pwd.h>
#include <grp.h>
int main(int args,char* argv[]){
if(args<2){
perror("argc<2");
exit(1);
}
struct stat st;
int ret=lstat(argv[1],&st);
if(ret==-1){
perror("lstat fail");
exit(-1);
}
char perm[11]={0};
//判断文件类型
switch(st.st_mode&S_IFMT){
case S_IFLNK:
perm[0]='l';
break;
case S_IFDIR:
perm[0]='d';
break;
case S_IFREG:
perm[0]='-';
break;
case S_IFBLK:
perm[0]='b';
break;
case S_IFCHR:
perm[0]='c';
break;
case S_IFSOCK:
perm[0]='s';
break;
case S_IFIFO:
perm[0]='p';
break;
default:
perm[0]='?';
break;
}
//User的访问权限
perm[1]=(st.st_mode & S_IRUSR)?'r':'-';
perm[2]=(st.st_mode & S_IWUSR)?'w':'-';
perm[3]=(st.st_mode & S_IXUSR)?'x':'-';
//Group的访问权限
perm[4]=(st.st_mode & S_IRGRP)?'r':'-';
perm[5]=(st.st_mode & S_IWGRP)?'w':'-';
perm[6]=(st.st_mode & S_IXGRP)?'x':'-';
//Other的访问权限
perm[7]=(st.st_mode & S_IROTH)?'r':'-';
perm[8]=(st.st_mode & S_IWOTH)?'w':'-';
perm[9]=(st.st_mode & S_IXOTH)?'x':'-';
//硬链接数目
int linkNum=st.st_nlink;
//文件所属者的name
char* fileUser=getpwuid(st.st_uid)->pw_name; //getpwuid函数:将uid转换成uname
//文件所属组的name
char* fileGrp=getgrgid(st.st_gid)->gr_name;//getgrgid函数:将gid转换成gname
//文件大小
int fileSize=(int)st.st_size;
//文件的修改时间:change time
char* time=ctime(&st.st_mtime);
char* mtime[512]={0};
strncpy(mtime,time,strlen(time)-1);
//打印最终的结果
char buf[1024];
sprintf(buf,"%s %d %s %s %d %s %s",perm,linkNum,fileUser,fileGrp,fileSize,mtime,argv[1]);
printf("%s\n",buf);
return 0;
}