1 | //===-- Wrapper over SYS_statx syscall ------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_LIBC_SRC_SYS_STAT_LINUX_KERNEL_STATX_H |
10 | #define LLVM_LIBC_SRC_SYS_STAT_LINUX_KERNEL_STATX_H |
11 | |
12 | #include "src/__support/OSUtil/syscall.h" // For internal syscall function. |
13 | #include "src/__support/common.h" |
14 | #include "src/__support/macros/config.h" |
15 | |
16 | #include <stdint.h> |
17 | #include <sys/stat.h> |
18 | #include <sys/syscall.h> // For syscall numbers. |
19 | |
20 | // It is safe to include this kernel header as it is designed to be |
21 | // included from user programs without causing any name pollution. |
22 | #include <linux/kdev_t.h> |
23 | |
24 | namespace { |
25 | |
26 | // The type definitions in the internal namespace match kernel's definition of |
27 | // the statx_timestamp and statx types in linux/stat.h. We define equivalent |
28 | // types here instead of including that header file to avoid name mixup between |
29 | // linux/stat.h and the libc's stat.h. |
30 | struct statx_timestamp { |
31 | int64_t tv_sec; |
32 | uint32_t tv_nsec; |
33 | int32_t __reserved; |
34 | }; |
35 | |
36 | struct statx_buf { |
37 | uint32_t stx_mask; // What results were written |
38 | uint32_t stx_blksize; // Preferred general I/O size |
39 | uint64_t stx_attributes; // Flags conveying information about the file |
40 | uint32_t stx_nlink; // Number of hard links |
41 | uint32_t stx_uid; // User ID of owner |
42 | uint32_t stx_gid; // Group ID of owner |
43 | uint16_t stx_mode; // File mode |
44 | uint16_t __spare0[1]; |
45 | uint64_t stx_ino; // Inode number |
46 | uint64_t stx_size; // File size |
47 | uint64_t stx_blocks; // Number of 512-byte blocks allocated |
48 | uint64_t stx_attributes_mask; // Mask to show what's supported in |
49 | // stx_attributes |
50 | struct statx_timestamp stx_atime; // Last access time |
51 | struct statx_timestamp stx_btime; // File creation time |
52 | struct statx_timestamp stx_ctime; // Last attribute change time |
53 | struct statx_timestamp stx_mtime; // Last data modification time |
54 | uint32_t stx_rdev_major; // Device ID of special file |
55 | uint32_t stx_rdev_minor; |
56 | uint32_t stx_dev_major; // ID of device containing file |
57 | uint32_t stx_dev_minor; |
58 | uint64_t stx_mnt_id; |
59 | uint64_t __spare2; |
60 | uint64_t __spare3[12]; // Spare space for future expansion |
61 | }; |
62 | |
63 | // The below mask value is based on the definition of a similarly |
64 | // named macro in linux/stat.h. When this flag is passed for the |
65 | // mask argument to the statx syscall, all fields except the |
66 | // stx_btime field will be filled in. |
67 | constexpr unsigned int STATX_BASIC_STATS_MASK = 0x7FF; |
68 | |
69 | } // Anonymous namespace |
70 | |
71 | namespace LIBC_NAMESPACE_DECL { |
72 | |
73 | LIBC_INLINE int statx(int dirfd, const char *__restrict path, int flags, |
74 | struct stat *__restrict statbuf) { |
75 | // We make a statx syscall and copy out the result into the |statbuf|. |
76 | ::statx_buf xbuf; |
77 | int ret = LIBC_NAMESPACE::syscall_impl<int>(SYS_statx, dirfd, path, flags, |
78 | ::STATX_BASIC_STATS_MASK, &xbuf); |
79 | if (ret < 0) |
80 | return -ret; |
81 | |
82 | statbuf->st_dev = MKDEV(xbuf.stx_dev_major, xbuf.stx_dev_minor); |
83 | statbuf->st_ino = static_cast<decltype(statbuf->st_ino)>(xbuf.stx_ino); |
84 | statbuf->st_mode = xbuf.stx_mode; |
85 | statbuf->st_nlink = xbuf.stx_nlink; |
86 | statbuf->st_uid = xbuf.stx_uid; |
87 | statbuf->st_gid = xbuf.stx_gid; |
88 | statbuf->st_rdev = MKDEV(xbuf.stx_rdev_major, xbuf.stx_rdev_minor); |
89 | statbuf->st_size = xbuf.stx_size; |
90 | statbuf->st_atim.tv_sec = xbuf.stx_atime.tv_sec; |
91 | statbuf->st_atim.tv_nsec = xbuf.stx_atime.tv_nsec; |
92 | statbuf->st_mtim.tv_sec = xbuf.stx_mtime.tv_sec; |
93 | statbuf->st_mtim.tv_nsec = xbuf.stx_mtime.tv_nsec; |
94 | statbuf->st_ctim.tv_sec = xbuf.stx_ctime.tv_sec; |
95 | statbuf->st_ctim.tv_nsec = xbuf.stx_ctime.tv_nsec; |
96 | statbuf->st_blksize = xbuf.stx_blksize; |
97 | statbuf->st_blocks = |
98 | static_cast<decltype(statbuf->st_blocks)>(xbuf.stx_blocks); |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | } // namespace LIBC_NAMESPACE_DECL |
104 | |
105 | #endif // LLVM_LIBC_SRC_SYS_STAT_LINUX_KERNEL_STATX_H |
106 | |