1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. The name of the author may not be used to endorse or promote products
17  *    derived from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
20  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
22  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include "defs.h"
32 
33 #undef dev_t
34 #undef ino_t
35 #undef mode_t
36 #undef nlink_t
37 #undef uid_t
38 #undef gid_t
39 #undef off_t
40 #undef loff_t
41 #define dev_t __kernel_dev_t
42 #define ino_t __kernel_ino_t
43 #define mode_t __kernel_mode_t
44 #define nlink_t __kernel_nlink_t
45 #define uid_t __kernel_uid_t
46 #define gid_t __kernel_gid_t
47 #define off_t __kernel_off_t
48 #define loff_t __kernel_loff_t
49 
50 #include "asm_stat.h"
51 
52 #undef dev_t
53 #undef ino_t
54 #undef mode_t
55 #undef nlink_t
56 #undef uid_t
57 #undef gid_t
58 #undef off_t
59 #undef loff_t
60 #define dev_t dev_t
61 #define ino_t ino_t
62 #define mode_t mode_t
63 #define nlink_t nlink_t
64 #define uid_t uid_t
65 #define gid_t gid_t
66 #define off_t off_t
67 #define loff_t loff_t
68 
69 /* for S_IFMT */
70 #define stat libc_stat
71 #define stat64 libc_stat64
72 #include <sys/stat.h>
73 #undef stat
74 #undef stat64
75 /* These might be macros. */
76 #undef st_atime
77 #undef st_mtime
78 #undef st_ctime
79 
80 #if defined MAJOR_IN_SYSMACROS
81 # include <sys/sysmacros.h>
82 #elif defined MAJOR_IN_MKDEV
83 # include <sys/mkdev.h>
84 #endif
85 
86 /* several stats */
87 
88 #include "printstat.h"
89 
90 /* all locally defined structures provide these fields */
91 #undef HAVE_STRUCT_STAT_ST_ATIME_NSEC
92 #define HAVE_STRUCT_STAT_ST_ATIME_NSEC 1
93 #undef HAVE_STRUCT_STAT_ST_CTIME_NSEC
94 #define HAVE_STRUCT_STAT_ST_CTIME_NSEC 1
95 #undef HAVE_STRUCT_STAT_ST_MTIME_NSEC
96 #define HAVE_STRUCT_STAT_ST_MTIME_NSEC 1
97 
98 #undef STAT32_PERSONALITY
99 #if SUPPORTED_PERSONALITIES > 1
100 # if defined AARCH64 || defined X86_64 || defined X32
101 struct stat32 {
102 	unsigned int	st_dev;
103 	unsigned int	st_ino;
104 	unsigned short	st_mode;
105 	unsigned short	st_nlink;
106 	unsigned short	st_uid;
107 	unsigned short	st_gid;
108 	unsigned int	st_rdev;
109 	unsigned int	st_size;
110 	unsigned int	st_blksize;
111 	unsigned int	st_blocks;
112 	unsigned int	st_atime;
113 	unsigned int	st_atime_nsec;
114 	unsigned int	st_mtime;
115 	unsigned int	st_mtime_nsec;
116 	unsigned int	st_ctime;
117 	unsigned int	st_ctime_nsec;
118 	unsigned int	__unused4;
119 	unsigned int	__unused5;
120 };
121 #  define STAT32_PERSONALITY 1
122 # elif defined POWERPC64
123 struct stat32 {
124 	unsigned int	st_dev;
125 	unsigned int	st_ino;
126 	unsigned int	st_mode;
127 	unsigned short	st_nlink;
128 	unsigned int	st_uid;
129 	unsigned int	st_gid;
130 	unsigned int	st_rdev;
131 	unsigned int	st_size;
132 	unsigned int	st_blksize;
133 	unsigned int	st_blocks;
134 	unsigned int	st_atime;
135 	unsigned int	st_atime_nsec;
136 	unsigned int	st_mtime;
137 	unsigned int	st_mtime_nsec;
138 	unsigned int	st_ctime;
139 	unsigned int	st_ctime_nsec;
140 	unsigned int	__unused4;
141 	unsigned int	__unused5;
142 };
143 #  define STAT32_PERSONALITY 1
144 # elif defined SPARC64
145 struct stat32 {
146 	unsigned short	st_dev;
147 	unsigned int	st_ino;
148 	unsigned short	st_mode;
149 	unsigned short	st_nlink;
150 	unsigned short	st_uid;
151 	unsigned short	st_gid;
152 	unsigned short	st_rdev;
153 	unsigned int	st_size;
154 	unsigned int	st_atime;
155 	unsigned int	st_atime_nsec;
156 	unsigned int	st_mtime;
157 	unsigned int	st_mtime_nsec;
158 	unsigned int	st_ctime;
159 	unsigned int	st_ctime_nsec;
160 	unsigned int	st_blksize;
161 	unsigned int	st_blocks;
162 	unsigned int	__unused4[2];
163 };
164 #  define STAT32_PERSONALITY 0
165 # elif defined SPARC
166 #  /* no 64-bit personalities */
167 # elif defined TILE
168 #  /* no 32-bit stat */
169 # else
170 #  warning FIXME: check whether struct stat32 definition is needed for this architecture!
171 # endif /* X86_64 || X32 || POWERPC64 */
172 #endif /* SUPPORTED_PERSONALITIES > 1 */
173 
174 #ifdef STAT32_PERSONALITY
175 # define DO_PRINTSTAT do_printstat32
176 # define STRUCT_STAT struct stat32
177 # undef HAVE_STRUCT_STAT_ST_FLAGS
178 # undef HAVE_STRUCT_STAT_ST_FSTYPE
179 # undef HAVE_STRUCT_STAT_ST_GEN
180 # include "printstat.h"
181 #endif /* STAT32_PERSONALITY */
182 
183 #if defined(SPARC) || defined(SPARC64)
184 
185 struct solstat {
186 	unsigned	st_dev;
187 	unsigned int	st_pad1[3];     /* network id */
188 	unsigned	st_ino;
189 	unsigned	st_mode;
190 	unsigned	st_nlink;
191 	unsigned	st_uid;
192 	unsigned	st_gid;
193 	unsigned	st_rdev;
194 	unsigned int	st_pad2[2];
195 	unsigned int	st_size;
196 	unsigned int	st_pad3;        /* st_size, off_t expansion */
197 	unsigned int	st_atime;
198 	unsigned int	st_atime_nsec;
199 	unsigned int	st_mtime;
200 	unsigned int	st_mtime_nsec;
201 	unsigned int	st_ctime;
202 	unsigned int	st_ctime_nsec;
203 	unsigned int	st_blksize;
204 	unsigned int	st_blocks;
205 	char		st_fstype[16];
206 	unsigned int	st_pad4[8];     /* expansion area */
207 };
208 
209 # define DO_PRINTSTAT	do_printstat_sol
210 # define STRUCT_STAT	struct solstat
211 # define STAT_MAJOR(x)	(((x) >> 18) & 0x3fff)
212 # define STAT_MINOR(x)	((x) & 0x3ffff)
213 # undef HAVE_STRUCT_STAT_ST_FLAGS
214 # undef HAVE_STRUCT_STAT_ST_FSTYPE
215 # undef HAVE_STRUCT_STAT_ST_GEN
216 # include "printstat.h"
217 #endif /* SPARC || SPARC64 */
218 
219 static void
printstat(struct tcb * tcp,long addr)220 printstat(struct tcb *tcp, long addr)
221 {
222 	struct stat statbuf;
223 
224 #ifdef STAT32_PERSONALITY
225 	if (current_personality == STAT32_PERSONALITY) {
226 		struct stat32 statbuf;
227 
228 		if (!umove_or_printaddr(tcp, addr, &statbuf))
229 			do_printstat32(tcp, &statbuf);
230 		return;
231 	}
232 #endif
233 
234 #if defined(SPARC) || defined(SPARC64)
235 	if (current_personality == 1) {
236 		struct solstat statbuf;
237 
238 		if (!umove_or_printaddr(tcp, addr, &statbuf))
239 			do_printstat_sol(tcp, &statbuf);
240 		return;
241 	}
242 #endif /* SPARC || SPARC64 */
243 
244 	if (!umove_or_printaddr(tcp, addr, &statbuf))
245 		do_printstat(tcp, &statbuf);
246 }
247 
SYS_FUNC(stat)248 SYS_FUNC(stat)
249 {
250 	if (entering(tcp)) {
251 		printpath(tcp, tcp->u_arg[0]);
252 		tprints(", ");
253 	} else {
254 		printstat(tcp, tcp->u_arg[1]);
255 	}
256 	return 0;
257 }
258 
SYS_FUNC(fstat)259 SYS_FUNC(fstat)
260 {
261 	if (entering(tcp)) {
262 		printfd(tcp, tcp->u_arg[0]);
263 		tprints(", ");
264 	} else {
265 		printstat(tcp, tcp->u_arg[1]);
266 	}
267 	return 0;
268 }
269 
270 #if defined STAT32_PERSONALITY && !defined HAVE_STRUCT_STAT64
271 # if defined AARCH64 || defined X86_64 || defined X32
272 /*
273  * Linux x86_64 and x32 have unified `struct stat' but their i386 personality
274  * needs `struct stat64'.
275  * linux/arch/x86/include/uapi/asm/stat.h defines `struct stat64' only for i386.
276  *
277  * Similarly, aarch64 has a unified `struct stat' but its arm personality
278  * needs `struct stat64' (unlike x86, it shouldn't be packed).
279  */
280 struct stat64 {
281 	unsigned long long	st_dev;
282 	unsigned char	__pad0[4];
283 	unsigned int	__st_ino;
284 	unsigned int	st_mode;
285 	unsigned int	st_nlink;
286 	unsigned int	st_uid;
287 	unsigned int	st_gid;
288 	unsigned long long	st_rdev;
289 	unsigned char	__pad3[4];
290 	long long	st_size;
291 	unsigned int	st_blksize;
292 	unsigned long long	st_blocks;
293 	unsigned int	st_atime;
294 	unsigned int	st_atime_nsec;
295 	unsigned int	st_mtime;
296 	unsigned int	st_mtime_nsec;
297 	unsigned int	st_ctime;
298 	unsigned int	st_ctime_nsec;
299 	unsigned long long	st_ino;
300 }
301 #  if defined X86_64 || defined X32
302   ATTRIBUTE_PACKED
303 #   define STAT64_SIZE	96
304 #  else
305 #   define STAT64_SIZE	104
306 #  endif
307 ;
308 #  define HAVE_STRUCT_STAT64	1
309 # else /* !(AARCH64 || X86_64 || X32) */
310 #  warning FIXME: check whether struct stat64 definition is needed for this architecture!
311 # endif
312 #endif /* STAT32_PERSONALITY && !HAVE_STRUCT_STAT64 */
313 
314 #ifdef HAVE_STRUCT_STAT64
315 
316 # define DO_PRINTSTAT do_printstat64
317 # define STRUCT_STAT struct stat64
318 # undef HAVE_STRUCT_STAT_ST_FLAGS
319 # undef HAVE_STRUCT_STAT_ST_FSTYPE
320 # undef HAVE_STRUCT_STAT_ST_GEN
321 # include "printstat.h"
322 
323 static void
printstat64(struct tcb * tcp,long addr)324 printstat64(struct tcb *tcp, long addr)
325 {
326 	struct stat64 statbuf;
327 
328 # ifdef STAT64_SIZE
329 	(void) sizeof(char[sizeof statbuf == STAT64_SIZE ? 1 : -1]);
330 # endif
331 
332 # ifdef STAT32_PERSONALITY
333 	if (current_personality != STAT32_PERSONALITY) {
334 		printstat(tcp, addr);
335 		return;
336 	}
337 # endif /* STAT32_PERSONALITY */
338 
339 	if (!umove_or_printaddr(tcp, addr, &statbuf))
340 		do_printstat64(tcp, &statbuf);
341 }
342 
SYS_FUNC(stat64)343 SYS_FUNC(stat64)
344 {
345 	if (entering(tcp)) {
346 		printpath(tcp, tcp->u_arg[0]);
347 		tprints(", ");
348 	} else {
349 		printstat64(tcp, tcp->u_arg[1]);
350 	}
351 	return 0;
352 }
353 
SYS_FUNC(fstat64)354 SYS_FUNC(fstat64)
355 {
356 	if (entering(tcp)) {
357 		printfd(tcp, tcp->u_arg[0]);
358 		tprints(", ");
359 	} else {
360 		printstat64(tcp, tcp->u_arg[1]);
361 	}
362 	return 0;
363 }
364 
365 #else
366 
SYS_FUNC(stat64)367 SYS_FUNC(stat64)
368 {
369 	return sys_stat(tcp);
370 }
371 
SYS_FUNC(fstat64)372 SYS_FUNC(fstat64)
373 {
374 	return sys_fstat(tcp);
375 }
376 
377 #endif /* HAVE_STRUCT_STAT64 */
378 
SYS_FUNC(newfstatat)379 SYS_FUNC(newfstatat)
380 {
381 	if (entering(tcp)) {
382 		print_dirfd(tcp, tcp->u_arg[0]);
383 		printpath(tcp, tcp->u_arg[1]);
384 		tprints(", ");
385 	} else {
386 #if defined STAT32_PERSONALITY
387 		if (current_personality == STAT32_PERSONALITY)
388 			printstat64(tcp, tcp->u_arg[2]);
389 		else
390 			printstat(tcp, tcp->u_arg[2]);
391 #elif defined HAVE_STRUCT_STAT64
392 		printstat64(tcp, tcp->u_arg[2]);
393 #else
394 		printstat(tcp, tcp->u_arg[2]);
395 #endif /* STAT32_PERSONALITY || HAVE_STRUCT_STAT64 */
396 		tprints(", ");
397 		printflags(at_flags, tcp->u_arg[3], "AT_???");
398 	}
399 	return 0;
400 }
401 
402 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
403 
404 static void
convertoldstat(const struct __old_kernel_stat * oldbuf,struct stat * newbuf)405 convertoldstat(const struct __old_kernel_stat *oldbuf, struct stat *newbuf)
406 {
407 	memset(newbuf, 0, sizeof(*newbuf));
408 	newbuf->st_dev = oldbuf->st_dev;
409 	newbuf->st_ino = oldbuf->st_ino;
410 	newbuf->st_mode = oldbuf->st_mode;
411 	newbuf->st_nlink = oldbuf->st_nlink;
412 	newbuf->st_uid = oldbuf->st_uid;
413 	newbuf->st_gid = oldbuf->st_gid;
414 	newbuf->st_rdev = oldbuf->st_rdev;
415 	newbuf->st_size = oldbuf->st_size;
416 	newbuf->st_atime = oldbuf->st_atime;
417 	newbuf->st_mtime = oldbuf->st_mtime;
418 	newbuf->st_ctime = oldbuf->st_ctime;
419 }
420 
421 static void
printoldstat(struct tcb * tcp,long addr)422 printoldstat(struct tcb *tcp, long addr)
423 {
424 	struct __old_kernel_stat statbuf;
425 	struct stat newstatbuf;
426 
427 # if defined(SPARC) || defined(SPARC64)
428 	if (current_personality == 1) {
429 		struct solstat statbuf;
430 
431 		if (!umove_or_printaddr(tcp, addr, &statbuf))
432 			do_printstat_sol(tcp, &statbuf);
433 		return;
434 	}
435 # endif
436 
437 	if (!umove_or_printaddr(tcp, addr, &statbuf)) {
438 		convertoldstat(&statbuf, &newstatbuf);
439 		do_printstat(tcp, &newstatbuf);
440 	}
441 }
442 
SYS_FUNC(oldstat)443 SYS_FUNC(oldstat)
444 {
445 	if (entering(tcp)) {
446 		printpath(tcp, tcp->u_arg[0]);
447 		tprints(", ");
448 	} else {
449 		printoldstat(tcp, tcp->u_arg[1]);
450 	}
451 	return 0;
452 }
453 
SYS_FUNC(oldfstat)454 SYS_FUNC(oldfstat)
455 {
456 	if (entering(tcp)) {
457 		printfd(tcp, tcp->u_arg[0]);
458 		tprints(", ");
459 	} else {
460 		printoldstat(tcp, tcp->u_arg[1]);
461 	}
462 	return 0;
463 }
464 
465 #endif /* HAVE_STRUCT___OLD_KERNEL_STAT */
466 
467 #if defined(SPARC) || defined(SPARC64)
468 
SYS_FUNC(xstat)469 SYS_FUNC(xstat)
470 {
471 	if (entering(tcp)) {
472 		tprintf("%ld, ", tcp->u_arg[0]);
473 		printpath(tcp, tcp->u_arg[1]);
474 		tprints(", ");
475 	} else {
476 		printstat(tcp, tcp->u_arg[2]);
477 	}
478 	return 0;
479 }
480 
SYS_FUNC(fxstat)481 SYS_FUNC(fxstat)
482 {
483 	if (entering(tcp)) {
484 		tprintf("%ld, ", tcp->u_arg[0]);
485 		printfd(tcp, tcp->u_arg[1]);
486 		tprints(", ");
487 	} else {
488 		printstat(tcp, tcp->u_arg[2]);
489 	}
490 	return 0;
491 }
492 
493 #endif /* SPARC || SPARC64 */
494