欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux stat获取文件类型

程序员文章站 2022-05-24 15:29:25
...

一、函数声明

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int stat(const char *pathname, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);
int lstat(const char *pathname, struct stat *statbuf);

#include <fcntl.h>           /* Definition of AT_* constants */
#include <sys/stat.h>

int fstatat(int dirfd, const char *pathname, struct stat *statbuf,
            int flags);

二、实例

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>

void sys_err(const char *msg) {
    perror(msg);
    exit(-1);
}

int main(int argc, const char **args)
{
    const char *path = args[1];
    struct stat st = {0};
    int fd;
    if (argc < 2) {
        exit(-1);
    }

    fd = open(path, __O_PATH|__O_NOFOLLOW);
    if (fd < 0) {
        sys_err("open with fail");
    }

    if (fstat(fd, &st) < 0) {
        sys_err("fstat with fail");
    }

    switch (st.st_mode & S_IFMT)
    {
    case __S_IFDIR:
        printf("directory\n");
        break;
    case __S_IFCHR:
        printf("charactor dev file\n");
        break;
    case __S_IFBLK:
        printf("block dev file\n");
        break;
    case __S_IFREG:
        printf("regular file\n");
        break;
    case __S_IFIFO:
        printf("fifo file\n");
        break;
    case __S_IFLNK:
        printf("sysmbol link file\n");
        break;
    case __S_IFSOCK:
        printf("socket file\n");
        break;
    default:
        break;
    }

    close(fd);

    return 0;
}

我之所以用open然后stat,而不是直接使用lstat。是因为,lstat实际上是有要求的。

open(path, __O_PATH|__O_NOFOLLOW);这样设置是基于,为了获取到了文件描述符是symbol link文件的。而不是其关联的文件的。
If pathname is a symbolic link and the O_NOFOLLOW flag is also specified,
then the call returns a file descriptor referring to the symbolic link
引用自:Ubuntu20.4 man 2 open 中对O_PATH的解释。

三、补充

Linux stat获取文件类型

Unix高级环境编程一书中提到。POSIX标准中,还有额外的几种文件类型。

但是我在Ubuntu20.4上查看,/usr/include/x86_64-linux-gnu/bits/stat 文件中所定义的这三个宏会发现。

/* POSIX.1b objects.  Note that these macros always evaluate to zero.  But
   they do it by enforcing the correct use of the macros.  */
#define __S_TYPEISMQ(buf)  ((buf)->st_mode - (buf)->st_mode)
#define __S_TYPEISSEM(buf) ((buf)->st_mode - (buf)->st_mode)
#define __S_TYPEISSHM(buf) ((buf)->st_mode - (buf)->st_mode)

这些值一直都是0。也就是虽然POSIX标准这么定义,但是现在的ubuntu 20.4这个发行版,并未采用实现该标准。