unix: add Statx on Linux

statx(2) allows to get enhanced file status information (not currently
available through the existing stat syscalls), lightweight stat,
heavyweight stat. The Statx_t type used by Statx has consistent field
sizes on all arches (with year-2038-capable timestamps) and is closer to
the BSD implementation of Stat_t.

See http://man7.org/linux/man-pages/man2/statx.2.html for details. The
syscall was added in Linux kernel 4.11.

See https://github.com/tklauser/statx for an example of how this
function and types can be used to report stat(1)-like file status
information.

Change-Id: I9e9642b5b42a393f94fd532453888ce9ba4f0003
Reviewed-on: https://go-review.googlesource.com/87555
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/unix/linux/types.go b/unix/linux/types.go
index 929bbbf..1217fd8 100644
--- a/unix/linux/types.go
+++ b/unix/linux/types.go
@@ -47,11 +47,12 @@
 #include <sys/utsname.h>
 #include <sys/wait.h>
 #include <linux/filter.h>
+#include <linux/icmpv6.h>
 #include <linux/keyctl.h>
 #include <linux/netlink.h>
 #include <linux/perf_event.h>
 #include <linux/rtnetlink.h>
-#include <linux/icmpv6.h>
+#include <linux/stat.h>
 #include <asm/termbits.h>
 #include <asm/ptrace.h>
 #include <time.h>
@@ -116,6 +117,21 @@
 
 #endif
 
+// These are defined in linux/fcntl.h, but including it globally causes
+// conflicts with fcntl.h
+#ifndef AT_STATX_SYNC_TYPE
+# define AT_STATX_SYNC_TYPE	0x6000	// Type of synchronisation required from statx()
+#endif
+#ifndef AT_STATX_SYNC_AS_STAT
+# define AT_STATX_SYNC_AS_STAT	0x0000	// - Do whatever stat() does
+#endif
+#ifndef AT_STATX_FORCE_SYNC
+# define AT_STATX_FORCE_SYNC	0x2000	// - Force the attributes to be sync'd with the server
+#endif
+#ifndef AT_STATX_DONT_SYNC
+# define AT_STATX_DONT_SYNC	0x4000	// - Don't sync attributes with the server
+#endif
+
 #ifdef TCSETS2
 // On systems that have "struct termios2" use this as type Termios.
 typedef struct termios2 termios_t;
@@ -249,6 +265,10 @@
 
 type Statfs_t C.struct_statfs
 
+type StatxTimestamp C.struct_statx_timestamp
+
+type Statx_t C.struct_statx
+
 type Dirent C.struct_dirent
 
 type Fsid C.fsid_t
@@ -513,9 +533,15 @@
 type EpollEvent C.struct_my_epoll_event
 
 const (
-	AT_FDCWD            = C.AT_FDCWD
-	AT_NO_AUTOMOUNT     = C.AT_NO_AUTOMOUNT
-	AT_REMOVEDIR        = C.AT_REMOVEDIR
+	AT_EMPTY_PATH   = C.AT_EMPTY_PATH
+	AT_FDCWD        = C.AT_FDCWD
+	AT_NO_AUTOMOUNT = C.AT_NO_AUTOMOUNT
+	AT_REMOVEDIR    = C.AT_REMOVEDIR
+
+	AT_STATX_SYNC_AS_STAT = C.AT_STATX_SYNC_AS_STAT
+	AT_STATX_FORCE_SYNC   = C.AT_STATX_FORCE_SYNC
+	AT_STATX_DONT_SYNC    = C.AT_STATX_DONT_SYNC
+
 	AT_SYMLINK_FOLLOW   = C.AT_SYMLINK_FOLLOW
 	AT_SYMLINK_NOFOLLOW = C.AT_SYMLINK_NOFOLLOW
 )
diff --git a/unix/mkerrors.sh b/unix/mkerrors.sh
index a452554..4dd40c1 100755
--- a/unix/mkerrors.sh
+++ b/unix/mkerrors.sh
@@ -187,6 +187,7 @@
 #include <linux/vm_sockets.h>
 #include <linux/taskstats.h>
 #include <linux/genetlink.h>
+#include <linux/stat.h>
 #include <linux/watchdog.h>
 #include <net/route.h>
 #include <asm/termbits.h>
@@ -428,6 +429,7 @@
 		$2 ~ /^(TASKSTATS|TS)_/ ||
 		$2 ~ /^CGROUPSTATS_/ ||
 		$2 ~ /^GENL_/ ||
