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 #undef STAT32_PERSONALITY
91 #if SUPPORTED_PERSONALITIES > 1
92 # if defined AARCH64 || defined X86_64 || defined X32
93 struct stat32 {
94 	unsigned int	st_dev;
95 	unsigned int	st_ino;
96 	unsigned short	st_mode;
97 	unsigned short	st_nlink;
98 	unsigned short	st_uid;
99 	unsigned short	st_gid;
100 	unsigned int	st_rdev;
101 	unsigned int	st_size;
102 	unsigned int	st_blksize;
103 	unsigned int	st_blocks;
104 	unsigned int	st_atime;
105 	unsigned int	st_atime_nsec;
106 	unsigned int	st_mtime;
107 	unsigned int	st_mtime_nsec;
108 	unsigned int	st_ctime;
109 	unsigned int	st_ctime_nsec;
110 	unsigned int	__unused4;
111 	unsigned int	__unused5;
112 };
113 #  ifdef AARCH64
114 #   define STAT32_PERSONALITY 0
115 #  else
116 #   define STAT32_PERSONALITY 1
117 #  endif
118 # elif defined POWERPC64
119 struct stat32 {
120 	unsigned int	st_dev;
121 	unsigned int	st_ino;
122 	unsigned int	st_mode;
123 	unsigned short	st_nlink;
124 	unsigned int	st_uid;
125 	unsigned int	st_gid;
126 	unsigned int	st_rdev;
127 	unsigned int	st_size;
128 	unsigned int	st_blksize;
129 	unsigned int	st_blocks;
130 	unsigned int	st_atime;
131 	unsigned int	st_atime_nsec;
132 	unsigned int	st_mtime;
133 	unsigned int	st_mtime_nsec;
134 	unsigned int	st_ctime;
135 	unsigned int	st_ctime_nsec;
136 	unsigned int	__unused4;
137 	unsigned int	__unused5;
138 };
139 #  define STAT32_PERSONALITY 1
140 # elif defined SPARC64
141 struct stat32 {
142 	unsigned short	st_dev;
143 	unsigned int	st_ino;
144 	unsigned short	st_mode;
145 	unsigned short	st_nlink;
146 	unsigned short	st_uid;
147 	unsigned short	st_gid;
148 	unsigned short	st_rdev;
149 	unsigned int	st_size;
150 	unsigned int	st_atime;
151 	unsigned int	st_atime_nsec;
152 	unsigned int	st_mtime;
153 	unsigned int	st_mtime_nsec;
154 	unsigned int	st_ctime;
155 	unsigned int	st_ctime_nsec;
156 	unsigned int	st_blksize;
157 	unsigned int	st_blocks;
158 	unsigned int	__unused4[2];
159 };
160 #  define STAT32_PERSONALITY 0
161 # elif defined SPARC
162 #  /* no 64-bit personalities */
163 # elif defined TILE
164 #  /* no 32-bit stat */
165 # else
166 #  warning FIXME: check whether struct stat32 definition is needed for this architecture!
167 # endif /* X86_64 || X32 || POWERPC64 */
168 #endif /* SUPPORTED_PERSONALITIES > 1 */
169 
170 #ifdef STAT32_PERSONALITY
171 # define DO_PRINTSTAT do_printstat32
172 # define STRUCT_STAT struct stat32
173 # undef HAVE_STRUCT_STAT_ST_FLAGS
174 # undef HAVE_STRUCT_STAT_ST_FSTYPE
175 # undef HAVE_STRUCT_STAT_ST_GEN
176 # include "printstat.h"
177 
178 static void
printstat32(struct tcb * tcp,long addr)179 printstat32(struct tcb *tcp, long addr)
180 {
181 	struct stat32 statbuf;
182 
183 	if (umove(tcp, addr, &statbuf) < 0) {
184 		tprints("{...}");
185 		return;
186 	}
187 
188 	do_printstat32(tcp, &statbuf);
189 }
190 #endif /* STAT32_PERSONALITY */
191 
192 #if defined(SPARC) || defined(SPARC64)
193 
194 struct solstat {
195 	unsigned	st_dev;
196 	unsigned int	st_pad1[3];     /* network id */
197 	unsigned	st_ino;
198 	unsigned	st_mode;
199 	unsigned	st_nlink;
200 	unsigned	st_uid;
201 	unsigned	st_gid;
202 	unsigned	st_rdev;
203 	unsigned int	st_pad2[2];
204 	unsigned int	st_size;
205 	unsigned int	st_pad3;        /* st_size, off_t expansion */
206 	unsigned int	st_atime;
207 	unsigned int	st_atime_nsec;
208 	unsigned int	st_mtime;
209 	unsigned int	st_mtime_nsec;
210 	unsigned int	st_ctime;
211 	unsigned int	st_ctime_nsec;
212 	unsigned int	st_blksize;
213 	unsigned int	st_blocks;
214 	char		st_fstype[16];
215 	unsigned int	st_pad4[8];     /* expansion area */
216 };
217 
218 # define DO_PRINTSTAT	do_printstat_sol
219 # define STRUCT_STAT	struct solstat
220 # define STAT_MAJOR(x)	(((x) >> 18) & 0x3fff)
221 # define STAT_MINOR(x)	((x) & 0x3ffff)
222 # undef HAVE_STRUCT_STAT_ST_FLAGS
223 # undef HAVE_STRUCT_STAT_ST_FSTYPE
224 # undef HAVE_STRUCT_STAT_ST_GEN
225 # include "printstat.h"
226 
227 static void
printstatsol(struct tcb * tcp,long addr)228 printstatsol(struct tcb *tcp, long addr)
229 {
230 	struct solstat statbuf;
231 
232 	if (umove(tcp, addr, &statbuf) < 0) {
233 		tprints("{...}");
234 		return;
235 	}
236 
237 	do_printstat_sol(tcp, &statbuf);
238 }
239 
240 #endif /* SPARC || SPARC64 */
241 
242 static void
printstat(struct tcb * tcp,long addr)243 printstat(struct tcb *tcp, long addr)
244 {
245 	struct stat statbuf;
246 
247 	if (!addr) {
248 		tprints("NULL");
249 		return;
250 	}
251 	if (syserror(tcp) || !verbose(tcp)) {
252 		tprintf("%#lx", addr);
253 		return;
254 	}
255 
256 #ifdef STAT32_PERSONALITY
257 	if (current_personality == STAT32_PERSONALITY) {
258 		printstat32(tcp, addr);
259 		return;
260 	}
261 #endif
262 
263 #if defined(SPARC) || defined(SPARC64)
264 	if (current_personality == 1) {
265 		printstatsol(tcp, addr);
266 		return;
267 	}
268 #endif /* SPARC || SPARC64 */
269 
270 	if (umove(tcp, addr, &statbuf) < 0) {
271 		tprints("{...}");
272 		return;
273 	}
274 
275 	do_printstat(tcp, &statbuf);
276 }
277 
SYS_FUNC(stat)278 SYS_FUNC(stat)
279 {
280 	if (entering(tcp)) {
281 		printpath(tcp, tcp->u_arg[0]);
282 		tprints(", ");
283 	} else {
284 		printstat(tcp, tcp->u_arg[1]);
285 	}
286 	return 0;
287 }
288 
SYS_FUNC(fstat)289 SYS_FUNC(fstat)
290 {
291 	if (entering(tcp)) {
292 		printfd(tcp, tcp->u_arg[0]);
293 		tprints(", ");
294 	} else {
295 		printstat(tcp, tcp->u_arg[1]);
296 	}
297 	return 0;
298 }
299 
300 #if defined STAT32_PERSONALITY && !defined HAVE_STRUCT_STAT64
301 # if defined AARCH64 || defined X86_64 || defined X32
302 /*
303  * Linux x86_64 and x32 have unified `struct stat' but their i386 personality
304  * needs `struct stat64'.
305  * linux/arch/x86/include/uapi/asm/stat.h defines `struct stat64' only for i386.
306  *
307  * Similarly, aarch64 has a unified `struct stat' but its arm personality
308  * needs `struct stat64' (unlike x86, it shouldn't be packed).
309  */
310 struct stat64 {
311 	unsigned long long	st_dev;
312 	unsigned char	__pad0[4];
313 	unsigned int	__st_ino;
314 	unsigned int	st_mode;
315 	unsigned int	st_nlink;
316 	unsigned int	st_uid;
317 	unsigned int	st_gid;
318 	unsigned long long	st_rdev;
319 	unsigned char	__pad3[4];
320 	long long	st_size;
321 	unsigned int	st_blksize;
322 	unsigned long long	st_blocks;
323 	unsigned int	st_atime;
324 	unsigned int	st_atime_nsec;
325 	unsigned int	st_mtime;
326 	unsigned int	st_mtime_nsec;
327 	unsigned int	st_ctime;
328 	unsigned int	st_ctime_nsec;
329 	unsigned long long	st_ino;
330 }
331 #  if defined X86_64 || defined X32
332   ATTRIBUTE_PACKED
333 #   define STAT64_SIZE	96
334 #  else
335 #   define STAT64_SIZE	104
336 #  endif
337 ;
338 #  define HAVE_STRUCT_STAT64	1
339 # else /* !(AARCH64 || X86_64 || X32) */
340 #  warning FIXME: check whether struct stat64 definition is needed for this architecture!
341 # endif
342 #endif /* STAT32_PERSONALITY && !HAVE_STRUCT_STAT64 */
343 
344 #ifdef HAVE_STRUCT_STAT64
345 
346 # define DO_PRINTSTAT do_printstat64
347 # define STRUCT_STAT struct stat64
348 # undef HAVE_STRUCT_STAT_ST_FLAGS
349 # undef HAVE_STRUCT_STAT_ST_FSTYPE
350 # undef HAVE_STRUCT_STAT_ST_GEN
351 # include "printstat.h"
352 
353 static void
printstat64(struct tcb * tcp,long addr)354 printstat64(struct tcb *tcp, long addr)
355 {
356 	struct stat64 statbuf;
357 
358 # ifdef STAT64_SIZE
359 	(void) sizeof(char[sizeof statbuf == STAT64_SIZE ? 1 : -1]);
360 # endif
361 
362 	if (!addr) {
363 		tprints("NULL");
364 		return;
365 	}
366 	if (syserror(tcp) || !verbose(tcp)) {
367 		tprintf("%#lx", addr);
368 		return;
369 	}
370 
371 # ifdef STAT32_PERSONALITY
372 	if (current_personality != STAT32_PERSONALITY) {
373 		printstat(tcp, addr);
374 		return;
375 	}
376 # endif /* STAT32_PERSONALITY */
377 
378 	if (umove(tcp, addr, &statbuf) < 0) {
379 		tprints("{...}");
380 		return;
381 	}
382 
383 	do_printstat64(tcp, &statbuf);
384 }
385 
SYS_FUNC(stat64)386 SYS_FUNC(stat64)
387 {
388 	if (entering(tcp)) {
389 		printpath(tcp, tcp->u_arg[0]);
390 		tprints(", ");
391 	} else {
392 		printstat64(tcp, tcp->u_arg[1]);
393 	}
394 	return 0;
395 }
396 
SYS_FUNC(fstat64)397 SYS_FUNC(fstat64)
398 {
399 	if (entering(tcp)) {
400 		printfd(tcp, tcp->u_arg[0]);
401 		tprints(", ");
402 	} else {
403 		printstat64(tcp, tcp->u_arg[1]);
404 	}
405 	return 0;
406 }
407 
408 #else
409 
SYS_FUNC(stat64)410 SYS_FUNC(stat64)
411 {
412 	return sys_stat(tcp);
413 }
414 
SYS_FUNC(fstat64)415 SYS_FUNC(fstat64)
416 {
417 	return sys_fstat(tcp);
418 }
419 
420 #endif /* HAVE_STRUCT_STAT64 */
421 
SYS_FUNC(newfstatat)422 SYS_FUNC(newfstatat)
423 {
424 	if (entering(tcp)) {
425 		print_dirfd(tcp, tcp->u_arg[0]);
426 		printpath(tcp, tcp->u_arg[1]);
427 		tprints(", ");
428 	} else {
429 #if defined STAT32_PERSONALITY
430 		if (current_personality == STAT32_PERSONALITY)
431 			printstat64(tcp, tcp->u_arg[2]);
432 		else
433 			printstat(tcp, tcp->u_arg[2]);
434 #elif defined HAVE_STRUCT_STAT64
435 		printstat64(tcp, tcp->u_arg[2]);
436 #else
437 		printstat(tcp, tcp->u_arg[2]);
438 #endif /* STAT32_PERSONALITY || HAVE_STRUCT_STAT64 */
439 		tprints(", ");
440 		printflags(at_flags, tcp->u_arg[3], "AT_???");
441 	}
442 	return 0;
443 }
444 
445 #if defined(HAVE_STRUCT___OLD_KERNEL_STAT)
446 
447 static void
convertoldstat(const struct __old_kernel_stat * oldbuf,struct stat * newbuf)448 convertoldstat(const struct __old_kernel_stat *oldbuf, struct stat *newbuf)
449 {
450 	memset(newbuf, 0, sizeof(*newbuf));
451 	newbuf->st_dev = oldbuf->st_dev;
452 	newbuf->st_ino = oldbuf->st_ino;
453 	newbuf->st_mode = oldbuf->st_mode;
454 	newbuf->st_nlink = oldbuf->st_nlink;
455 	newbuf->st_uid = oldbuf->st_uid;
456 	newbuf->st_gid = oldbuf->st_gid;
457 	newbuf->st_rdev = oldbuf->st_rdev;
458 	newbuf->st_size = oldbuf->st_size;
459 	newbuf->st_atime = oldbuf->st_atime;
460 	newbuf->st_mtime = oldbuf->st_mtime;
461 	newbuf->st_ctime = oldbuf->st_ctime;
462 }
463 
464 static void
printoldstat(struct tcb * tcp,long addr)465 printoldstat(struct tcb *tcp, long addr)
466 {
467 	struct __old_kernel_stat statbuf;
468 	struct stat newstatbuf;
469 
470 	if (!addr) {
471 		tprints("NULL");
472 		return;
473 	}
474 	if (syserror(tcp) || !verbose(tcp)) {
475 		tprintf("%#lx", addr);
476 		return;
477 	}
478 
479 # if defined(SPARC) || defined(SPARC64)
480 	if (current_personality == 1) {
481 		printstatsol(tcp, addr);
482 		return;
483 	}
484 # endif
485 
486 	if (umove(tcp, addr, &statbuf) < 0) {
487 		tprints("{...}");
488 		return;
489 	}
490 
491 	convertoldstat(&statbuf, &newstatbuf);
492 	do_printstat(tcp, &newstatbuf);
493 }
494 
SYS_FUNC(oldstat)495 SYS_FUNC(oldstat)
496 {
497 	if (entering(tcp)) {
498 		printpath(tcp, tcp->u_arg[0]);
499 		tprints(", ");
500 	} else {
501 		printoldstat(tcp, tcp->u_arg[1]);
502 	}
503 	return 0;
504 }
505 
SYS_FUNC(oldfstat)506 SYS_FUNC(oldfstat)
507 {
508 	if (entering(tcp)) {
509 		printfd(tcp, tcp->u_arg[0]);
510 		tprints(", ");
511 	} else {
512 		printoldstat(tcp, tcp->u_arg[1]);
513 	}
514 	return 0;
515 }
516 
517 #endif /* HAVE_STRUCT___OLD_KERNEL_STAT */
518 
519 #if defined(SPARC) || defined(SPARC64)
520 
SYS_FUNC(xstat)521 SYS_FUNC(xstat)
522 {
523 	if (entering(tcp)) {
524 		tprintf("%ld, ", tcp->u_arg[0]);
525 		printpath(tcp, tcp->u_arg[1]);
526 		tprints(", ");
527 	} else {
528 		printstat(tcp, tcp->u_arg[2]);
529 	}
530 	return 0;
531 }
532 
SYS_FUNC(fxstat)533 SYS_FUNC(fxstat)
534 {
535 	if (entering(tcp)) {
536 		tprintf("%ld, ", tcp->u_arg[0]);
537 		printfd(tcp, tcp->u_arg[1]);
538 		tprints(", ");
539 	} else {
540 		printstat(tcp, tcp->u_arg[2]);
541 	}
542 	return 0;
543 }
544 
545 #endif /* SPARC || SPARC64 */
546