stat() - Unix,Linux 系统调用
广告
名称
stat、fstat、lstat - 获取文件状态
语法
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *path, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *path, struct stat *buf);
|
描述
这些函数返回有关文件的信息。文件本身不需要任何权限,但是 - 在 stat() 和 lstat() 的情况下 - 需要对通往文件的 path 中的所有目录具有执行(搜索)权限。
stat() 统计 path 指向的文件并填充 buf。lstat() 与 stat() 相同,除了如果 path 是符号链接,则会统计链接本身,而不是它所引用的文件。
fstat() 与 stat() 相同,除了要统计的文件由文件描述符 filedes 指定。
所有这些系统调用都返回一个 stat 结构,其中包含以下字段
struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};
|
st_dev 字段描述了此文件所在的设备。
st_rdev 字段描述了此文件(inode)表示的设备。 st_size 字段以字节为单位给出文件(如果它是常规文件或符号链接)的大小。符号链接的大小是它包含的路径名的长度,不包括尾随的空字节。
st_blocks 字段指示分配给文件的数据块数量,以 512 字节为单位。(这可能小于 st_size/512,例如,当文件有空洞时。)
st_blksize 字段给出用于高效文件系统 I/O 的“首选”块大小。(以较小的块写入文件可能会导致效率低下的读-修改-重写。)
并非所有 Linux 文件系统都实现了所有时间字段。某些文件系统类型允许以不会导致更新 st_atime 字段的方式进行挂载。(请参阅 mount(8) 中的“noatime”。)
st_atime 字段会因文件访问而更改,例如,由 execve(2)、mknod(2)、pipe(2)、utime(2) 和 read(2)(超过零字节)更改。其他例程,如 mmap(2),可能会或可能不会更新 st_atime。
st_mtime 字段会因文件修改而更改,例如,由 mknod(2)、truncate(2)、utime(2) 和 write(2)(超过零字节)更改。此外,目录的 st_mtime 会因该目录中文件的创建或删除而更改。st_mtime 字段不会因所有者、组、硬链接计数或模式的更改而更改。
st_ctime 字段会因写入或设置 inode 信息(即所有者、组、链接计数、模式等)而更改。
以下 POSIX 宏定义用于使用 st_mode 字段检查文件类型
标签 | 描述 |
S_ISREG(m) | 它是否为常规文件? |
S_ISDIR(m) | 目录? |
S_ISCHR(m) | 字符设备? |
S_ISBLK(m) | 块设备? |
S_ISFIFO(m) | FIFO(命名管道)? |
S_ISLNK(m) | 符号链接?(不在 POSIX.1-1996 中。) |
S_ISSOCK(m) | 套接字?(不在 POSIX.1-1996 中。) |
以下标志定义用于 st_mode 字段
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 | 设置 UID 位 |
S_ISGID | 0002000 | 设置组 ID 位(见下文) |
S_ISVTX | 0001000 | 粘滞位(见下文) |
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 | 其他用户具有执行权限 |
设置组 ID 位 (S_ISGID) 有几个特殊用途。对于目录,它指示应为该目录使用 BSD 语义:在其中创建的文件将从目录继承其组 ID,而不是从创建进程的有效组 ID 继承,并且在其中创建的目录也将设置 S_ISGID 位。对于未设置组执行位 (S_IXGRP) 的文件,设置组 ID 位表示强制文件/记录锁定。
目录上的“粘滞”位 (S_ISVTX) 表示只有文件的所有者、目录的所有者以及特权进程才能重命名或删除该目录中的文件。
Linux 说明
自内核 2.5.48 以来,stat 结构支持三个文件时间戳字段的纳秒分辨率。如果定义了 _BSD_SOURCE 或 _SVID_SOURCE 特性测试宏,则 Glibc 使用 st_atim.tv_nsec 形式的名称公开每个字段的纳秒分量,或者如果未定义这些宏中的任何一个,则使用 st_atimensec 形式的名称公开。在不支持亚秒级时间戳的文件系统上,这些纳秒字段将返回 0 值。
对于 /proc 目录下的大多数文件,stat() 不会在 st_size 字段中返回文件大小;而是将该字段返回 0 值。
返回值
成功时,返回零。错误时,返回 -1,并且 errno 被相应地设置。
错误
标签 | 描述 |
EACCES | 拒绝搜索 path 的路径前缀中的某个目录的权限。(另请参阅 path_resolution(2)。) |
EBADF |
filedes 无效。 |
EFAULT | 错误地址。 |
ELOOP | 在遍历路径时遇到太多符号链接。 |
ENAMETOOLONG | 文件名太长。 |
ENOENT | path 的某个组件不存在,或者路径为空字符串。 |
ENOMEM | 内存不足(即内核内存)。 |
ENOTDIR | 路径的某个组件不是目录。 |
符合标准
这些系统调用符合 SVr4、4.3BSD、POSIX.1-2001。
st_blocks 和 st_blksize 字段的使用可能不太便携。(它们是在 BSD 中引入的。解释在系统之间以及当涉及 NFS 挂载时可能在单个系统上有所不同。)
POSIX 没有描述 S_IFMT、S_IFSOCK、S_IFLNK、S_IFREG、S_IFBLK、S_IFDIR、S_IFCHR、S_IFIFO、S_ISVTX 位,而是要求使用 S_ISDIR() 等宏。S_ISLNK 和 S_ISSOCK 宏不在 POSIX.1-1996 中,但都存在于 POSIX.1-2001 中;前者来自 SVID 4,后者来自 SUSv2。
Unix V7(以及后续系统)有 S_IREAD、S_IWRITE、S_IEXEC,而 POSIX 规定了同义词 S_IRUSR、S_IWUSR、S_IXUSR。
其他系统
各种系统上已使用(或正在使用)的值
十六进制 | 名称 | ls | 八进制 | 描述 |
f000 | S_IFMT | | 170000 | 文件类型的掩码 |
0000 | | | 000000 | SCO 停用 inode,BSD 未知类型 |
| | | | SVID-v2 和 XPG2 对普通文件都使用 0 和 0100000 |
1000 | S_IFIFO | p| | 010000 | FIFO(命名管道) |
2000 | S_IFCHR | c | 020000 | 字符特殊(V7) |
3000 | S_IFMPC | | 030000 | 多路复用字符特殊(V7) |
4000 | S_IFDIR | d/ | 040000 | 目录(V7) |
5000 | S_IFNAM | | 050000 | XENIX 命名特殊文件 |
| | | | 有两个子类型,由 st_rdev 值 1、2 区分 |
0001 | S_INSEM | s | 000001 | XENIX IFNAM 的信号量子类型 |
0002 | S_INSHD | m | 000002 | XENIX IFNAM 的共享数据子类型 |
6000 | S_IFBLK | b | 060000 | 块特殊(V7) |
7000 | S_IFMPB | | 070000 | 多路复用块特殊(V7) |
8000 | S_IFREG | - | 100000 | 常规(V7) |
9000 | S_IFCMP | | 110000 | VxFS 压缩 |
9000 | S_IFNWK | n | 110000 | 网络特殊(HP-UX) |
a000 | S_IFLNK | l@ | 120000 | 符号链接(BSD) |
b000 | S_IFSHAD | | 130000 | Solaris ACL 的影子 inode(用户空间看不到) |
c000 | S_IFSOCK | s= | 140000 | 套接字(BSD;VxFS 上也称为“S_IFSOC”) |
d000 | S_IFDOOR | D> | 150000 | Solaris 门 |
e000 | S_IFWHT | w% | 160000 | BSD 覆盖(不用于 inode) |
0200 | S_ISVTX | | 001000 | “粘滞位”:即使在使用后也保存交换的文本(V7) |
| | | | 保留(SVID-v2) |
| | | | 在非目录上:不要缓存此文件(SunOS) |
| | | | 在目录上:受限删除标志(SVID-v4.2) |
0400 | S_ISGID | | 002000 | 执行时设置组 ID(V7) |
| | | | 对于目录:使用 BSD 语义传播 GID |
0400 | S_ENFMT | | 002000 | SysV 文件锁定执行(与 S_ISGID 共享) |
0800 | S_ISUID | | 004000 | 执行时设置用户 ID(V7) |
0800 | S_CDF | | 004000 | 目录是上下文相关文件(HP-UX) |
粘滞命令出现在版本 32V AT&T UNIX 中。
参见
广告
|