blob: 7840190a6f404713a2eccb3711f24fc31990c498 [file] [log] [blame]
Dmitry V. Levincc2baf32015-12-05 00:01:56 +00001/*
2 * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
3 * 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
28#if defined TEST_SYSCALL_NAME \
29 && defined HAVE_FTRUNCATE && defined HAVE_FUTIMENS
30
31# ifndef TEST_SYSCALL_INVOKE
32# error TEST_SYSCALL_INVOKE must be defined
33# endif
34# ifndef PRINT_SYSCALL_HEADER
35# error PRINT_SYSCALL_HEADER must be defined
36# endif
37# ifndef PRINT_SYSCALL_FOOTER
38# error PRINT_SYSCALL_FOOTER must be defined
39# endif
40
41# include <errno.h>
42# include <stdio.h>
43# include <stddef.h>
44# include <time.h>
45# include <unistd.h>
46
47# if defined MAJOR_IN_SYSMACROS
48# include <sys/sysmacros.h>
49# elif defined MAJOR_IN_MKDEV
50# include <sys/mkdev.h>
51# else
52# include <sys/types.h>
53# endif
54
55static void
56print_time(const time_t t)
57{
58 if (!t) {
59 printf("0");
60 return;
61 }
62
63 struct tm *p = localtime(&t);
64
65 if (p)
66 printf("%02d/%02d/%02d-%02d:%02d:%02d",
67 p->tm_year + 1900, p->tm_mon + 1, p->tm_mday,
68 p->tm_hour, p->tm_min, p->tm_sec);
69 else
70 printf("%llu", (unsigned long long) t);
71}
72
73typedef off_t libc_off_t;
74
75# ifdef USE_ASM_STAT
76# define stat libc_stat
77# define stat64 libc_stat64
78# endif
79# include <fcntl.h>
80# include <sys/stat.h>
81# ifdef USE_ASM_STAT
82# undef stat
83# undef stat64
84# endif
85
86# ifdef USE_ASM_STAT
87# undef st_atime
88# undef st_mtime
89# undef st_ctime
90# undef dev_t
91# undef gid_t
92# undef ino_t
93# undef loff_t
94# undef mode_t
95# undef nlink_t
96# undef off64_t
97# undef off_t
98# undef time_t
99# undef uid_t
100# define dev_t __kernel_dev_t
101# define gid_t __kernel_gid_t
102# define ino_t __kernel_ino_t
103# define loff_t __kernel_loff_t
104# define mode_t __kernel_mode_t
105# define nlink_t __kernel_nlink_t
106# define off64_t __kernel_off64_t
107# define off_t __kernel_off_t
108# define time_t __kernel_time_t
109# define uid_t __kernel_uid_t
110# include "asm_stat.h"
111# else
112# undef HAVE_STRUCT_STAT_ST_ATIME_NSEC
113# ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
114# define HAVE_STRUCT_STAT_ST_ATIME_NSEC 1
115# undef st_atime_nsec
116# define st_atime_nsec st_atim.tv_nsec
117# endif
118# undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
119# ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC
120# define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
121# undef st_mtime_nsec
122# define st_mtime_nsec st_mtim.tv_nsec
123# endif
124# undef HAVE_STRUCT_STAT_ST_CTIME_NSEC
125# ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC
126# define HAVE_STRUCT_STAT_ST_CTIME_NSEC 1
127# undef st_ctime_nsec
128# define st_ctime_nsec st_ctim.tv_nsec
129# endif
130# endif
131
132# ifndef STRUCT_STAT
133# define STRUCT_STAT struct stat
134# endif
135# ifndef SAMPLE_SIZE
136# define SAMPLE_SIZE 43147718418
137# endif
138
139static void
140print_ftype(const unsigned int mode)
141{
142 if (S_ISREG(mode))
143 printf("S_IFREG");
144 else if (S_ISDIR(mode))
145 printf("S_IFDIR");
146 else if (S_ISCHR(mode))
147 printf("S_IFCHR");
148 else if (S_ISBLK(mode))
149 printf("S_IFBLK");
150 else
151 printf("%#o", mode & S_IFMT);
152}
153
154static void
155print_perms(const unsigned int mode)
156{
157 printf("%#o", mode & ~S_IFMT);
158}
159
160static void
161print_stat(const STRUCT_STAT *st)
162{
163 printf("{st_dev=makedev(%u, %u)",
164 (unsigned int) major(st->st_dev),
165 (unsigned int) minor(st->st_dev));
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000166 printf(", st_ino=%llu", (unsigned long long) st->st_ino);
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000167 printf(", st_mode=");
168 print_ftype(st->st_mode);
169 printf("|");
170 print_perms(st->st_mode);
171 printf(", st_nlink=%u", (unsigned int) st->st_nlink);
172 printf(", st_uid=%u", (unsigned int) st->st_uid);
173 printf(", st_gid=%u", (unsigned int) st->st_gid);
174 printf(", st_blksize=%u", (unsigned int) st->st_blksize);
175 printf(", st_blocks=%u", (unsigned int) st->st_blocks);
176
177 switch (st->st_mode & S_IFMT) {
178 case S_IFCHR: case S_IFBLK:
179 printf(", st_rdev=makedev(%u, %u)",
180 (unsigned int) major(st->st_rdev),
181 (unsigned int) minor(st->st_rdev));
182 break;
183 default:
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000184 printf(", st_size=%llu", (unsigned long long) st->st_size);
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000185 }
186
187 printf(", st_atime=");
188 print_time(st->st_atime);
189# ifdef HAVE_STRUCT_STAT_ST_ATIME_NSEC
190 if (st->st_atime_nsec)
191 printf(".%09lu", (unsigned long) st->st_atime_nsec);
192# endif
193 printf(", st_mtime=");
194 print_time(st->st_mtime);
195# ifdef HAVE_STRUCT_STAT_ST_MTIME_NSEC
196 if (st->st_mtime_nsec)
197 printf(".%09lu", (unsigned long) st->st_mtime_nsec);
198# endif
199 printf(", st_ctime=");
200 print_time(st->st_ctime);
201# ifdef HAVE_STRUCT_STAT_ST_CTIME_NSEC
202 if (st->st_ctime_nsec)
203 printf(".%09lu", (unsigned long) st->st_ctime_nsec);
204# endif
205 printf("}");
206}
207
208static int
209create_sample(const char *fname, const libc_off_t size)
210{
211 static const struct timespec ts[] = {
212 {-10843, 135}, {-10841, 246}
213 };
214
215 (void) close(0);
216 if (open(fname, O_RDWR | O_CREAT | O_TRUNC, 0640)) {
217 perror(fname);
218 return 77;
219 }
220 if (ftruncate(0, size)) {
221 perror("ftruncate");
222 return 77;
223 }
224 if (futimens(0, ts)) {
225 perror("futimens");
226 return 77;
227 }
228 return 0;
229}
230
231# define stringify_(arg) #arg
232# define stringify(arg) stringify_(arg)
233# define TEST_SYSCALL_STR stringify(TEST_SYSCALL_NAME)
234# define STRUCT_STAT_STR stringify(STRUCT_STAT)
235
236int
237main(void)
238{
239 static const char sample[] = TEST_SYSCALL_STR ".sample";
240 STRUCT_STAT st[2];
241
242 int rc = create_sample(sample, SAMPLE_SIZE);
243 if (rc) {
244 (void) unlink(sample);
245 return rc;
246 }
247
248 if (TEST_SYSCALL_INVOKE(sample, st)) {
249 perror(TEST_SYSCALL_STR);
250 (void) unlink(sample);
251 return 77;
252 }
253 (void) unlink(sample);
254 if ((unsigned long long) SAMPLE_SIZE !=
255 (unsigned long long) st[0].st_size) {
256 fprintf(stderr, "Size mismatch: "
Dmitry V. Levine67c8e42015-12-16 00:07:16 +0000257 "requested size(%llu) != st_size(%llu)\n",
Dmitry V. Levincc2baf32015-12-05 00:01:56 +0000258 (unsigned long long) SAMPLE_SIZE,
259 (unsigned long long) st[0].st_size);
260 fprintf(stderr, "The most likely reason for this is incorrect"
261 " definition of %s.\n"
262 "Here is some diagnostics that might help:\n",
263 STRUCT_STAT_STR);
264 fprintf(stderr, "offsetof(%s, st_dev) = %zu"
265 ", sizeof(st_dev) = %zu\n",
266 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_dev),
267 sizeof(st[0].st_dev));
268 fprintf(stderr, "offsetof(%s, st_ino) = %zu"
269 ", sizeof(st_ino) = %zu\n",
270 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_ino),
271 sizeof(st[0].st_ino));
272 fprintf(stderr, "offsetof(%s, st_mode) = %zu"
273 ", sizeof(st_mode) = %zu\n",
274 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_mode),
275 sizeof(st[0].st_mode));
276 fprintf(stderr, "offsetof(%s, st_nlink) = %zu"
277 ", sizeof(st_nlink) = %zu\n",
278 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_nlink),
279 sizeof(st[0].st_nlink));
280 fprintf(stderr, "offsetof(%s, st_uid) = %zu"
281 ", sizeof(st_uid) = %zu\n",
282 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_uid),
283 sizeof(st[0].st_uid));
284 fprintf(stderr, "offsetof(%s, st_gid) = %zu"
285 ", sizeof(st_gid) = %zu\n",
286 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_gid),
287 sizeof(st[0].st_gid));
288 fprintf(stderr, "offsetof(%s, st_rdev) = %zu"
289 ", sizeof(st_rdev) = %zu\n",
290 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_rdev),
291 sizeof(st[0].st_rdev));
292 fprintf(stderr, "offsetof(%s, st_size) = %zu"
293 ", sizeof(st_size) = %zu\n",
294 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_size),
295 sizeof(st[0].st_size));
296 fprintf(stderr, "offsetof(%s, st_blksize) = %zu"
297 ", sizeof(st_blksize) = %zu\n",
298 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_blksize),
299 sizeof(st[0].st_blksize));
300 fprintf(stderr, "offsetof(%s, st_blocks) = %zu"
301 ", sizeof(st_blocks) = %zu\n",
302 STRUCT_STAT_STR, offsetof(STRUCT_STAT, st_blocks),
303 sizeof(st[0].st_blocks));
304 return 77;
305 }
306
307 PRINT_SYSCALL_HEADER(sample);
308 print_stat(st);
309 PRINT_SYSCALL_FOOTER;
310
311 puts("+++ exited with 0 +++");
312 return 0;
313}
314
315#else
316
317int
318main(void)
319{
320 return 77;
321}
322
323#endif