2 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
3 * Copyright (c) 2015-2017 The strace developers.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #if defined HAVE_FTRUNCATE && defined HAVE_FUTIMENS
31 # ifndef TEST_SYSCALL_STR
32 # error TEST_SYSCALL_STR must be defined
34 # ifndef TEST_SYSCALL_INVOKE
35 # error TEST_SYSCALL_INVOKE must be defined
37 # ifndef PRINT_SYSCALL_HEADER
38 # error PRINT_SYSCALL_HEADER must be defined
40 # ifndef PRINT_SYSCALL_FOOTER
41 # error PRINT_SYSCALL_FOOTER must be defined
49 # include <sys/sysmacros.h>
54 # define STRUCT_STAT struct stat
55 # define STRUCT_STAT_STR "struct stat"
56 # define STRUCT_STAT_IS_STAT64 0
59 # define SAMPLE_SIZE ((libc_off_t) 43147718418ULL)
62 typedef off_t libc_off_t;
64 # define stat libc_stat
65 # define stat64 libc_stat64
67 # include <sys/stat.h>
74 # include "asm_stat.h"
76 # if STRUCT_STAT_IS_STAT64
77 # undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
78 # if defined MPERS_IS_m32
79 # ifdef HAVE_M32_STRUCT_STAT64_ST_MTIME_NSEC
80 # define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
82 # elif defined MPERS_IS_mx32
83 # ifdef HAVE_MX32_STRUCT_STAT64_ST_MTIME_NSEC
84 # define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
86 # elif defined HAVE_STRUCT_STAT64_ST_MTIME_NSEC
87 # define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
88 # endif /* MPERS_IS_m32 || MPERS_IS_mx32 || HAVE_STRUCT_STAT64_ST_MTIME_NSEC */
89 # else /* !STRUCT_STAT_IS_STAT64 */
90 # if defined MPERS_IS_m32
91 # undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
92 # ifdef HAVE_M32_STRUCT_STAT_ST_MTIME_NSEC
93 # define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
95 # elif defined MPERS_IS_mx32
96 # undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
97 # ifdef HAVE_MX32_STRUCT_STAT_ST_MTIME_NSEC
98 # define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
100 # endif /* MPERS_IS_m32 || MPERS_IS_mx32 */
101 # endif /* STRUCT_STAT_IS_STAT64 */
103 # ifndef TEST_BOGUS_STRUCT_STAT
104 # define TEST_BOGUS_STRUCT_STAT 1
120 print_ftype(const unsigned int mode)
124 else if (S_ISDIR(mode))
126 else if (S_ISCHR(mode))
128 else if (S_ISBLK(mode))
131 printf("%#o", mode & S_IFMT);
135 print_perms(const unsigned int mode)
137 printf("%#o", mode & ~S_IFMT);
143 print_stat(const STRUCT_STAT *st)
145 printf("{st_dev=makedev(%u, %u)",
146 (unsigned int) major(zero_extend_signed_to_ull(st->st_dev)),
147 (unsigned int) minor(zero_extend_signed_to_ull(st->st_dev)));
148 printf(", st_ino=%llu", zero_extend_signed_to_ull(st->st_ino));
149 printf(", st_mode=");
150 print_ftype(st->st_mode);
152 print_perms(st->st_mode);
153 printf(", st_nlink=%llu", zero_extend_signed_to_ull(st->st_nlink));
154 printf(", st_uid=%llu", zero_extend_signed_to_ull(st->st_uid));
155 printf(", st_gid=%llu", zero_extend_signed_to_ull(st->st_gid));
157 printf(", st_blksize=0, st_blocks=0");
158 # else /* !OLD_STAT */
159 printf(", st_blksize=%llu", zero_extend_signed_to_ull(st->st_blksize));
160 printf(", st_blocks=%llu", zero_extend_signed_to_ull(st->st_blocks));
161 # endif /* OLD_STAT */
163 switch (st->st_mode & S_IFMT) {
164 case S_IFCHR: case S_IFBLK:
165 printf(", st_rdev=makedev(%u, %u)",
166 (unsigned int) major(zero_extend_signed_to_ull(st->st_rdev)),
167 (unsigned int) minor(zero_extend_signed_to_ull(st->st_rdev)));
170 printf(", st_size=%llu", zero_extend_signed_to_ull(st->st_size));
173 # if defined(HAVE_STRUCT_STAT_ST_MTIME_NSEC) && !OLD_STAT
174 # define TIME_NSEC(val) zero_extend_signed_to_ull(val)
177 # define TIME_NSEC(val) 0ULL
181 #define PRINT_ST_TIME(field) \
182 printf(", st_" #field "=%lld", \
183 sign_extend_unsigned_to_ll(st->st_ ## field)); \
184 print_time_t_nsec(sign_extend_unsigned_to_ll(st->st_ ## field), \
185 TIME_NSEC(st->st_ ## field ## _nsec), 1); \
187 printf(", st_" #field "_nsec=%llu", \
188 TIME_NSEC(st->st_ ## field ## _nsec))
190 PRINT_ST_TIME(atime);
191 PRINT_ST_TIME(mtime);
192 PRINT_ST_TIME(ctime);
196 # else /* !IS_STATX */
199 print_stat(const STRUCT_STAT *st)
201 # define PRINT_FIELD_U(field) \
202 printf(", %s=%llu", #field, (unsigned long long) st->field)
204 # define PRINT_FIELD_U32_UID(field) \
205 if (st->field == (uint32_t) -1) \
206 printf(", %s=-1", #field); \
208 printf(", %s=%llu", #field, (unsigned long long) st->field)
210 # define PRINT_FIELD_TIME(field) \
211 printf(", %s={tv_sec=%lld, tv_nsec=%u}", \
212 #field, (long long) st->field.tv_sec, \
213 (unsigned) st->field.tv_nsec); \
214 print_time_t_nsec(st->field.tv_sec, \
215 zero_extend_signed_to_ull(st->field.tv_nsec), 1);
217 printf("{stx_mask=");
218 printflags(statx_masks, st->stx_mask, "STATX_???");
220 PRINT_FIELD_U(stx_blksize);
222 printf(", stx_attributes=");
223 printflags(statx_attrs, st->stx_attributes, "STATX_ATTR_???");
225 PRINT_FIELD_U(stx_nlink);
226 PRINT_FIELD_U32_UID(stx_uid);
227 PRINT_FIELD_U32_UID(stx_gid);
229 printf(", stx_mode=");
230 print_ftype(st->stx_mode);
232 print_perms(st->stx_mode);
234 PRINT_FIELD_U(stx_ino);
235 PRINT_FIELD_U(stx_size);
236 PRINT_FIELD_U(stx_blocks);
238 printf(", stx_attributes_mask=");
239 printflags(statx_attrs, st->stx_attributes_mask, "STATX_ATTR_???");
241 PRINT_FIELD_TIME(stx_atime);
242 PRINT_FIELD_TIME(stx_btime);
243 PRINT_FIELD_TIME(stx_ctime);
244 PRINT_FIELD_TIME(stx_mtime);
245 PRINT_FIELD_U(stx_rdev_major);
246 PRINT_FIELD_U(stx_rdev_minor);
247 PRINT_FIELD_U(stx_dev_major);
248 PRINT_FIELD_U(stx_dev_minor);
252 # endif /* !IS_STATX */
255 create_sample(const char *fname, const libc_off_t size)
257 static const struct timespec ts[] = {
258 {-10843, 135}, {-10841, 246}
262 if (open(fname, O_RDWR | O_CREAT | O_TRUNC, 0640)) {
266 if (ftruncate(0, size)) {
270 if (futimens(0, ts)) {
281 skip_if_unavailable("/proc/self/fd/");
283 static const char full[] = "/dev/full";
285 static const char sample[] = "stat.sample";
286 TAIL_ALLOC_OBJECT_CONST_PTR(STRUCT_STAT, st);
290 rc = create_sample(sample, SAMPLE_SIZE);
294 # if TEST_BOGUS_STRUCT_STAT
295 STRUCT_STAT *st_cut = tail_alloc(sizeof(long) * 4);
296 rc = TEST_SYSCALL_INVOKE(sample, st_cut);
297 PRINT_SYSCALL_HEADER(sample);
298 printf("%p", st_cut);
299 PRINT_SYSCALL_FOOTER(rc);
303 rc = TEST_SYSCALL_INVOKE(full, st);
304 PRINT_SYSCALL_HEADER(full);
309 PRINT_SYSCALL_FOOTER(rc);
312 if ((rc = TEST_SYSCALL_INVOKE(sample, st))) {
313 if (errno != EOVERFLOW) {
314 rc = (errno == ENOSYS) ? 77 : 1;
315 perror(TEST_SYSCALL_STR);
321 # define ST_SIZE_FIELD stx_size
323 # define ST_SIZE_FIELD st_size
325 if (!rc && zero_extend_signed_to_ull(SAMPLE_SIZE) !=
326 zero_extend_signed_to_ull(st->ST_SIZE_FIELD)) {
327 fprintf(stderr, "Size mismatch: "
328 "requested size(%llu) != st_size(%llu)\n",
329 zero_extend_signed_to_ull(SAMPLE_SIZE),
330 zero_extend_signed_to_ull(st->ST_SIZE_FIELD));
331 fprintf(stderr, "The most likely reason for this is incorrect"
332 " definition of %s.\n"
333 "Here is some diagnostics that might help:\n",
336 # define LOG_STAT_OFFSETOF_SIZEOF(object, member) \
337 fprintf(stderr, "offsetof(%s, %s) = %zu" \
338 ", sizeof(%s) = %zu\n", \
339 STRUCT_STAT_STR, #member, \
340 offsetof(STRUCT_STAT, member), \
341 #member, sizeof((object).member))
344 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_mask);
345 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_blksize);
346 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_attributes);
347 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_nlink);
348 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_uid);
349 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_gid);
350 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_mode);
351 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_ino);
352 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_size);
353 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_blocks);
354 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_attributes_mask);
355 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_atime);
356 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_btime);
357 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_ctime);
358 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_mtime);
359 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_rdev_major);
360 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_rdev_minor);
361 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_dev_major);
362 LOG_STAT_OFFSETOF_SIZEOF(*st, stx_dev_minor);
364 LOG_STAT_OFFSETOF_SIZEOF(*st, st_dev);
365 LOG_STAT_OFFSETOF_SIZEOF(*st, st_ino);
366 LOG_STAT_OFFSETOF_SIZEOF(*st, st_mode);
367 LOG_STAT_OFFSETOF_SIZEOF(*st, st_nlink);
368 LOG_STAT_OFFSETOF_SIZEOF(*st, st_uid);
369 LOG_STAT_OFFSETOF_SIZEOF(*st, st_gid);
370 LOG_STAT_OFFSETOF_SIZEOF(*st, st_rdev);
371 LOG_STAT_OFFSETOF_SIZEOF(*st, st_size);
373 LOG_STAT_OFFSETOF_SIZEOF(*st, st_blksize);
374 LOG_STAT_OFFSETOF_SIZEOF(*st, st_blocks);
375 # endif /* !OLD_STAT */
377 # endif /* IS_STATX */
382 PRINT_SYSCALL_HEADER(sample);
387 PRINT_SYSCALL_FOOTER(rc);
392 rc = TEST_SYSCALL_INVOKE(sample, st); \
393 PRINT_SYSCALL_HEADER(sample); \
398 PRINT_SYSCALL_FOOTER(rc)
400 # define SET_FLAGS_INVOKE(flags, flags_str) \
401 TEST_SYSCALL_STATX_FLAGS = flags; \
402 TEST_SYSCALL_STATX_FLAGS_STR = flags_str; \
405 # define SET_MASK_INVOKE(mask, mask_str) \
406 TEST_SYSCALL_STATX_MASK = mask; \
407 TEST_SYSCALL_STATX_MASK_STR = mask_str; \
410 unsigned old_flags = TEST_SYSCALL_STATX_FLAGS;
411 const char *old_flags_str = TEST_SYSCALL_STATX_FLAGS_STR;
412 unsigned old_mask = TEST_SYSCALL_STATX_MASK;
413 const char *old_mask_str = TEST_SYSCALL_STATX_MASK_STR;
415 SET_FLAGS_INVOKE(AT_SYMLINK_FOLLOW | 0xffff0000U,
416 "AT_STATX_SYNC_AS_STAT|AT_SYMLINK_FOLLOW|0xffff0000");
418 SET_FLAGS_INVOKE(AT_STATX_SYNC_TYPE,
419 "AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC");
421 SET_FLAGS_INVOKE(0xffffff,
422 "AT_STATX_FORCE_SYNC|AT_STATX_DONT_SYNC|AT_SYMLINK_NOFOLLOW|"
423 "AT_REMOVEDIR|AT_SYMLINK_FOLLOW|AT_NO_AUTOMOUNT|AT_EMPTY_PATH|"
426 /* We're done playing with flags. */
427 TEST_SYSCALL_STATX_FLAGS = old_flags;
428 TEST_SYSCALL_STATX_FLAGS_STR = old_flags_str;
430 SET_MASK_INVOKE(0, "0");
431 SET_MASK_INVOKE(0xfffff000U, "0xfffff000 /* STATX_??? */");
433 SET_MASK_INVOKE(0xfffffffbU,
434 "STATX_TYPE|STATX_MODE|STATX_UID|STATX_GID|STATX_ATIME|"
435 "STATX_MTIME|STATX_CTIME|STATX_INO|STATX_SIZE|STATX_BLOCKS|"
436 "STATX_BTIME|0xfffff000");
438 SET_MASK_INVOKE(STATX_UID, "STATX_UID");
440 /* ...and with mask. */
441 TEST_SYSCALL_STATX_MASK = old_mask;
442 TEST_SYSCALL_STATX_MASK_STR = old_mask_str;
444 # endif /* IS_STATX */
446 puts("+++ exited with 0 +++");
452 SKIP_MAIN_UNDEFINED("HAVE_FTRUNCATE && HAVE_FUTIMENS")