blob: a9fb8e8a5e8e49a7688d27b717a6d5a8e72045e5 [file] [log] [blame]
Dmitry V. Levincc2baf32015-12-05 00:01:56 +00001/*
Dmitry V. Levin6c52f2b2016-01-05 22:37:42 +00002 * Copyright (c) 2015-2016 Dmitry V. Levin <ldv@altlinux.org>
Dmitry V. Levincc2baf32015-12-05 00:01:56 +00003 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
Dmitry V. Levin6c52f2b2016-01-05 22:37:42 +000028#if defined HAVE_FTRUNCATE && defined HAVE_FUTIMENS
Dmitry V. Levincc2baf32015-12-05 00:01:56 +000029
Dmitry V. Levin7bbf8b52016-01-12 00:03:41 +000030# ifndef TEST_SYSCALL_STR
31# error TEST_SYSCALL_STR must be defined
Dmitry V. Levin6c52f2b2016-01-05 22:37:42 +000032# endif
Dmitry V. Levincc2baf32015-12-05 00:01:56 +000033# ifndef TEST_SYSCALL_INVOKE
34# error TEST_SYSCALL_INVOKE must be defined
35# endif
36# ifndef PRINT_SYSCALL_HEADER
37# error PRINT_SYSCALL_HEADER must be defined
38# endif
39# ifndef PRINT_SYSCALL_FOOTER
40# error PRINT_SYSCALL_FOOTER must be defined
41# endif
42
Dmitry V. Levincc2baf32015-12-05 00:01:56 +000043# include <stdio.h>
44# include <stddef.h>
45# include <time.h>
46# include <unistd.h>
47
48# if defined MAJOR_IN_SYSMACROS
49# include <sys/sysmacros.h>
50# elif defined MAJOR_IN_MKDEV
51# include <sys/mkdev.h>
52# else
53# include <sys/types.h>
54# endif
55
56static void
57print_time(const time_t t)
58{
59 if (!t) {
60 printf("0");
61 return;
62 }
63
64 struct tm *p = localtime(&t);
65
66 if (p)
67 printf("%02d/%02d/%02d-%02d:%02d:%02d",
68 p->tm_year + 1900, p->tm_mon + 1, p->tm_mday,
69 p->tm_hour, p->tm_min, p->tm_sec);
70 else
71 printf("%llu", (unsigned long long) t);
72}
73
74typedef off_t libc_off_t;
75
76# ifdef USE_ASM_STAT
77# define stat libc_stat
78# define stat64 libc_stat64
79# endif
80# include <fcntl.h>
81# include <sys/stat.h>
82# ifdef USE_ASM_STAT
83# undef stat
84# undef stat64
85# endif
86
87# ifdef USE_ASM_STAT
88# undef st_atime
89# undef st_mtime
90# undef st_ctime
91# undef dev_t
92# undef gid_t
93# undef ino_t
94# undef loff_t
95# undef mode_t
96# undef nlink_t
97# undef off64_t
98# undef off_t
99# undef time_t
100# undef uid_t
101# define dev_t __kernel_dev_t
102# define gid_t __kernel_gid_t
103# define ino_t __kernel_ino_t
104# define loff_t __kernel_loff_t
105# define mode_t __kernel_mode_t
106# define nlink_t __kernel_nlink_t
107# define off64_t __kernel_off64_t
108# define off_t __kernel_off_t
109# define time_t __kernel_time_t
110# define uid_t __kernel_uid_t
111# include "asm_stat.h"
112# else
113# undef HAVE_STRUCT_STAT_ST_ATIME_NSEC
114# ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
115# define HAVE_STRUCT_STAT_ST_ATIME_NSEC 1
116# undef st_atime_nsec
117# define st_atime_nsec st_atim.tv_nsec
118# endif
119# undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
120# ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
121# define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
122# undef st_mtime_nsec
123# define st_mtime_nsec st_mtim.tv_nsec
124# endif
125# undef HAVE_STRUCT_STAT_ST_CTIME_NSEC
126# ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
127# define HAVE_STRUCT_STAT_ST_CTIME_NSEC 1
128# undef st_ctime_nsec
129# define st_ctime_nsec st_ctim.tv_nsec
130# endif
131# endif
132
133# ifndef STRUCT_STAT
134# define STRUCT_STAT struct stat
Dmitry V. Levin7bbf8b52016-01-12 00:03:41 +0000135# define STRUCT_STAT_STR "struct stat"
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000136# endif
137# ifndef SAMPLE_SIZE
138# define SAMPLE_SIZE 43147718418
139# endif
140
141static void
142print_ftype(const unsigned int mode)
143{
144 if (S_ISREG(mode))
145 printf("S_IFREG");
146 else if (S_ISDIR(mode))
147 printf("S_IFDIR");
148 else if (S_ISCHR(mode))
149 printf("S_IFCHR");
150 else if (S_ISBLK(mode))
151 printf("S_IFBLK");
152 else
153 printf("%#o", mode & S_IFMT);
154}
155
156static void
157print_perms(const unsigned int mode)
158{
159 printf("%#o", mode & ~S_IFMT);
160}
161
162static void
163print_stat(const STRUCT_STAT *st)
164{
165 printf("{st_dev=makedev(%u, %u)",
166 (unsigned int) major(st->st_dev),
167 (unsigned int) minor(st->st_dev));
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000168 printf(", st_ino=%llu", (unsigned long long) st->st_ino);
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000169 printf(", st_mode=");
170 print_ftype(st->st_mode);
171 printf("|");
172 print_perms(st->st_mode);
173 printf(", st_nlink=%u", (unsigned int) st->st_nlink);
174 printf(", st_uid=%u", (unsigned int) st->st_uid);
175 printf(", st_gid=%u", (unsigned int) st->st_gid);
176 printf(", st_blksize=%u", (unsigned int) st->st_blksize);
177 printf(", st_blocks=%u", (unsigned int) st->st_blocks);
178
179 switch (st->st_mode & S_IFMT) {
180 case S_IFCHR: case S_IFBLK:
181 printf(", st_rdev=makedev(%u, %u)",
182 (unsigned int) major(st->st_rdev),
183 (unsigned int) minor(st->st_rdev));
184 break;
185 default:
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000186 printf(", st_size=%llu", (unsigned long long) st->st_size);
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000187 }
188
189 printf(", st_atime=");
190 print_time(st->st_atime);
191# ifdef HAVE_STRUCT_STAT_ST_ATIME_NSEC
192 if (st->st_atime_nsec)
193 printf(".%09lu", (unsigned long) st->st_atime_nsec);
194# endif
195 printf(", st_mtime=");
196 print_time(st->st_mtime);
197# ifdef HAVE_STRUCT_STAT_ST_MTIME_NSEC
198 if (st->st_mtime_nsec)
199 printf(".%09lu", (unsigned long) st->st_mtime_nsec);
200# endif
201 printf(", st_ctime=");
202 print_time(st->st_ctime);
203# ifdef HAVE_STRUCT_STAT_ST_CTIME_NSEC
204 if (st->st_ctime_nsec)
205 printf(".%09lu", (unsigned long) st->st_ctime_nsec);
206# endif
207 printf("}");
208}
209
210static int
211create_sample(const char *fname, const libc_off_t size)
212{
213 static const struct timespec ts[] = {
James Cowgill3fb84bf2016-08-11 16:33:01 +0000214#ifdef __mips64
215 // On mips64, struct stat cannot handle negative timestamps
216 {10841, 246}, {10843, 135}
217#else
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000218 {-10843, 135}, {-10841, 246}
James Cowgill3fb84bf2016-08-11 16:33:01 +0000219#endif
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000220 };
221
222 (void) close(0);
223 if (open(fname, O_RDWR | O_CREAT | O_TRUNC, 0640)) {
224 perror(fname);
225 return 77;
226 }
227 if (ftruncate(0, size)) {
228 perror("ftruncate");
229 return 77;
230 }
231 if (futimens(0, ts)) {
232 perror("futimens");
233 return 77;
234 }
235 return 0;
236}
237
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000238int
239main(void)
240{
241 static const char sample[] = TEST_SYSCALL_STR ".sample";
242 STRUCT_STAT st[2];
243
244 int rc = create_sample(sample, SAMPLE_SIZE);
245 if (rc) {
246 (void) unlink(sample);
247 return rc;
248 }
249
250 if (TEST_SYSCALL_INVOKE(sample, st)) {
251 perror(TEST_SYSCALL_STR);
252 (void) unlink(sample);
253 return 77;
254 }
255 (void) unlink(sample);
256 if ((unsigned long long) SAMPLE_SIZE !=
257 (unsigned long long) st[0].st_size) {
258 fprintf(stderr, "Size mismatch: "
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000259 "requested size(%llu) != st_size(%llu)\n",
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000260 (unsigned long long) SAMPLE_SIZE,
261 (unsigned long long) st[0].st_size);
262 fprintf(stderr, "The most likely reason for this is incorrect"
263 " definition of %s.\n"
264 "Here is some diagnostics that might help:\n",
265 STRUCT_STAT_STR);
266 fprintf(stderr, "offsetof(%s, st_dev) = %zu"
267 ", sizeof(st_dev) = %zu\n",
268 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_dev),
269 sizeof(st[0].st_dev));
270 fprintf(stderr, "offsetof(%s, st_ino) = %zu"
271 ", sizeof(st_ino) = %zu\n",
272 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_ino),
273 sizeof(st[0].st_ino));
274 fprintf(stderr, "offsetof(%s, st_mode) = %zu"
275 ", sizeof(st_mode) = %zu\n",
276 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_mode),
277 sizeof(st[0].st_mode));
278 fprintf(stderr, "offsetof(%s, st_nlink) = %zu"
279 ", sizeof(st_nlink) = %zu\n",
280 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_nlink),
281 sizeof(st[0].st_nlink));
282 fprintf(stderr, "offsetof(%s, st_uid) = %zu"
283 ", sizeof(st_uid) = %zu\n",
284 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_uid),
285 sizeof(st[0].st_uid));
286 fprintf(stderr, "offsetof(%s, st_gid) = %zu"
287 ", sizeof(st_gid) = %zu\n",
288 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_gid),
289 sizeof(st[0].st_gid));
290 fprintf(stderr, "offsetof(%s, st_rdev) = %zu"
291 ", sizeof(st_rdev) = %zu\n",
292 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_rdev),
293 sizeof(st[0].st_rdev));
294 fprintf(stderr, "offsetof(%s, st_size) = %zu"
295 ", sizeof(st_size) = %zu\n",
296 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_size),
297 sizeof(st[0].st_size));
298 fprintf(stderr, "offsetof(%s, st_blksize) = %zu"
299 ", sizeof(st_blksize) = %zu\n",
300 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_blksize),
301 sizeof(st[0].st_blksize));
302 fprintf(stderr, "offsetof(%s, st_blocks) = %zu"
303 ", sizeof(st_blocks) = %zu\n",
304 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_blocks),
305 sizeof(st[0].st_blocks));
306 return 77;
307 }
308
309 PRINT_SYSCALL_HEADER(sample);
310 print_stat(st);
311 PRINT_SYSCALL_FOOTER;
312
313 puts("+++ exited with 0 +++");
314 return 0;
315}
316
317#else
318
Dmitry V. Levin6c52f2b2016-01-05 22:37:42 +0000319SKIP_MAIN_UNDEFINED("HAVE_FTRUNCATE && HAVE_FUTIMENS")
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000320
321#endif