+		$2 ~ /^STATX_/ ||
 		$2 ~ /^UTIME_/ ||
 		$2 ~ /^XATTR_(CREATE|REPLACE)/ ||
 		$2 ~ /^ATTR_(BIT_MAP_COUNT|(CMN|VOL|FILE)_)/ ||
diff --git a/unix/mkpost.go b/unix/mkpost.go
index dbdfd0a..4c191f0 100644
--- a/unix/mkpost.go
+++ b/unix/mkpost.go
@@ -61,6 +61,10 @@
 	convertUtsnameRegex := regexp.MustCompile(`((Sys|Node|Domain)name|Release|Version|Machine)(\s+)\[(\d+)\]u?int8`)
 	b = convertUtsnameRegex.ReplaceAll(b, []byte("$1$3[$4]byte"))
 
+	// Remove spare fields (e.g. in Statx_t)
+	spareFieldsRegex := regexp.MustCompile(`X__spare\S*`)
+	b = spareFieldsRegex.ReplaceAll(b, []byte("_"))
+
 	// We refuse to export private fields on s390x
 	if goarch == "s390x" && goos == "linux" {
 		// Remove cgo padding fields
diff --git a/unix/syscall_linux.go b/unix/syscall_linux.go
index 4462856..71c58e1 100644
--- a/unix/syscall_linux.go
+++ b/unix/syscall_linux.go
@@ -1318,6 +1318,7 @@
 
 //sys	Setpriority(which int, who int, prio int) (err error)
 //sys	Setxattr(path string, attr string, data []byte, flags int) (err error)
+//sys	Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error)
 //sys	Sync()
 //sys	Syncfs(fd int) (err error)
 //sysnb	Sysinfo(info *Sysinfo_t) (err error)
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index 9cc0754..78d2879 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -314,6 +314,96 @@
 	}
 }
 
