stat,fstat,lstat,fstatat的解析

大耗子 2020年03月29日 264次浏览

文章链接:https://codemouse.online/archives/2020-03-29224238

函数声明

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

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

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

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

  • 函数说明: 通过文件名filename获取文件信息,并保存在buf所指的结构体stat中

  • 返回值: 执行成功则返回0,失败返回-1,错误代码存于errno

  • 错误代码:

    EACCES:
    	路径名的路径前缀中的一个目录的搜索权限被拒绝。(See also path_resolution(7).)
    EBADF:
    	文件描述符fd失效了。
    EFAULT:
    	错误地址。
    ELOOP:
    	在遍历路径时遇到太多符号链接。
    ENAMETOOLONG:
    	路径名太长。
    ENOENT:
    	pathname的组件不存在,或者pathname是一个空字符串,并且标记中没有指定AT_EMPTY_PATH。
    ENOMEM:
    	内存不足(也就是内核内存)。
    ENOTDIR:
    	pathname的路径前缀的不是目录。
    EOVERFLOW:
    	路径名或fd引用文件的大小、inode号或块数不能分别用off_t、ino_t或blkcnt_t类型表示。例如,当在32位平台上编译的应用程序在没有-D_FILE_OFFSET_BITS=64的情况下调用大小超过(1<<31)-1字节的文件stat()时,可能会发生此错误。
    
    fstatat()可能会出现以下附加错误:
    EBADF:
    	dirfd不是一个有效的文件描述符。
    EINVAL:
    	在flags中指定的无效标志。
    ENOTDIR:
    	路径名是相对的,dirfd是一个文件描述符,引用的文件不是目录。
    

struct stat结构体:

struct stat { 
    dev_t         st_dev;       //文件的设备编号 
    ino_t         st_ino;       //节点 
    mode_t        st_mode;      //文件的类型和存取的权限 
    nlink_t       st_nlink;     //连到该文件的硬连接数目,刚建立的文件值为1 
    uid_t         st_uid;       //用户ID 
    gid_t         st_gid;       //组ID 
    dev_t         st_rdev;      //(设备类型)若此文件为设备文件,则为其设备编号 
    off_t         st_size;      //文件字节数(文件大小) 
    unsigned long st_blksize;   //块大小(文件系统的I/O 缓冲区大小) 
    unsigned long st_blocks;    //块数 
    struct timespec st_atim;    //最后一次访问时间 
    struct timespec st_mtim;    //最后一次修改时间
    struct timespec st_ctim;    //最后一次改变时间(指属性) 
#define st_atime st_atim.tv_sec /* Backward compatibility */
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec

}; 

宏的定义

/*文件类型标志*/
#define S_IFMT  00170000  	/*文件类型判断掩码*/
#define S_IFSOCK 0140000  	/*套接字文件 s */
#define S_IFLNK	 0120000    /*符号链接文件l */
#define S_IFREG  0100000    /*普通文件 - */
#define S_IFBLK  0060000    /*块设备文件 b */
#define S_IFDIR  0040000    /*目录文件 d */
#define S_IFCHR  0020000  	/*字符设备文件 c */
#define S_IFIFO  0010000    /*管道文件 p */
/*判断文件类型宏*/
#define S_ISLNK(m)	(((m) & S_IFMT) == S_IFLNK)  /*判断是否是符号链接文件*/
#define S_ISREG(m)	(((m) & S_IFMT) == S_IFREG)  /*判断是否是普通文件*/
#define S_ISDIR(m)	(((m) & S_IFMT) == S_IFDIR)  /*判断是否是目录文件*/
#define S_ISCHR(m)	(((m) & S_IFMT) == S_IFCHR)  /*判断是否是字符设备*/
#define S_ISBLK(m)	(((m) & S_IFMT) == S_IFBLK)  /*判断是否是块设备*/
#define S_ISFIFO(m)	(((m) & S_IFMT) == S_IFIFO)  /*判断是否是管道文件*/
#define S_ISSOCK(m)	(((m) & S_IFMT) == S_IFSOCK) /*判断是否是套接字文件*/
/*特殊权限位*/
#define S_ISUID  0004000  /*S位,设置用户ID,使可执行文件在执行阶段具有UID的权限*/
#define S_ISGID  0002000  /*G位,设置组ID位,使可执行文件在执行阶段具有GID的权限*/
#define S_ISVTX  0001000  /*T(粘着位),使文件只能被该文件的UID用户或者root用户删除*/
/*所有者权限标志*/
#define S_IRWXU 00700  /*用户(所有者)具有读、写和执行*/
#define S_IRUSR 00400  /*用户(所有者)具有读*/
#define S_IWUSR 00200  /*用户(所有者)具有写*/
#define S_IXUSR 00100  /*用户(所有者)具有执行*/
/*组权限标志*/
#define S_IRWXG 00070  /*组具有读、写和执行*/
#define S_IRGRP 00040  /*组具有读*/
#define S_IWGRP 00020  /*组具有写*/
#define S_IXGRP 00010  /*组具有执行*/
/*其他用户权限标志*/
#define S_IRWXO 00007  /*其他用户具有读、写和执行*/
#define S_IROTH 00004  /*其他用户具有读*/
#define S_IWOTH 00002  /*其他用户具有写*/
#define S_IXOTH 00001  /*其他用户具有执行*/

stat,fstat,lstat,fstatat的区别

stat和fstat作用是一样的,只是stat通过文件路径获取,fstat通过文件描述符fd获取。

lstat获取的是链接文件的文件属性,stat只能获取链接文件引用的文件的信息。

fstatat()系统调用是访问文件信息的更通用的接口,它仍然可以准确地提供stat()、lstat()和fstat()中的每一个的特性。
  如果pathname中给出的路径名是相对的,那么它将被解释为相对于文件描述符dirfd所引用的目录(而不是相对于调用进程的当前工作目录,就像stat()和lstat()对相对路径名所做的那样)。
  如果pathname是相对的,那么dirfd的值指定为AT_FDCWD,然后pathname被解释为相对于调用进程的当前工作目录(与stat()、lstat()一样)。
  如果路径名是绝对的,则忽略dirfd。