statx(2)
Extended stat: request specific fields, get birth time, inode attribute flags and mount ID.
- Since
- Linux 4.11check your kernel →
- glibc
- glibc 2.28
- System
- Linux
- Man page
- statx(2)
Synopsis
#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <fcntl.h> /* Definition of AT_* constants */
#include <sys/stat.h>
int statx(int dirfd, const char *_Nullable restrict path,
int flags, unsigned int mask,
struct statx *restrict statxbuf);Rod's take
stat(2) froze its struct back when a filesystem fit on a floppy: three timestamps, none of them birth time, and ctime still means inode change no matter how many juniors swear otherwise. statx lets you ask for just the fields you want, then tells you through stx_mask which ones it actually filled. Check that mask before trusting anything, btime especially. You also get immutable, append-only, encrypted and verity flags without opening the file and fumbling an ioctl, plus a mount ID. FreeBSD had birth time in stat first, naturally. Still a good syscall.
Flags and arguments that matter
| Name | What it does |
|---|---|
| STATX_BASIC_STATS | Mask: everything classic stat(2) returns (type, mode, nlink, uid, gid, times, ino, size, blocks). |
| STATX_BTIME | Mask: request stx_btime, the file creation time. Check stx_mask; not every filesystem has it. |
| STATX_MNT_IDLinux 5.8 | Mask: request stx_mnt_id, the ID of the mount containing the file. |
| STATX_MNT_ID_UNIQUELinux 6.8 | Mask: request a unique (non-reused) mount ID in stx_mnt_id. |
| STATX_DIOALIGNLinux 6.1 | Mask: request direct I/O alignment limits; support varies by filesystem. |
| STATX_ALL | Mask: STATX_BASIC_STATS | STATX_BTIME. Deprecated; don't use it. |
| AT_STATX_SYNC_AS_STAT | Flags: do whatever stat(2) does about syncing attributes with a remote server. |
| AT_STATX_FORCE_SYNC | Flags: force attribute sync with the server (network filesystems). |
| AT_STATX_DONT_SYNC | Flags: return cached attributes even if stale; no server round trip. |
| AT_SYMLINK_NOFOLLOW | Flags: if path is a symlink, report on the link itself. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| ENOENT | A path component doesn't exist, or path is empty without AT_EMPTY_PATH. |
| EACCES | Search permission denied on a directory in the path prefix. |
| EINVAL | Invalid flag in flags, or the reserved STATX__RESERVED bit set in mask. |
| EBADF | path is relative but dirfd is neither AT_FDCWD nor a valid fd. |
| ENOTDIR | A prefix component isn't a directory, or path is relative and dirfd isn't a directory. |
Example
struct statx sx;
if (statx(AT_FDCWD, path, AT_STATX_SYNC_AS_STAT,
STATX_BASIC_STATS | STATX_BTIME, &sx) == 0) {
if (sx.stx_mask & STATX_BTIME)
printf("born: %lld.%09u\n",
(long long)sx.stx_btime.tv_sec, sx.stx_btime.tv_nsec);
else
puts("no birth time on this filesystem");
if ((sx.stx_attributes_mask & STATX_ATTR_IMMUTABLE) &&
(sx.stx_attributes & STATX_ATTR_IMMUTABLE))
puts("immutable");
}Trimmed from the full walkthrough in statx(2): what stat(2) should have been.
BSD equivalent
FreeBSD: no statx; stat(2) already carries st_birthtim (st_birthtime). OpenBSD: no statx; plain stat(2)/fstatat(2).
The long version, from the console
Sources
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
