stat函数

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;
}

运行结果如下:

在这个实现中,除了时间,其余的都实现了。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券