STAT - Linux手册页
Linux程序员手册 第2部分
更新日期: 2020-08-13
名称
stat,fstat,lstat,fstatat-获取文件状态
语法
#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);
glibc的功能测试宏要求(请参阅feature_test_macros(7)):
lstat():
- / * glibc 2.19和更早版本* / _BSD_SOURCE || / *自glibc 2.20起* / -_DEFAULT_SOURCE || _XOPEN_SOURCE>= 500 || / *自glibc 2.10起:* / _POSIX_C_SOURCE>= 200112L
fstatat():
- Since glibc 2.10:
- _POSIX_C_SOURCE>= 200809L
- Before glibc 2.10:
- _ATFILE_SOURCE
说明
这些函数在statbuf指向的缓冲区中返回有关文件的信息。不需要文件本身的权限,但是---对于stat(),fstatat()和lstat()的情况---路径名中所有导致文件名的目录都需要执行(搜索)权限文件。
stat()和fstatat()检索有关路径名指向的文件的信息; fstatat()的差异如下所述。
lstat()与stat()相同,不同之处在于,如果路径名是符号链接,则它返回有关链接本身的信息,而不是有关链接引用的文件的信息。
fstat()与stat()相同,除了要通过文件描述符fd指定要检索其信息的文件。
The stat structure
所有这些系统调用都返回一个stat结构,其中包含以下字段:
struct stat { dev_t st_dev; /* ID of device containing file */ ino_t st_ino; /* Inode number */ mode_t st_mode; /* File type and mode */ 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; /* Block size for filesystem I/O */ blkcnt_t st_blocks; /* Number of 512B blocks allocated */ /* Since Linux 2.6, the kernel supports nanosecond precision for the following timestamp fields. For the details before Linux 2.6, see NOTES. */ struct timespec st_atim; /* Time of last access */ struct timespec st_mtim; /* Time of last modification */ struct timespec st_ctim; /* Time of last status change */ #define st_atime st_atim.tv_sec /* Backward compatibility */ #define st_mtime st_mtim.tv_sec #define st_ctime st_ctim.tv_sec };
注意:stat结构中字段的顺序在不同体系结构中有所不同。另外,上面的定义没有显示在各种体系结构的某些字段之间可能存在的填充字节。如果需要了解详细信息,请查阅glibc和内核源代码。
注意:出于性能和简便性的考虑,stat结构中的不同字段可能包含系统调用执行期间不同时刻的状态信息。例如,如果另一个进程通过调用chmod(2)或chown(2)来更改st_mode或st_uid,则stat()可能会返回旧的st_mode和新的st_uid,或者旧的st_uid和新的st_mode。
stat结构中的字段如下:
- st_dev
- 该字段描述此文件所在的设备。 (major(3)和minor(3)宏可用于分解此字段中的设备ID。)
- st_ino
- 该字段包含文件的索引节点号。
- st_mode
- 该字段包含文件类型和模式。有关更多信息,请参见inode(7)。
- st_nlink
- 该字段包含到文件的硬链接数。
- st_uid
- 该字段包含文件所有者的用户标识。
- st_gid
- 该字段包含文件的组所有者的ID。
- st_rdev
- 该字段描述此文件(inode)代表的设备。
- st_size
- 该字段以字节为单位给出文件的大小(如果是常规文件或符号链接)。符号链接的大小是它包含的路径名的长度,没有终止的空字节。
- st_blksize
- 该字段给出有效文件系统I / O的"首选"块大小。
- st_blocks
- 该字段指示以512字节为单位分配给文件的块数。 (当文件有孔时,它可能小于st_size / 512。)
- st_atime
- 这是最后一次访问文件数据的时间。
- st_mtime
- 这是文件数据的最后修改时间。
- st_ctime
- 这是文件的最后状态更改时间戳(最后一次更改到inode的时间)。
有关以上字段的更多信息,请参见inode(7)。
fstatat()
fstatat()系统调用是用于访问文件信息的更通用的接口,该文件信息仍可以准确提供stat(),lstat()和fstat()的行为。
如果在路径名中给定的路径名是相对的,那么它将相对于文件描述符dirfd所引用的目录进行解释(而不是相对于调用进程的当前工作目录,如stat()和lstat()所做的那样)相对路径名)。
如果路径名是相对的并且dirfd是特殊值AT_FDCWD,则路径名将相对于调用进程的当前工作目录(如stat()和lstat())进行解释。
如果路径名是绝对的,则dirfd被忽略。
标志可以是0,也可以包含一个或多个以下标志或:
- AT_EMPTY_PATH(since Linux 2.6.39)
- 如果路径名是空字符串,请对dirfd引用的文件进行操作(该文件可能已使用open(2)O_PATH标志获得)。在这种情况下,dirfd可以引用任何类型的文件,而不仅仅是目录,并且fstatat()的行为类似于fstat()的行为。如果dirfd为AT_FDCWD,则调用在当前工作目录上进行。该标志是特定于Linux的。定义_GNU_SOURCE以获得其定义。
- AT_NO_AUTOMOUNT(since Linux 2.6.38)
- 如果它是自动挂载点的目录,请不要自动挂载路径名的终端(" basename")组件。这允许调用者收集自动挂载点的属性(而不是其将挂载的位置)。从Linux 4.14开始,也不要在按需目录中实例化不存在的名称,例如用于自动挂载程序间接映射的目录。如果安装点已被安装,则此标志无效。
- stat()和lstat()都像设置了AT_NO_AUTOMOUNT一样起作用。
- 可以在扫描目录的工具中使用AT_NO_AUTOMOUNT,以防止自动安装点目录的大规模自动安装。
- 该标志是特定于Linux的。定义_GNU_SOURCE以获得其定义。
- AT_SYMLINK_NOFOLLOW
- 如果路径名是符号链接,请不要取消引用它:而是返回有关链接本身的信息,例如lstat()。 (默认情况下,fstatat()取消引用符号链接,例如stat()。)
有关对fstatat()的需求的说明,请参见openat(2)。
返回值
成功时,返回零。如果出错,则返回-1,并正确设置errno。
错误说明
- EACCES
- 路径名的路径前缀中的目录之一的搜索权限被拒绝。 (另请参见path_resolution(7)。)
- EBADF
- fd不是有效的打开文件描述符。
- EFAULT
- 地址错误。
- ELOOP
- 遍历路径时遇到太多符号链接。
- ENAMETOOLONG
- 路径名太长。
- ENOENT
- 路径名的组件不存在或是悬挂的符号链接。
- ENOENT
- 路径名是一个空字符串,并且未在标志中指定AT_EMPTY_PATH。
- ENOMEM
- 内存不足(即内核内存)。
- ENOTDIR
- 路径名的路径前缀的组成部分不是目录。
- EOVERFLOW
- 路径名或fd表示一个文件,其大小,索引节点号或块数不能分别用off_t,ino_t或blkcnt_t类型表示。例如,在没有-D_FILE_OFFSET_BITS = 64的32位平台上编译的应用程序在大小超过(1)的文件上调用stat()时,可能会发生此错误。
fstatat()可能会发生以下其他错误:
- EBADF
- dirfd不是有效的文件描述符。
- EINVAL
- 标志中指定的标志无效。
- ENOTDIR
- pathname是相对的,dirfd是引用目录以外的文件的文件描述符。
版本
fstatat()在内核2.6.16中添加到Linux;库支持已添加到版本2.4中的glibc。
遵循规范
stat(),fstat(),lstat():SVr4、4.3BSD,POSIX.1-2001,POSIX.1.2008。
fstatat():POSIX.1-2008。
根据POSIX.1-2001,符号链接上的lstat()仅需要在stat结构的st_size字段和st_mode字段的文件类型中返回有效信息。 POSIX.1-2008加强了规范,要求lstat()返回除st_mode中的模式位以外的所有字段中的有效信息。
使用st_blocks和st_blksize字段可能不太方便。 (它们是在BSD中引入的。系统之间的解释不同,并且在涉及NFS挂载时可能在单个系统上。)
备注
Timestamp fields
较早的内核和较早的标准不支持纳秒级时间戳字段。相反,有三个时间戳字段-st_atime,st_mtime和st_ctime-键入为time_t,它们以一秒的精度记录了时间戳。
从内核2.5.48开始,stat结构为三个文件时间戳字段支持纳秒分辨率。如果定义了适当的功能测试宏,则可以通过st_atim.tv_nsec形式的名称获得每个时间戳的纳秒分量。纳秒级时间戳在POSIX.1-2008中进行了标准化,从版本2.12开始,如果_POSIX_C_SOURCE的值定义为200809L或更大,或者_XOPEN_SOURCE的值定义为700或更大,则glibc将公开纳秒组件的名称。直到并包括glibc 2.19,如果定义了_BSD_SOURCE或_SVID_SOURCE,也将定义纳秒组件的定义。如果没有定义上述宏,则以st_atimensec形式的名称公开纳秒值。
C library/kernel differences
随着时间的推移,stat结构的大小增加导致stat()的三个连续版本:32位的sys_stat()(插槽__NR_oldstat),sys_newstat()(插槽__NR_stat)和sys_stat64()(插槽__NR_stat64) i386等平台。前两个版本已经存在于Linux 1.0中(尽管名称不同)。最后一个是在Linux 2.4中添加的。类似的说明适用于fstat()和lstat()。
不同版本处理的stat结构的内核内部版本分别为:
- __old_kernel_stat
- 原始结构,具有很窄的字段,没有填充。
- stat
- 较大的st_ino字段和填充添加到结构的各个部分,以便将来进行扩展。
- stat64
- 甚至更大的st_ino字段,更大的st_uid和st_gid字段可以容纳Linux-2.4将UID和GID扩展到32位,以及各种其他扩大的字段以及结构中的进一步填充。 (随着填充32位设备ID和纳秒组件的出现,最终在Linux 2.6中消耗了各种填充字节。)
glibc stat()包装函数会将这些详细信息从应用程序中隐藏,调用内核提供的最新版本的系统调用,并根据旧二进制文件的需要重新包装返回的信息。
在现代的64位系统上,工作更简单:只有一个stat()系统调用,内核处理的stat结构包含足够大的字段。
glibc fstatat()包装函数使用的基础系统调用实际上称为fstatat64(),或者在某些体系结构上称为newfstatat()。
示例
以下程序调用lstat()并在返回的stat结构中显示选定的字段。
#include <sys/types.h> #include <sys/stat.h> #include <time.h> #include <stdio.h> #include <stdlib.h> #include <sys/sysmacros.h> int main(int argc, char *argv[]) { struct stat sb; if (argc != 2) { fprintf(stderr, "Usage: %s <pathname>\n", argv[0]); exit(EXIT_FAILURE); } if (lstat(argv[1], &sb) == -1) { perror("lstat"); exit(EXIT_FAILURE); } printf("ID of containing device: [%lx,%lx]\n", (long) major(sb.st_dev), (long) minor(sb.st_dev)); printf("File type: "); switch (sb.st_mode & S_IFMT) { case S_IFBLK: printf("block device\n"); break; case S_IFCHR: printf("character device\n"); break; case S_IFDIR: printf("directory\n"); break; case S_IFIFO: printf("FIFO/pipe\n"); break; case S_IFLNK: printf("symlink\n"); break; case S_IFREG: printf("regular file\n"); break; case S_IFSOCK: printf("socket\n"); break; default: printf("unknown?\n"); break; } printf("I-node number: %ld\n", (long) sb.st_ino); printf("Mode: %lo (octal)\n", (unsigned long) sb.st_mode); printf("Link count: %ld\n", (long) sb.st_nlink); printf("Ownership: UID=%ld GID=%ld\n", (long) sb.st_uid, (long) sb.st_gid); printf("Preferred I/O block size: %ld bytes\n", (long) sb.st_blksize); printf("File size: %lld bytes\n", (long long) sb.st_size); printf("Blocks allocated: %lld\n", (long long) sb.st_blocks); printf("Last status change: %s", ctime(&sb.st_ctime)); printf("Last file access: %s", ctime(&sb.st_atime)); printf("Last file modification: %s", ctime(&sb.st_mtime)); exit(EXIT_SUCCESS); }
另外参见
ls(1),stat(1),access(2),chmod(2),chown(2),readlink(2),statx(2),utime(2),capabilities(7),inode(7),符号链接(7)
出版信息
这个页面是Linux手册页项目5.08版的一部分。有关项目的说明、有关报告错误的信息以及此页面的最新版本,请访问https://www.kernel.org/doc/man-pages/。