1 /*
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
55 static void
print_time(const time_t t)56 print_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
73 typedef 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
139 static void
print_ftype(const unsigned int mode)140 print_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
154 static void
print_perms(const unsigned int mode)155 print_perms(const unsigned int mode)
156 {
157 printf("%#o", mode & ~S_IFMT);
158 }
159
160 static void
print_stat(const STRUCT_STAT * st)161 print_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));
166 printf(", st_ino=%llu", (unsigned long long) st->st_ino);
167 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:
184 printf(", st_size=%llu", (unsigned long long) st->st_size);
185 }
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
208 static int
create_sample(const char * fname,const libc_off_t size)209 create_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
236 int
main(void)237 main(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: "
257 "requested size(%llu) != st_size(%llu)\n",
258 (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
317 int
main(void)318 main(void)
319 {
320 return 77;
321 }
322
323 #endif
324