• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Referred from linux kernel -github/torvalds/linux/include/uapi/linux/fcntl.h
4  * Copyright (c) Zilogic Systems Pvt. Ltd., 2018
5  * Email: code@zilogic.com
6  */
7 
8 #ifndef LAPI_STAT_H__
9 #define LAPI_STAT_H__
10 
11 #include <stdint.h>
12 #include <unistd.h>
13 #include <sys/stat.h>
14 #include "lapi/syscalls.h"
15 
16 /*
17  * Timestamp structure for the timestamps in struct statx.
18  *
19  * tv_sec holds the number of seconds before (negative) or after (positive)
20  * 00:00:00 1st January 1970 UTC.
21  *
22  * tv_nsec holds a number of nanoseconds (0..999,999,999) after the tv_sec time.
23  *
24  * __reserved is held in case we need a yet finer resolution.
25  */
26 #ifndef HAVE_STRUCT_STATX_TIMESTAMP
27 struct statx_timestamp {
28 	int64_t tv_sec;
29 	uint32_t tv_nsec;
30 	int32_t __reserved;
31 };
32 #endif
33 
34 /*
35  * Structures for the extended file attribute retrieval system call
36  * (statx()).
37  *
38  * The caller passes a mask of what they're specifically interested in as a
39  * parameter to statx().  What statx() actually got will be indicated in
40  * st_mask upon return.
41  *
42  * For each bit in the mask argument:
43  *
44  * - if the datum is not supported:
45  *
46  *   - the bit will be cleared, and
47  *
48  *   - the datum will be set to an appropriate fabricated value if one is
49  *     available (eg. CIFS can take a default uid and gid), otherwise
50  *
51  *   - the field will be cleared;
52  *
53  * - otherwise, if explicitly requested:
54  *
55  *   - the datum will be synchronised to the server if AT_STATX_FORCE_SYNC is
56  *     set or if the datum is considered out of date, and
57  *
58  *   - the field will be filled in and the bit will be set;
59  *
60  * - otherwise, if not requested, but available in approximate form without any
61  *   effort, it will be filled in anyway, and the bit will be set upon return
62  *   (it might not be up to date, however, and no attempt will be made to
63  *   synchronise the internal state first);
64  *
65  * - otherwise the field and the bit will be cleared before returning.
66  *
67  * Items in STATX_BASIC_STATS may be marked unavailable on return, but they
68  * will have values installed for compatibility purposes so that stat() and
69  * co. can be emulated in userspace.
70  */
71  #define LTP_DEFINE_STATX_STRUCT(x) \
72  	struct x { \
73 	uint32_t	stx_mask; \
74 	uint32_t	stx_blksize; \
75 	uint64_t	stx_attributes; \
76 	uint32_t	stx_nlink; \
77 	uint32_t	stx_uid; \
78 	uint32_t	stx_gid; \
79 	uint16_t	stx_mode; \
80 	uint16_t	__spare0[1]; \
81 	uint64_t	stx_ino; \
82 	uint64_t	stx_size; \
83 	uint64_t	stx_blocks; \
84 	uint64_t	stx_attributes_mask; \
85 	const struct statx_timestamp	stx_atime; \
86 	const struct statx_timestamp	stx_btime; \
87 	const struct statx_timestamp	stx_ctime; \
88 	const struct statx_timestamp	stx_mtime; \
89 	uint32_t	stx_rdev_major; \
90 	uint32_t	stx_rdev_minor; \
91 	uint32_t	stx_dev_major; \
92 	uint32_t	stx_dev_minor; \
93 	uint64_t	stx_mnt_id; \
94 	uint32_t	stx_dio_mem_align; \
95 	uint32_t	stx_dio_offset_align; \
96 	uint64_t	__spare3[12]; \
97 };
98 
99 LTP_DEFINE_STATX_STRUCT(statx_fallback);
100 
101 #ifndef HAVE_STRUCT_STATX
102 LTP_DEFINE_STATX_STRUCT(statx);
103 #endif
104 
105 /*
106  * This is the fallback statx that we pass to the safe_statx() syscall.
107  * The reason why we need it, is that statx struct is constantly changing
108  * inside the kernel and we need to extend its definition when structure
109  * changes in order to compile the tests.
110  */
111 struct ltp_statx {
112 	union {
113 		struct statx buff;
114 		struct statx_fallback data;
115 	};
116 };
117 
118 #ifndef HAVE_STATX
119 
120 /*
121  * statx: wrapper function of statx
122  *
123  * Returns: It returns status of statx syscall
124  */
statx(int dirfd,const char * pathname,unsigned int flags,unsigned int mask,struct statx * st)125 static inline int statx(int dirfd, const char *pathname, unsigned int flags,
126 			unsigned int mask, struct statx *st)
127 {
128 	return tst_syscall(__NR_statx, dirfd, pathname, flags, mask, st);
129 }
130 #endif
131 
132 /*
133  * Flags to be stx_mask
134  *
135  * Query request/result mask for statx() and struct statx::stx_mask.
136  *
137  * These bits should be set in the mask argument of statx() to request
138  * particular items when calling statx().
139  */
140 #ifndef STATX_TYPE
141 # define STATX_TYPE		0x00000001U
142 #endif
143 
144 #ifndef STATX_MODE
145 # define STATX_MODE		0x00000002U
146 #endif
147 
148 #ifndef STATX_NLINK
149 # define STATX_NLINK		0x00000004U
150 #endif
151 
152 #ifndef STATX_UID
153 # define STATX_UID		0x00000008U
154 #endif
155 
156 #ifndef STATX_GID
157 # define STATX_GID		0x00000010U
158 #endif
159 
160 #ifndef STATX_ATIME
161 # define STATX_ATIME		0x00000020U
162 #endif
163 
164 #ifndef STATX_MTIME
165 # define STATX_MTIME		0x00000040U
166 #endif
167 
168 #ifndef STATX_CTIME
169 # define STATX_CTIME		0x00000080U
170 #endif
171 
172 #ifndef STATX_INO
173 # define STATX_INO		0x00000100U
174 #endif
175 
176 #ifndef STATX_SIZE
177 # define STATX_SIZE		0x00000200U
178 #endif
179 
180 #ifndef STATX_BLOCKS
181 # define STATX_BLOCKS		0x00000400U
182 #endif
183 
184 #ifndef STATX_BASIC_STATS
185 # define STATX_BASIC_STATS	0x000007ffU
186 #endif
187 
188 #ifndef STATX_BTIME
189 # define STATX_BTIME		0x00000800U
190 #endif
191 
192 #ifndef STATX_MNT_ID
193 # define STATX_MNT_ID		0x00001000U
194 #endif
195 
196 #ifndef STATX_DIOALIGN
197 # define STATX_DIOALIGN		0x00002000U
198 #endif
199 
200 #ifndef STATX__RESERVED
201 # define STATX__RESERVED	0x80000000U
202 #endif
203 
204 /*
205  * Attributes to be found in stx_attributes and masked in stx_attributes_mask.
206  *
207  * These give information about the features or the state of a file that might
208  * be of use to ordinary userspace programs such as GUIs or ls rather than
209  * specialised tools.
210  *
211  * Note that the flags marked [I] correspond to generic FS_IOC_FLAGS
212  * semantically.  Where possible, the numerical value is picked to correspond
213  * also.
214  */
215 #ifndef STATX_ATTR_COMPRESSED
216 # define STATX_ATTR_COMPRESSED	0x00000004
217 #endif
218 
219 #ifndef STATX_ATTR_IMMUTABLE
220 # define STATX_ATTR_IMMUTABLE	0x00000010
221 #endif
222 
223 #ifndef STATX_ATTR_APPEND
224 # define STATX_ATTR_APPEND	0x00000020
225 #endif
226 
227 #ifndef STATX_ATTR_NODUMP
228 # define STATX_ATTR_NODUMP	0x00000040
229 #endif
230 
231 #ifndef STATX_ATTR_ENCRYPTED
232 # define STATX_ATTR_ENCRYPTED	0x00000800
233 #endif
234 
235 #ifndef STATX_ATTR_AUTOMOUNT
236 # define STATX_ATTR_AUTOMOUNT	0x00001000
237 #endif
238 
239 #ifndef STATX_ATTR_MOUNT_ROOT
240 # define STATX_ATTR_MOUNT_ROOT	0x00002000
241 #endif
242 
243 #ifndef STATX_ATTR_VERITY
244 # define STATX_ATTR_VERITY	0x00100000
245 #endif
246 
247 #ifndef STATX_MNT_ID_UNIQUE
248 # define STATX_MNT_ID_UNIQUE  0x00004000U
249 #endif
250 
251 #define SAFE_FCHMODAT2(dfd, filename, mode, flags) \
252 	safe_fchmodat2(__FILE__, __LINE__, (dfd), (filename), (mode), (flags))
253 
safe_fchmodat2(const char * file,const int lineno,int dfd,const char * filename,mode_t mode,int flags)254 static inline int safe_fchmodat2(const char *file, const int lineno,
255 		int dfd, const char *filename, mode_t mode, int flags)
256 {
257 	int ret;
258 
259 	ret = tst_syscall(__NR_fchmodat2, dfd, filename, mode, flags);
260 	if (ret == -1) {
261 		tst_brk_(file, lineno, TBROK | TERRNO,
262 			 "syscall(__NR_fchmodat2,%d,%s,%d,%d) failed",
263 			 dfd, filename, mode, flags);
264 	} else if (ret) {
265 		tst_brk_(file, lineno, TBROK | TERRNO,
266 			 "Invalid syscall(__NR_fchmodat2,%d,%s,%d,%d) return value %d",
267 			 dfd, filename, mode, flags, ret);
268 	}
269 
270 	return ret;
271 }
272 
273 #define SAFE_STATX(dirfd, pathname, flags, mask, buf) \
274 	safe_statx(__FILE__, __LINE__, (dirfd), (pathname), (flags), (mask), (buf))
275 
safe_statx(const char * file,const int lineno,int dirfd,const char * pathname,int flags,unsigned int mask,struct ltp_statx * buf)276 static inline int safe_statx(const char *file, const int lineno,
277 	int dirfd, const char *pathname, int flags, unsigned int mask,
278 	struct ltp_statx *buf)
279 {
280 	int rval;
281 
282 	rval = statx(dirfd, pathname, flags, mask, &buf->buff);
283 
284 	if (rval == -1) {
285 		tst_brk_(file, lineno, TBROK | TERRNO,
286 			"statx(%d,%s,%d,%u,%p) failed", dirfd, pathname, flags, mask, buf);
287 	} else if (rval) {
288 		tst_brk_(file, lineno, TBROK | TERRNO,
289 			"Invalid statx(%d,%s,%d,%u,%p) return value %d",
290 			dirfd, pathname, flags, mask, buf,
291 			rval);
292 	}
293 
294 	return rval;
295 }
296 
297 #endif /* LAPI_STAT_H__ */
298