Home | History | Annotate | Download | only in strace
      1 /*
      2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl>
      3  * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl>
      4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com>
      5  * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) 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
    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
    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
    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 
    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 
    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
    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 
    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 
    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 
    410 SYS_FUNC(stat64)
    411 {
    412 	return sys_stat(tcp);
    413 }
    414 
    415 SYS_FUNC(fstat64)
    416 {
    417 	return sys_fstat(tcp);
    418 }
    419 
    420 #endif /* HAVE_STRUCT_STAT64 */
    421 
    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
    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
    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 
    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 
    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 
    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 
    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