文章链接: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。