+func TestStatx(t *testing.T) {
+	var stx unix.Statx_t
+	err := unix.Statx(unix.AT_FDCWD, ".", 0, 0, &stx)
+	if err == unix.ENOSYS {
+		t.Skip("statx syscall is not available, skipping test")
+	} else if err != nil {
+		t.Fatalf("Statx: %v", err)
+	}
+
+	defer chtmpdir(t)()
+	touch(t, "file1")
+
+	var st unix.Stat_t
+	err = unix.Stat("file1", &st)
+	if err != nil {
+		t.Fatalf("Stat: %v", err)
+	}
+
+	flags := unix.AT_STATX_SYNC_AS_STAT
+	err = unix.Statx(unix.AT_FDCWD, "file1", flags, unix.STATX_ALL, &stx)
+	if err != nil {
+		t.Fatalf("Statx: %v", err)
+	}
+
+	if uint32(stx.Mode) != st.Mode {
+		t.Errorf("Statx: returned stat mode does not match Stat")
+	}
+
+	atime := unix.StatxTimestamp{Sec: int64(st.Atim.Sec), Nsec: uint32(st.Atim.Nsec)}
+	ctime := unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)}
+	mtime := unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)}
+
+	if stx.Atime != atime {
+		t.Errorf("Statx: returned stat atime does not match Stat")
+	}
+	if stx.Ctime != ctime {
+		t.Errorf("Statx: returned stat ctime does not match Stat")
+	}
+	if stx.Mtime != mtime {
+		t.Errorf("Statx: returned stat mtime does not match Stat")
+	}
+
+	err = os.Symlink("file1", "symlink1")
+	if err != nil {
+		t.Fatal(err)
+	}
+
+	err = unix.Lstat("symlink1", &st)
+	if err != nil {
+		t.Fatalf("Lstat: %v", err)
+	}
+
+	err = unix.Statx(unix.AT_FDCWD, "symlink1", flags, unix.STATX_BASIC_STATS, &stx)
+	if err != nil {
+		t.Fatalf("Statx: %v", err)
+	}
+
+	// follow symlink, expect a regulat file
+	if stx.Mode&unix.S_IFREG == 0 {
+		t.Errorf("Statx: didn't follow symlink")
+	}
+
+	err = unix.Statx(unix.AT_FDCWD, "symlink1", flags|unix.AT_SYMLINK_NOFOLLOW, unix.STATX_ALL, &stx)
+	if err != nil {
+		t.Fatalf("Statx: %v", err)
+	}
+
+	// follow symlink, expect a symlink
+	if stx.Mode&unix.S_IFLNK == 0 {
+		t.Errorf("Statx: unexpectedly followed symlink")
+	}
+	if uint32(stx.Mode) != st.Mode {
+		t.Errorf("Statx: returned stat mode does not match Lstat")
+	}
+
+	atime = unix.StatxTimestamp{Sec: int64(st.Atim.Sec), Nsec: uint32(st.Atim.Nsec)}
+	ctime = unix.StatxTimestamp{Sec: int64(st.Ctim.Sec), Nsec: uint32(st.Ctim.Nsec)}
+	mtime = unix.StatxTimestamp{Sec: int64(st.Mtim.Sec), Nsec: uint32(st.Mtim.Nsec)}
+
+	if stx.Atime != atime {
+		t.Errorf("Statx: returned stat atime does not match Lstat")
+	}
+	if stx.Ctime != ctime {
+		t.Errorf("Statx: returned stat ctime does not match Lstat")
+	}
+	if stx.Mtime != mtime {
+		t.Errorf("Statx: returned stat mtime does not match Lstat")
+	}
+}
+
 // utilities taken from os/os_test.go
 
 func touch(t *testing.T, name string) {
diff --git a/unix/zerrors_linux_386.go b/unix/zerrors_linux_386.go
index 8947248..4fba476 100644
--- a/unix/zerrors_linux_386.go
+++ b/unix/zerrors_linux_386.go
@@ -1638,6 +1638,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_amd64.go b/unix/zerrors_linux_amd64.go
index 4083cb2..7e2a108 100644
--- a/unix/zerrors_linux_amd64.go
+++ b/unix/zerrors_linux_amd64.go
@@ -1639,6 +1639,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_arm.go b/unix/zerrors_linux_arm.go
index 27d3835..250841b 100644
--- a/unix/zerrors_linux_arm.go
+++ b/unix/zerrors_linux_arm.go
@@ -1643,6 +1643,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_arm64.go b/unix/zerrors_linux_arm64.go
index 69ad314..f5d7856 100644
--- a/unix/zerrors_linux_arm64.go
+++ b/unix/zerrors_linux_arm64.go
@@ -1629,6 +1629,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_mips.go b/unix/zerrors_linux_mips.go
index d131a4c..f45492d 100644
--- a/unix/zerrors_linux_mips.go
+++ b/unix/zerrors_linux_mips.go
@@ -1641,6 +1641,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_mips64.go b/unix/zerrors_linux_mips64.go
index 62dd203..f5a64fb 100644
--- a/unix/zerrors_linux_mips64.go
+++ b/unix/zerrors_linux_mips64.go
@@ -1641,6 +1641,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_mips64le.go b/unix/zerrors_linux_mips64le.go
index dc8e56e..db6d556 100644
--- a/unix/zerrors_linux_mips64le.go
+++ b/unix/zerrors_linux_mips64le.go
@@ -1641,6 +1641,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_mipsle.go b/unix/zerrors_linux_mipsle.go
index 9067662..4a62a55 100644
--- a/unix/zerrors_linux_mipsle.go
+++ b/unix/zerrors_linux_mipsle.go
@@ -1641,6 +1641,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_ppc64.go b/unix/zerrors_linux_ppc64.go
index f6ca82c..5e1e81e 100644
--- a/unix/zerrors_linux_ppc64.go
+++ b/unix/zerrors_linux_ppc64.go
@@ -1696,6 +1696,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_ppc64le.go b/unix/zerrors_linux_ppc64le.go
index ddd2562..6a80324 100644
--- a/unix/zerrors_linux_ppc64le.go
+++ b/unix/zerrors_linux_ppc64le.go
@@ -1696,6 +1696,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zerrors_linux_s390x.go b/unix/zerrors_linux_s390x.go
index fc304a6..af5a895 100644
--- a/unix/zerrors_linux_s390x.go
+++ b/unix/zerrors_linux_s390x.go
@@ -1700,6 +1700,27 @@
 	SPLICE_F_MORE                        = 0x4
 	SPLICE_F_MOVE                        = 0x1
 	SPLICE_F_NONBLOCK                    = 0x2
+	STATX_ALL                            = 0xfff
+	STATX_ATIME                          = 0x20
+	STATX_ATTR_APPEND                    = 0x20
+	STATX_ATTR_AUTOMOUNT                 = 0x1000
+	STATX_ATTR_COMPRESSED                = 0x4
+	STATX_ATTR_ENCRYPTED                 = 0x800
+	STATX_ATTR_IMMUTABLE                 = 0x10
+	STATX_ATTR_NODUMP                    = 0x40
+	STATX_BASIC_STATS                    = 0x7ff
+	STATX_BLOCKS                         = 0x400
+	STATX_BTIME                          = 0x800
+	STATX_CTIME                          = 0x80
+	STATX_GID                            = 0x10
+	STATX_INO                            = 0x100
+	STATX_MODE                           = 0x2
+	STATX_MTIME                          = 0x40
+	STATX_NLINK                          = 0x4
+	STATX_SIZE                           = 0x200
+	STATX_TYPE                           = 0x1
+	STATX_UID                            = 0x8
+	STATX__RESERVED                      = 0x80000000
 	S_BLKSIZE                            = 0x200
 	S_IEXEC                              = 0x40
 	S_IFBLK                              = 0x6000
diff --git a/unix/zsyscall_linux_386.go b/unix/zsyscall_linux_386.go
index dcb9547..ef9602c 100644
--- a/unix/zsyscall_linux_386.go
+++ b/unix/zsyscall_linux_386.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_amd64.go b/unix/zsyscall_linux_amd64.go
index badf57e..63054b3 100644
--- a/unix/zsyscall_linux_amd64.go
+++ b/unix/zsyscall_linux_amd64.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_arm.go b/unix/zsyscall_linux_arm.go
index 69765c3..8b10ee1 100644
--- a/unix/zsyscall_linux_arm.go
+++ b/unix/zsyscall_linux_arm.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_arm64.go b/unix/zsyscall_linux_arm64.go
index dc8e642..8f276d6 100644
--- a/unix/zsyscall_linux_arm64.go
+++ b/unix/zsyscall_linux_arm64.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_mips.go b/unix/zsyscall_linux_mips.go
index 59f50c8..61169b3 100644
--- a/unix/zsyscall_linux_mips.go
+++ b/unix/zsyscall_linux_mips.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_mips64.go b/unix/zsyscall_linux_mips64.go
index 3803380..4cb59b4 100644
--- a/unix/zsyscall_linux_mips64.go
+++ b/unix/zsyscall_linux_mips64.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_mips64le.go b/unix/zsyscall_linux_mips64le.go
index fee2f85..0b547ae 100644
--- a/unix/zsyscall_linux_mips64le.go
+++ b/unix/zsyscall_linux_mips64le.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_mipsle.go b/unix/zsyscall_linux_mipsle.go
index 4094d3d..cd94d3a 100644
--- a/unix/zsyscall_linux_mipsle.go
+++ b/unix/zsyscall_linux_mipsle.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_ppc64.go b/unix/zsyscall_linux_ppc64.go
index d83bafb..cdad555 100644
--- a/unix/zsyscall_linux_ppc64.go
+++ b/unix/zsyscall_linux_ppc64.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_ppc64le.go b/unix/zsyscall_linux_ppc64le.go
index 460971c..38f4e44 100644
--- a/unix/zsyscall_linux_ppc64le.go
+++ b/unix/zsyscall_linux_ppc64le.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/zsyscall_linux_s390x.go b/unix/zsyscall_linux_s390x.go
index b7ef121..c443baf 100644
--- a/unix/zsyscall_linux_s390x.go
+++ b/unix/zsyscall_linux_s390x.go
@@ -1238,6 +1238,21 @@
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
+func Statx(dirfd int, path string, flags int, mask int, stat *Statx_t) (err error) {
+	var _p0 *byte
+	_p0, err = BytePtrFromString(path)
+	if err != nil {
+		return
+	}
+	_, _, e1 := Syscall6(SYS_STATX, uintptr(dirfd), uintptr(unsafe.Pointer(_p0)), uintptr(flags), uintptr(mask), uintptr(unsafe.Pointer(stat)), 0)
+	if e1 != 0 {
+		err = errnoErr(e1)
+	}
+	return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
 func Sync() {
 	SyscallNoError(SYS_SYNC, 0, 0, 0)
 	return
diff --git a/unix/ztypes_linux_386.go b/unix/ztypes_linux_386.go
index 1bb1a5e..7cf0a74 100644
--- a/unix/ztypes_linux_386.go
+++ b/unix/ztypes_linux_386.go
@@ -131,6 +131,36 @@
 	Spare   [4]int32
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -643,9 +673,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_amd64.go b/unix/ztypes_linux_amd64.go
index 081c607..1671205 100644
--- a/unix/ztypes_linux_amd64.go
+++ b/unix/ztypes_linux_amd64.go
@@ -131,6 +131,36 @@
 	Spare   [4]int64
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -661,9 +691,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_arm.go b/unix/ztypes_linux_arm.go
index 904510d..cc0c3de 100644
--- a/unix/ztypes_linux_arm.go
+++ b/unix/ztypes_linux_arm.go
@@ -133,6 +133,36 @@
 	Pad_cgo_0 [4]byte
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -632,9 +662,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_arm64.go b/unix/ztypes_linux_arm64.go
index 5da8cef..d82cca9 100644
--- a/unix/ztypes_linux_arm64.go
+++ b/unix/ztypes_linux_arm64.go
@@ -132,6 +132,36 @@
 	Spare   [4]int64
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -640,9 +670,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_mips.go b/unix/ztypes_linux_mips.go
index 2707c36..f9a7fae 100644
--- a/unix/ztypes_linux_mips.go
+++ b/unix/ztypes_linux_mips.go
@@ -132,6 +132,36 @@
 	Pad_cgo_1 [4]byte
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -637,9 +667,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_mips64.go b/unix/ztypes_linux_mips64.go
index 23e9da6..5b6c48f 100644
--- a/unix/ztypes_linux_mips64.go
+++ b/unix/ztypes_linux_mips64.go
@@ -132,6 +132,36 @@
 	Spare   [5]int64
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -642,9 +672,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_mips64le.go b/unix/ztypes_linux_mips64le.go
index 1090dc1..23af0f5 100644
--- a/unix/ztypes_linux_mips64le.go
+++ b/unix/ztypes_linux_mips64le.go
@@ -132,6 +132,36 @@
 	Spare   [5]int64
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -642,9 +672,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_mipsle.go b/unix/ztypes_linux_mipsle.go
index dff3f1f..32f2a86 100644
--- a/unix/ztypes_linux_mipsle.go
+++ b/unix/ztypes_linux_mipsle.go
@@ -132,6 +132,36 @@
 	Pad_cgo_1 [4]byte
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -637,9 +667,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_ppc64.go b/unix/ztypes_linux_ppc64.go
index 86c7475..51f6778 100644
--- a/unix/ztypes_linux_ppc64.go
+++ b/unix/ztypes_linux_ppc64.go
@@ -133,6 +133,36 @@
 	Spare   [4]int64
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -650,9 +680,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_ppc64le.go b/unix/ztypes_linux_ppc64le.go
index 1cc159e..59497fe 100644
--- a/unix/ztypes_linux_ppc64le.go
+++ b/unix/ztypes_linux_ppc64le.go
@@ -133,6 +133,36 @@
 	Spare   [4]int64
 }
 
+type StatxTimestamp struct {
+	Sec         int64
+	Nsec        uint32
+	X__reserved int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino       uint64
 	Off       int64
@@ -650,9 +680,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STATX_SYNC_AS_STAT = 0x0
+	AT_STATX_FORCE_SYNC   = 0x2000
+	AT_STATX_DONT_SYNC    = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )
diff --git a/unix/ztypes_linux_s390x.go b/unix/ztypes_linux_s390x.go
index 2d27c0f..c064b3b 100644
--- a/unix/ztypes_linux_s390x.go
+++ b/unix/ztypes_linux_s390x.go
@@ -132,6 +132,36 @@
 	_       [4]byte
 }
 
+type StatxTimestamp struct {
+	Sec  int64
+	Nsec uint32
+	_    int32
+}
+
+type Statx_t struct {
+	Mask            uint32
+	Blksize         uint32
+	Attributes      uint64
+	Nlink           uint32
+	Uid             uint32
+	Gid             uint32
+	Mode            uint16
+	_               [1]uint16
+	Ino             uint64
+	Size            uint64
+	Blocks          uint64
+	Attributes_mask uint64
+	Atime           StatxTimestamp
+	Btime           StatxTimestamp
+	Ctime           StatxTimestamp
+	Mtime           StatxTimestamp
+	Rdev_major      uint32
+	Rdev_minor      uint32
+	Dev_major       uint32
+	Dev_minor       uint32
+	_               [14]uint64
+}
+
 type Dirent struct {
 	Ino    uint64
 	Off    int64
@@ -667,9 +697,15 @@
 }
 
 const (
-	AT_FDCWD            = -0x64
-	AT_NO_AUTOMOUNT     = 0x800
-	AT_REMOVEDIR        = 0x200
+	AT_EMPTY_PATH   = 0x1000
+	AT_FDCWD        = -0x64
+	AT_NO_AUTOMOUNT = 0x800
+	AT_REMOVEDIR    = 0x200
+
+	AT_STAT_ = 0x0
+	AT_STAT_ = 0x2000
+	AT_STAT_ = 0x4000
+
 	AT_SYMLINK_FOLLOW   = 0x400
 	AT_SYMLINK_NOFOLLOW = 0x100
 )