• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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