stat函数可以给出文件的性质,也可以直接在shell下输入命令:stat 文件名。
我们可以看的文件的相关信息。 然后我们查看stat这个函数。使用man 2 stat。
其中参数statbuf是一个结构体指针。这个结构体中包含的成员如下:
文件类型信息包含在stat结构的st_mode成员中。这个成员的大小是2字节。它还包含了文件的权限信息。他的位结构如下:
15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|
0-2位:表示的是其他人的权限;
3-5位:表示的是文件所在组权限;
6-8位:表示的是文件拥有者的权限。
9-11位:特殊权限位。
12-15位:表示文件类型。
早期的Unix系统并没有提供S_ISxxx这样的宏来提取文件类型,我们只好使用屏蔽字S_IFMT(0170000)来进行按位与运算,这样就能提取到文件的类型。当然,提取文件权限的时候也可以使用类似的屏蔽字。
这个结构体中定义的宏是为了兼容性,2008年标准以前的时间都是time_t类型的(以秒来计),timespec则提供了更高精度的时间戳,为了保持兼容性,使用了宏定义将旧的名字定义为了tv_sec成员。
stat的成员st_size表示的是以字节为单位的文件长度,这个字段只对普通文件,目录文件和符号链接有用。对于Linux系统的普通文件,他的大小可以是0字节,例如用touch命令创建一个空文件,它的大小就是0.在Linux系统下,目录文件的大小总是4Kb。符号链接文件的大小表示的是原文件的文件名长度(包括路径长度)。例如:
以上使用的是UTF-8编码,故一般一个汉字占据3字节。所以总长度是24.
stat函数是一个穿透函数,它在读软链接的时候,会将软链接指向的文件的实际信息读取出来,而不是读取软链接本身的文件信息;而lstat函数不穿透,它就是读取软链接本身的文件信息。
下面仿照ls -l命令来基本实现一下该命令。使用lstat函数。
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char * argv[])
{
struct stat buf; //存放文件信息
char file_type; //文件类型
char file_mode[9] = {'-','-','-','-','-','-','-','-','-'}; //文件权限
int file_hardlink; //硬链接数
char uid[10]={0}; //文件拥有者
char gid[10]={0}; //文件所在组
int file_size; //文件大小
time_t file_lasttime; //最后一次修改时间
char *name; //文件名
lstat(argv[1],&buf); //获取文件信息
if (S_ISREG(buf.st_mode)) //普通文件
{
file_type = '-';
}
else if(S_ISDIR(buf.st_mode)) //目录文件
{
file_type = 'd';
}
else if(S_ISCHR(buf.st_mode)) //字符设备文件
{
file_type = 'c';
}
else if(S_ISBLK(buf.st_mode)) //块设备文件
{
file_type = 'b';
}
else if(S_ISFIFO(buf.st_mode)) //管道文件
{
file_type = 'p';
}
else if(S_ISLNK(buf.st_mode)) //链接文件
{
file_type = 'l';
}
if(buf.st_mode & S_IRUSR)
{
file_mode[0] = 'r';
}
if(buf.st_mode & S_IWUSR)
{
file_mode[1] = 'w';
}
if (buf.st_mode & S_IXUSR)
{
file_mode[2] = 'x';
}
if (buf.st_mode & S_IROTH)
{
file_mode[6] = 'r';
}
if (buf.st_mode & S_IWOTH)
{
file_mode[7] = 'w';
}
if (buf.st_mode & S_IXOTH)
{
file_mode[8] = 'x';
}
if (buf.st_mode & S_IWGRP)
{
file_mode[3] = 'r';
}
if (buf.st_mode & S_IRGRP)
{
file_mode[4] = 'w';
}
if (buf.st_mode & S_IXGRP)
{
file_mode[5] = 'x';
}
file_hardlink = buf.st_nlink; //硬链接数
if(buf.st_gid == 1000)
{
strcpy(gid,"zy");
}
else if (0 == buf.st_gid)
{
strcpy(gid,"root");
}
if(1000 == buf.st_uid)
{
strcpy(uid,"zy");
}
else if (0 == buf.st_uid)
{
strcpy(uid,"root");
}
file_size = buf.st_size;
name = argv[1];
printf("%c",file_type);
for(int i = 0; i < 9; i++)
{
printf("%c",file_mode[i]);
}
printf(" %d",file_hardlink);
printf(" %s",uid);
printf(" %s",gid);
printf(" %d",file_size);
printf(" %s\n",name);
return 0;
}
运行结果如下:
在这个实现中,除了时间,其余的都实现了。