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  *	$Id: desc.c,v 1.22 2005/06/01 19:22:07 roland Exp $
     31  */
     32 
     33 #include "defs.h"
     34 
     35 #include <fcntl.h>
     36 #include <sys/file.h>
     37 #ifdef LINUX
     38 #include <inttypes.h>
     39 #endif
     40 #ifdef HAVE_SYS_EPOLL_H
     41 #include <sys/epoll.h>
     42 #endif
     43 #ifdef HAVE_LIBAIO_H
     44 #include <libaio.h>
     45 #endif
     46 
     47 #if HAVE_LONG_LONG_OFF_T
     48 /*
     49  * Hacks for systems that have a long long off_t
     50  */
     51 #define flock64	flock		/* Horrid hack */
     52 #define printflock printflock64	/* Horrider hack */
     53 #endif
     54 
     55 
     56 static const struct xlat fcntlcmds[] = {
     57 	{ F_DUPFD,	"F_DUPFD"	},
     58 	{ F_GETFD,	"F_GETFD"	},
     59 	{ F_SETFD,	"F_SETFD"	},
     60 	{ F_GETFL,	"F_GETFL"	},
     61 	{ F_SETFL,	"F_SETFL"	},
     62 	{ F_GETLK,	"F_GETLK"	},
     63 	{ F_SETLK,	"F_SETLK"	},
     64 	{ F_SETLKW,	"F_SETLKW"	},
     65 	{ F_GETOWN,	"F_GETOWN"	},
     66 	{ F_SETOWN,	"F_SETOWN"	},
     67 #ifdef F_RSETLK
     68 	{ F_RSETLK,	"F_RSETLK"	},
     69 #endif
     70 #ifdef F_RSETLKW
     71 	{ F_RSETLKW,	"F_RSETLKW"	},
     72 #endif
     73 #ifdef F_RGETLK
     74 	{ F_RGETLK,	"F_RGETLK"	},
     75 #endif
     76 #ifdef F_CNVT
     77 	{ F_CNVT,	"F_CNVT"	},
     78 #endif
     79 #ifdef F_SETSIG
     80 	{ F_SETSIG,	"F_SETSIG"	},
     81 #endif
     82 #ifdef F_GETSIG
     83 	{ F_GETSIG,	"F_GETSIG"	},
     84 #endif
     85 #ifdef F_CHKFL
     86 	{ F_CHKFL,	"F_CHKFL"	},
     87 #endif
     88 #ifdef F_DUP2FD
     89 	{ F_DUP2FD,	"F_DUP2FD"	},
     90 #endif
     91 #ifdef F_ALLOCSP
     92 	{ F_ALLOCSP,	"F_ALLOCSP"	},
     93 #endif
     94 #ifdef F_ISSTREAM
     95 	{ F_ISSTREAM,	"F_ISSTREAM"	},
     96 #endif
     97 #ifdef F_PRIV
     98 	{ F_PRIV,	"F_PRIV"	},
     99 #endif
    100 #ifdef F_NPRIV
    101 	{ F_NPRIV,	"F_NPRIV"	},
    102 #endif
    103 #ifdef F_QUOTACL
    104 	{ F_QUOTACL,	"F_QUOTACL"	},
    105 #endif
    106 #ifdef F_BLOCKS
    107 	{ F_BLOCKS,	"F_BLOCKS"	},
    108 #endif
    109 #ifdef F_BLKSIZE
    110 	{ F_BLKSIZE,	"F_BLKSIZE"	},
    111 #endif
    112 #ifdef F_GETOWN
    113 	{ F_GETOWN,	"F_GETOWN"	},
    114 #endif
    115 #ifdef F_SETOWN
    116 	{ F_SETOWN,	"F_SETOWN"	},
    117 #endif
    118 #ifdef F_REVOKE
    119 	{ F_REVOKE,	"F_REVOKE"	},
    120 #endif
    121 #ifdef F_SETLK
    122 	{ F_SETLK,	"F_SETLK"	},
    123 #endif
    124 #ifdef F_SETLKW
    125 	{ F_SETLKW,	"F_SETLKW"	},
    126 #endif
    127 #ifdef F_FREESP
    128 	{ F_FREESP,	"F_FREESP"	},
    129 #endif
    130 #ifdef F_GETLK
    131 	{ F_GETLK,	"F_GETLK"	},
    132 #endif
    133 #ifdef F_SETLK64
    134 	{ F_SETLK64,	"F_SETLK64"	},
    135 #endif
    136 #ifdef F_SETLKW64
    137 	{ F_SETLKW64,	"F_SETLKW64"	},
    138 #endif
    139 #ifdef F_FREESP64
    140 	{ F_FREESP64,	"F_FREESP64"	},
    141 #endif
    142 #ifdef F_GETLK64
    143 	{ F_GETLK64,	"F_GETLK64"	},
    144 #endif
    145 #ifdef F_SHARE
    146 	{ F_SHARE,	"F_SHARE"	},
    147 #endif
    148 #ifdef F_UNSHARE
    149 	{ F_UNSHARE,	"F_UNSHARE"	},
    150 #endif
    151 	{ 0,		NULL		},
    152 };
    153 
    154 static const struct xlat fdflags[] = {
    155 #ifdef FD_CLOEXEC
    156 	{ FD_CLOEXEC,	"FD_CLOEXEC"	},
    157 #endif
    158 	{ 0,		NULL		},
    159 };
    160 
    161 #ifdef LOCK_SH
    162 
    163 static const struct xlat flockcmds[] = {
    164 	{ LOCK_SH,	"LOCK_SH"	},
    165 	{ LOCK_EX,	"LOCK_EX"	},
    166 	{ LOCK_NB,	"LOCK_NB"	},
    167 	{ LOCK_UN,	"LOCK_UN"	},
    168 	{ 0,		NULL		},
    169 };
    170 
    171 #endif /* LOCK_SH */
    172 
    173 static const struct xlat lockfcmds[] = {
    174 	{ F_RDLCK,	"F_RDLCK"	},
    175 	{ F_WRLCK,	"F_WRLCK"	},
    176 	{ F_UNLCK,	"F_UNLCK"	},
    177 #ifdef F_EXLCK
    178 	{ F_EXLCK,	"F_EXLCK"	},
    179 #endif
    180 #ifdef F_SHLCK
    181 	{ F_SHLCK,	"F_SHLCK"	},
    182 #endif
    183 	{ 0,		NULL		},
    184 };
    185 
    186 static const struct xlat whence[] = {
    187 	{ SEEK_SET,	"SEEK_SET"	},
    188 	{ SEEK_CUR,	"SEEK_CUR"	},
    189 	{ SEEK_END,	"SEEK_END"	},
    190 	{ 0,		NULL		},
    191 };
    192 
    193 #ifndef HAVE_LONG_LONG_OFF_T
    194 /* fcntl/lockf */
    195 static void
    196 printflock(tcp, addr, getlk)
    197 struct tcb *tcp;
    198 long addr;
    199 int getlk;
    200 {
    201 	struct flock fl;
    202 
    203 	if (umove(tcp, addr, &fl) < 0) {
    204 		tprintf("{...}");
    205 		return;
    206 	}
    207 	tprintf("{type=");
    208 	printxval(lockfcmds, fl.l_type, "F_???");
    209 	tprintf(", whence=");
    210 	printxval(whence, fl.l_whence, "SEEK_???");
    211 	tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
    212 	if (getlk)
    213 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
    214 	else
    215 		tprintf("}");
    216 }
    217 #endif
    218 
    219 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
    220 /* fcntl/lockf */
    221 static void
    222 printflock64(tcp, addr, getlk)
    223 struct tcb *tcp;
    224 long addr;
    225 int getlk;
    226 {
    227 	struct flock64 fl;
    228 
    229 	if (umove(tcp, addr, &fl) < 0) {
    230 		tprintf("{...}");
    231 		return;
    232 	}
    233 	tprintf("{type=");
    234 	printxval(lockfcmds, fl.l_type, "F_???");
    235 	tprintf(", whence=");
    236 	printxval(whence, fl.l_whence, "SEEK_???");
    237 	tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
    238 	if (getlk)
    239 		tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
    240 	else
    241 		tprintf("}");
    242 }
    243 #endif
    244 
    245 static char *
    246 sprintflags(xlat, flags)
    247 const struct xlat *xlat;
    248 int flags;
    249 {
    250 	static char outstr[1024];
    251 	char *sep;
    252 
    253 	strcpy(outstr, "flags ");
    254 	sep = "";
    255 	for (; xlat->str; xlat++) {
    256 		if ((flags & xlat->val) == xlat->val) {
    257 			sprintf(outstr + strlen(outstr),
    258 				"%s%s", sep, xlat->str);
    259 			sep = "|";
    260 			flags &= ~xlat->val;
    261 		}
    262 	}
    263 	if (flags)
    264 		sprintf(outstr + strlen(outstr),
    265 			"%s%#x", sep, flags);
    266 	return outstr;
    267 }
    268 
    269 int
    270 sys_fcntl(tcp)
    271 struct tcb *tcp;
    272 {
    273 	extern const struct xlat openmodes[];
    274 
    275 	if (entering(tcp)) {
    276 		tprintf("%ld, ", tcp->u_arg[0]);
    277 		printxval(fcntlcmds, tcp->u_arg[1], "F_???");
    278 		switch (tcp->u_arg[1]) {
    279 		case F_SETFD:
    280 			tprintf(", ");
    281 			printflags(fdflags, tcp->u_arg[2], "FD_???");
    282 			break;
    283 		case F_SETOWN: case F_DUPFD:
    284 			tprintf(", %ld", tcp->u_arg[2]);
    285 			break;
    286 		case F_SETFL:
    287 			tprintf(", ");
    288 			printflags(openmodes, tcp->u_arg[2] + 1, "O_???");
    289 			break;
    290 		case F_SETLK: case F_SETLKW:
    291 #ifdef F_FREESP
    292 		case F_FREESP:
    293 #endif
    294 			tprintf(", ");
    295 			printflock(tcp, tcp->u_arg[2], 0);
    296 			break;
    297 #if _LFS64_LARGEFILE
    298 #ifdef F_FREESP64
    299 		case F_FREESP64:
    300 #endif
    301 		/* Linux glibc defines SETLK64 as SETLK,
    302 		   even though the kernel has different values - as does Solaris. */
    303 #if defined(F_SETLK64) && F_SETLK64+0!=F_SETLK
    304 		case F_SETLK64:
    305 #endif
    306 #if defined(F_SETLKW64) && F_SETLKW64+0!=F_SETLKW
    307 		case F_SETLKW64:
    308 #endif
    309 			tprintf(", ");
    310 			printflock64(tcp, tcp->u_arg[2], 0);
    311 			break;
    312 #endif
    313  		}
    314 	}
    315 	else {
    316 		switch (tcp->u_arg[1]) {
    317 		case F_DUPFD:
    318 		case F_SETFD: case F_SETFL:
    319 		case F_SETLK: case F_SETLKW:
    320 		case F_SETOWN: case F_GETOWN:
    321 			break;
    322 		case F_GETFD:
    323 			if (tcp->u_rval == 0)
    324 				return 0;
    325 			tcp->auxstr = sprintflags(fdflags, tcp->u_rval);
    326 			return RVAL_HEX|RVAL_STR;
    327 		case F_GETFL:
    328 			tcp->auxstr = sprintflags(openmodes, tcp->u_rval + 1);
    329 			return RVAL_HEX|RVAL_STR;
    330 		case F_GETLK:
    331 			tprintf(", ");
    332 			printflock(tcp, tcp->u_arg[2], 1);
    333 			break;
    334 #if _LFS64_LARGEFILE
    335 #if defined(F_GETLK64) && F_GETLK64+0!=F_GETLK
    336 		case F_GETLK64:
    337 #endif
    338 			tprintf(", ");
    339 			printflock64(tcp, tcp->u_arg[2], 1);
    340 			break;
    341 #endif
    342  		default:
    343 			tprintf(", %#lx", tcp->u_arg[2]);
    344 			break;
    345 		}
    346 	}
    347 	return 0;
    348 }
    349 
    350 #ifdef LOCK_SH
    351 
    352 int
    353 sys_flock(tcp)
    354 struct tcb *tcp;
    355 {
    356 	if (entering(tcp)) {
    357 		tprintf("%ld, ", tcp->u_arg[0]);
    358 		printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
    359 	}
    360 	return 0;
    361 }
    362 #endif /* LOCK_SH */
    363 
    364 int
    365 sys_close(tcp)
    366 struct tcb *tcp;
    367 {
    368 	if (entering(tcp)) {
    369 		tprintf("%ld", tcp->u_arg[0]);
    370 	}
    371 	return 0;
    372 }
    373 
    374 int
    375 sys_dup(tcp)
    376 struct tcb *tcp;
    377 {
    378 	if (entering(tcp)) {
    379 		tprintf("%ld", tcp->u_arg[0]);
    380 	}
    381 	return 0;
    382 }
    383 
    384 int
    385 sys_dup2(tcp)
    386 struct tcb *tcp;
    387 {
    388 	if (entering(tcp)) {
    389 		tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]);
    390 	}
    391 	return 0;
    392 }
    393 
    394 int
    395 sys_getdtablesize(tcp)
    396 struct tcb *tcp;
    397 {
    398 	return 0;
    399 }
    400 
    401 static int
    402 decode_select(tcp, args, bitness)
    403 struct tcb *tcp;
    404 long *args;
    405 int bitness;
    406 {
    407 	int i, j, nfds;
    408 	unsigned int fdsize = ((((args[0] + 7) / 8) + sizeof(long) - 1)
    409 			       & -sizeof(long));
    410 	fd_set *fds;
    411 	struct timeval tv;
    412 #ifdef ALPHA
    413 	struct timeval32 {
    414 		unsigned tv_sec;
    415 		unsigned tv_usec;
    416 	} *tv32;
    417 #endif
    418 	static char outstr[1024];
    419 	char *sep;
    420 	long arg;
    421 
    422 	if (entering(tcp)) {
    423 		fds = (fd_set *) malloc(fdsize);
    424 		if (fds == NULL)
    425 			fprintf(stderr, "out of memory\n");
    426 		nfds = args[0];
    427 		tprintf("%d", nfds);
    428 		for (i = 0; i < 3; i++) {
    429 			arg = args[i+1];
    430 			if (arg == 0) {
    431 				tprintf(", NULL");
    432 				continue;
    433 			}
    434 			if (fds == NULL || !verbose(tcp)) {
    435 				tprintf(", %#lx", arg);
    436 				continue;
    437 			}
    438 			if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
    439 				tprintf(", [?]");
    440 				continue;
    441 			}
    442 			tprintf(", [");
    443 			for (j = 0, sep = ""; j < nfds; j++) {
    444 				if (FD_ISSET(j, fds)) {
    445 					tprintf("%s%u", sep, j);
    446 					sep = " ";
    447 				}
    448 			}
    449 			tprintf("]");
    450 		}
    451 		free(fds);
    452 		if (!args[4])
    453 			tprintf(", NULL");
    454 		else if (!verbose(tcp))
    455 			tprintf(", %#lx", args[4]);
    456 		else if (umove(tcp, args[4], &tv) < 0)
    457 			tprintf(", {...}");
    458 		else {
    459 #ifdef ALPHA
    460 			if (bitness) {
    461 				tv32=(struct timeval32*)&tv;
    462 				tprintf(", {%u, %u}", tv32->tv_sec, tv32->tv_usec);
    463 			} else
    464 #endif
    465 				tprintf(", {%lu, %lu}",
    466 					(long) tv.tv_sec, (long) tv.tv_usec);
    467 		}
    468 	}
    469 	else
    470 	{
    471 		unsigned int cumlen = 0;
    472 		char *sep = "";
    473 
    474 		if (syserror(tcp))
    475 			return 0;
    476 
    477 		if ((nfds = tcp->u_rval) == 0) {
    478 			tcp->auxstr = "Timeout";
    479 			return RVAL_STR;
    480 		}
    481 
    482 		fds = (fd_set *) malloc(fdsize);
    483 		if (fds == NULL)
    484 			fprintf(stderr, "out of memory\n");
    485 
    486 		outstr[0] = '\0';
    487 		for (i = 0; i < 3; i++) {
    488 			int first = 1;
    489 			char str[20];
    490 
    491 			tcp->auxstr = outstr;
    492 			arg = args[i+1];
    493 			if (fds == NULL || !arg ||
    494 			    umoven(tcp, arg, fdsize, (char *) fds) < 0)
    495 				continue;
    496 			for (j = 0; j < args[0]; j++) {
    497 				if (FD_ISSET(j, fds)) {
    498 					if (first) {
    499 						sprintf(str, "%s%s [%u", sep,
    500 							i == 0 ? "in" :
    501 							i == 1 ? "out" :
    502 							"except", j);
    503 						first = 0;
    504 						sep = ", ";
    505 					}
    506 					else
    507 						sprintf(str, " %u", j);
    508 					cumlen += strlen(str);
    509 					if (cumlen < sizeof(outstr))
    510 						strcat(outstr, str);
    511 					nfds--;
    512 				}
    513 			}
    514 			if (cumlen)
    515 				strcat(outstr, "]");
    516 			if (nfds == 0)
    517 				break;
    518 		}
    519 		free(fds);
    520 #ifdef LINUX
    521 		/* This contains no useful information on SunOS.  */
    522 		if (args[4]) {
    523 			char str[64];
    524 
    525 			if (umove(tcp, args[4], &tv) >= 0) {
    526 #ifdef ALPHA
    527 				if (bitness) {
    528 					tv32=(struct timeval32*)&tv;
    529 					sprintf(str, "%sleft {%u, %u}", sep,
    530 						tv32->tv_sec, tv32->tv_usec);
    531 				} else
    532 #endif
    533 					sprintf(str, "%sleft {%lu, %lu}", sep,
    534 						(long) tv.tv_sec, (long) tv.tv_usec);
    535 
    536 				if ((cumlen += strlen(str)) < sizeof(outstr))
    537 					strcat(outstr, str);
    538 			}
    539 		}
    540 #endif /* LINUX */
    541 		return RVAL_STR;
    542 	}
    543 	return 0;
    544 }
    545 
    546 #ifdef LINUX
    547 
    548 int
    549 sys_oldselect(tcp)
    550 struct tcb *tcp;
    551 {
    552 	long args[5];
    553 
    554 	if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
    555 		tprintf("[...]");
    556 		return 0;
    557 	}
    558 	return decode_select(tcp, args, 0);
    559 }
    560 
    561 #ifdef ALPHA
    562 int
    563 sys_osf_select(tcp)
    564 struct tcb *tcp;
    565 {
    566 	long *args = tcp->u_arg;
    567 	return decode_select(tcp, args, 1);
    568 }
    569 #endif
    570 
    571 static struct xlat epollctls[] = {
    572 #ifdef EPOLL_CTL_ADD
    573 	{ EPOLL_CTL_ADD,	"EPOLL_CTL_ADD"	},
    574 #endif
    575 #ifdef EPOLL_CTL_MOD
    576 	{ EPOLL_CTL_MOD,	"EPOLL_CTL_MOD"	},
    577 #endif
    578 #ifdef EPOLL_CTL_DEL
    579 	{ EPOLL_CTL_DEL,	"EPOLL_CTL_DEL"	},
    580 #endif
    581 	{ 0,			NULL		}
    582 };
    583 
    584 static struct xlat epollevents[] = {
    585 #ifdef EPOLLIN
    586 	{ EPOLLIN,	"EPOLLIN"	},
    587 #endif
    588 #ifdef EPOLLPRI
    589 	{ EPOLLPRI,	"EPOLLPRI"	},
    590 #endif
    591 #ifdef EPOLLOUT
    592 	{ EPOLLOUT,	"EPOLLOUT"	},
    593 #endif
    594 #ifdef EPOLLRDNORM
    595 	{ EPOLLRDNORM,	"EPOLLRDNORM"	},
    596 #endif
    597 #ifdef EPOLLRDBAND
    598 	{ EPOLLRDBAND,	"EPOLLRDBAND"	},
    599 #endif
    600 #ifdef EPOLLWRNORM
    601 	{ EPOLLWRNORM,	"EPOLLWRNORM"	},
    602 #endif
    603 #ifdef EPOLLWRBAND
    604 	{ EPOLLWRBAND,	"EPOLLWRBAND"	},
    605 #endif
    606 #ifdef EPOLLMSG
    607 	{ EPOLLMSG,	"EPOLLMSG"	},
    608 #endif
    609 #ifdef EPOLLERR
    610 	{ EPOLLERR,	"EPOLLERR"	},
    611 #endif
    612 #ifdef EPOLLHUP
    613 	{ EPOLLHUP,	"EPOLLHUP"	},
    614 #endif
    615 #ifdef EPOLLONESHOT
    616 	{ EPOLLONESHOT,	"EPOLLONESHOT"	},
    617 #endif
    618 #ifdef EPOLLET
    619 	{ EPOLLET,	"EPOLLET"	},
    620 #endif
    621 	{ 0,		NULL		}
    622 };
    623 
    624 int
    625 sys_epoll_create(tcp)
    626 struct tcb *tcp;
    627 {
    628 	if (entering(tcp))
    629 		tprintf("%ld", tcp->u_arg[0]);
    630 	return 0;
    631 }
    632 
    633 #ifdef HAVE_SYS_EPOLL_H
    634 static void
    635 print_epoll_event(ev)
    636 struct epoll_event *ev;
    637 {
    638 	tprintf("{");
    639 	printflags(epollevents, ev->events, "EPOLL???");
    640 	/* We cannot know what format the program uses, so print u32 and u64
    641 	   which will cover every value.  */
    642 	tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
    643 		ev->data.u32, ev->data.u64);
    644 }
    645 #endif
    646 
    647 int
    648 sys_epoll_ctl(tcp)
    649 struct tcb *tcp;
    650 {
    651 	if (entering(tcp)) {
    652 		tprintf("%ld, ", tcp->u_arg[0]);
    653                 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
    654 		tprintf(", %ld, ", tcp->u_arg[2]);
    655 		if (tcp->u_arg[3] == 0)
    656 			tprintf("NULL");
    657 		else {
    658 #ifdef HAVE_SYS_EPOLL_H
    659 			struct epoll_event ev;
    660 			if (umove(tcp, tcp->u_arg[3], &ev) == 0)
    661 				print_epoll_event(&ev);
    662 			else
    663 #endif
    664 				tprintf("{...}");
    665 		}
    666 	}
    667 	return 0;
    668 }
    669 
    670 int
    671 sys_epoll_wait(tcp)
    672 struct tcb *tcp;
    673 {
    674 	if (entering(tcp))
    675 		tprintf("%ld, ", tcp->u_arg[0]);
    676 	else {
    677 		if (syserror(tcp))
    678 			tprintf("%lx", tcp->u_arg[1]);
    679 		else if (tcp->u_rval == 0)
    680 			tprintf("{}");
    681 		else {
    682 #ifdef HAVE_SYS_EPOLL_H
    683 			struct epoll_event ev, *start, *cur, *end;
    684 			int failed = 0;
    685 
    686 			tprintf("{");
    687 			start = (struct epoll_event *) tcp->u_arg[1];
    688 			end = start + tcp->u_rval;
    689 			for (cur = start; cur < end; ++cur) {
    690 				if (cur > start)
    691 					tprintf(", ");
    692 				if (umove(tcp, (long) cur, &ev) == 0)
    693 					print_epoll_event(&ev);
    694 				else {
    695 					tprintf("?");
    696 					failed = 1;
    697 					break;
    698 				}
    699 			}
    700 			tprintf("}");
    701 			if (failed)
    702 				tprintf(" %#lx", (long) start);
    703 #else
    704 			tprintf("{...}");
    705 #endif
    706 		}
    707 		tprintf(", %ld, %ld", tcp->u_arg[2], tcp->u_arg[3]);
    708 	}
    709 	return 0;
    710 }
    711 
    712 int
    713 sys_io_setup(tcp)
    714 struct tcb *tcp;
    715 {
    716 	if (entering(tcp))
    717 		tprintf("%ld, ", tcp->u_arg[0]);
    718 	else {
    719 		if (syserror(tcp))
    720 			tprintf("0x%0lx", tcp->u_arg[1]);
    721 		else {
    722 			unsigned long user_id;
    723 			if (umove(tcp, tcp->u_arg[1], &user_id) == 0)
    724 				tprintf("{%lu}", user_id);
    725 			else
    726 				tprintf("{...}");
    727 		}
    728 	}
    729 	return 0;
    730 }
    731 
    732 int
    733 sys_io_destroy(tcp)
    734 struct tcb *tcp;
    735 {
    736 	if (entering(tcp))
    737 		tprintf("%lu", tcp->u_arg[0]);
    738 	return 0;
    739 }
    740 
    741 int
    742 sys_io_submit(tcp)
    743 struct tcb *tcp;
    744 {
    745 	long nr;
    746 	if (entering(tcp)) {
    747 		tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
    748 		nr = tcp->u_arg[1];
    749 		/* and if nr is negative? */
    750 		if (nr == 0)
    751 			tprintf("{}");
    752 		else {
    753 #ifdef HAVE_LIBAIO_H
    754 			long i;
    755 			struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2];
    756 
    757 			for (i = 0; i < nr; i++, iocbs++) {
    758 				struct iocb iocb;
    759 				if (i == 0)
    760 					tprintf("{");
    761 				else
    762 					tprintf(", ");
    763 
    764 				if (umove(tcp, (unsigned long)iocbs, &iocbp) ||
    765 				    umove(tcp, (unsigned long)iocbp, &iocb)) {
    766 					tprintf("{...}");
    767 					continue;
    768 				}
    769 				tprintf("{%p, %u, %hu, %hu, %d}",
    770 					iocb.data, iocb.key,
    771 					iocb.aio_lio_opcode,
    772 					iocb.aio_reqprio, iocb.aio_fildes);
    773 			}
    774 			if (i)
    775 				tprintf("}");
    776 #else
    777 			tprintf("{...}");
    778 #endif
    779 		}
    780 	}
    781 	return 0;
    782 }
    783 
    784 int
    785 sys_io_cancel(tcp)
    786 struct tcb *tcp;
    787 {
    788 	if (entering(tcp)) {
    789 #ifdef HAVE_LIBAIO_H
    790 		struct iocb iocb;
    791 #endif
    792 		tprintf("%lu, ", tcp->u_arg[0]);
    793 #ifdef HAVE_LIBAIO_H
    794 		if (umove(tcp, tcp->u_arg[1], &iocb) == 0) {
    795 			tprintf("{%p, %u, %hu, %hu, %d}, ",
    796 				iocb.data, iocb.key,
    797 				iocb.aio_lio_opcode,
    798 				iocb.aio_reqprio, iocb.aio_fildes);
    799 		} else
    800 #endif
    801 			tprintf("{...}, ");
    802 	} else {
    803 		if (tcp->u_rval < 0)
    804 			tprintf("{...}");
    805 		else {
    806 #ifdef HAVE_LIBAIO_H
    807 			struct io_event event;
    808 			if (umove(tcp, tcp->u_arg[2], &event) == 0)
    809 				tprintf("{%p, %p, %ld, %ld}",
    810 					event.data, event.obj,
    811 					event.res, event.res2);
    812 			else
    813 #endif
    814 				tprintf("{...}");
    815 		}
    816 	}
    817 	return 0;
    818 }
    819 
    820 int
    821 sys_io_getevents(tcp)
    822 struct tcb *tcp;
    823 {
    824 	if (entering(tcp)) {
    825 		tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1],
    826 			tcp->u_arg[2]);
    827 	} else {
    828 		if (tcp->u_rval == 0) {
    829 			tprintf("{}");
    830 		} else  {
    831 #ifdef HAVE_LIBAIO_H
    832 			struct io_event *events = (void *)tcp->u_arg[3];
    833 			long i, nr = tcp->u_rval;
    834 
    835 			for (i = 0; i < nr; i++, events++) {
    836 				struct io_event event;
    837 
    838 				if (i == 0)
    839 					tprintf("{");
    840 				else
    841 					tprintf(", ");
    842 
    843 				if (umove(tcp, (unsigned long)events, &event) != 0) {
    844 					tprintf("{...}");
    845 					continue;
    846 				}
    847 				tprintf("{%p, %p, %ld, %ld}", event.data,
    848 					event.obj, event.res, event.res2);
    849 			}
    850 			tprintf("}, ");
    851 #else
    852 				tprintf("{...}");
    853 #endif
    854 		}
    855 
    856 		if (tcp->u_arg[4] == 0)
    857 			tprintf("NULL");
    858 		else {
    859 			struct timespec to;
    860 			if (umove(tcp, tcp->u_arg[4], &to) == 0)
    861 				tprintf("{%lu, %lu}", to.tv_sec, to.tv_nsec);
    862 			else
    863 				tprintf("{...}");
    864 		}
    865 	}
    866 	return 0;
    867 }
    868 #endif /* LINUX */
    869 
    870 int
    871 sys_select(tcp)
    872 struct tcb *tcp;
    873 {
    874 	long *args = tcp->u_arg;
    875 	return decode_select(tcp, args, 0);
    876 }
    877