C语言:stat、fstat、lstat函数使用方法

函数头文件及原型

查看man 2 stat男人:)手册:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

struct stat {
    dev_t     st_dev;     /* 包含文件的设备的ID */
    ino_t     st_ino;     /* inode值 */
    mode_t    st_mode;    /* 类型及权限 */
    nlink_t   st_nlink;   /* 硬链接数量 */
    uid_t     st_uid;     /* 所有者的用户ID */
    gid_t     st_gid;     /* 所有者的组ID */
    dev_t     st_rdev;    /* 设备ID(如果是特殊文件) */
    off_t     st_size;    /* 总大小,以byte为单位 */
    blksize_t st_blksize; /* 文件系统I/O的块大小 */
    blkcnt_t  st_blocks;  /* 分配的512B块数 */
    time_t    st_atime;   /* 最后访问时间 */
    time_t    st_mtime;   /* 最后修改时间 */
    time_t    st_ctime;   /* 上次状态更改的时间 */
};

int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

stat与lstat差别就在于l(link),stat会越过链接文件读取原文件,后者则读取链接文件。关于Linux环境的软硬链接可以参考:https://blog.csdn.net/weixin_44498318/article/details/105399439

可以使用以下宏传递结构体成员st_mode查看文件类型:

1
2
3
4
5
6
7
S_ISREG(m)      常规文件
S_ISDIR(m)      目录
S_ISCHR(m)      字符设备
S_ISBLK(m)      块设备
S_ISFIFO(m)     FIFO文件
S_ISLNK(m)      符号链接
S_ISSOCK(m)     套接字文件

事实上以下就是st_mode字段定义的标志,也可以相“&”来读取文件的属性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
S_IFMT     0170000   文件类型的位遮罩
S_IFSOCK   0140000   套接字
S_IFLNK    0120000   符号连接
S_IFREG    0100000   普通文件
S_IFBLK    0060000   块设备
S_IFDIR    0040000   目录
S_IFCHR    0020000   字符设备
S_IFIFO    0010000   FIFO
S_ISUID    0004000   文件的(set user-id on execution)位
S_ISGID    0002000   文件的(set group-id on execution)位
S_ISVTX    0001000   文件的sticky位
S_IRWXU    00700     文件所有者权限的掩码
S_IRUSR    00400     拥有者读权限
S_IWUSR    00200     拥有者写权限
S_IXUSR    00100     拥有者执行权限
S_IRWXG    00070     文件所在组权限的掩码
S_IRGRP    00040     用户组读权限
S_IWGRP    00020     用户组写权限
S_IXGRP    00010     用户组执行权限
S_IRWXO    00007     其他用户权限的掩码
S_IROTH    00004     其他用户读权限
S_IWOTH    00002     其他用户写权限
S_IXOTH    00001     其他用户执行权限

返回值

成功返回0,失败返回-1并且设置错误码errno;

示例

vi file.txt创建源文件,内容为hello,然后再ln -s file.txt file.txt.soft创建一个软链接文件。创建程序,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>


int main()
{
    int fd;
    struct stat buf[3];
   
    // stat函数
    if( 0 != stat("./file.txt.soft", &buf[0]))
    {
        printf("stat error!\n");
        return -1;
    }
    printf("stat: The file size is %lu\n", buf[0].st_size);


    // fstat函数
    fd = open("./file.txt.soft", O_RDWR);
    if(fd < 0)
    {
        printf("open file error!\n");
        return -1;
    }
    if(0 != fstat(fd, &buf[1]))
    {
        printf("fstat error!\n");
        return -1;
    }
    printf("fstat: The file size is %lu\n", buf[1].st_size);
    close(fd);
   

    // lstat函数
    if(0 != lstat("./file.txt.soft", &buf[2]))
    {
        printf("stat error!\n");
        return -1;
    }
    printf("lstat: The file size is %lu\n", buf[2].st_size);


    // 比较stat和lstat
    if(S_ISLNK(buf[0].st_mode))
        printf("stat: It is a link file!\n");
    else
        printf("stat: It is not a link file!\n");

    if(buf[2].st_mode & S_IFLNK)
        printf("lstat: It is a link file!\n");
    else
        printf("lstat: It is not a link file!\n");

    return 0;  
}

gcc stat.c -o stat编译后./stat运行程序查看打印:

1
2
3
4
5
stat: The file size is 6
fstat: The file size is 6
lstat: The file size is 8
stat: It is not a link file!
lstat: It is a link file!

可以看到stat和lstat的区别就在于是否会越过链接文件进行读取。