• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  *	$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
printflock(tcp,addr,getlk)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
printflock64(tcp,addr,getlk)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 *
sprintflags(xlat,flags)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
sys_fcntl(tcp)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
sys_flock(tcp)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
sys_close(tcp)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
sys_dup(tcp)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
sys_dup2(tcp)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
sys_getdtablesize(tcp)395 sys_getdtablesize(tcp)
396 struct tcb *tcp;
397 {
398 	return 0;
399 }
400 
401 static int
decode_select(tcp,args,bitness)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
sys_oldselect(tcp)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
sys_osf_select(tcp)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
sys_epoll_create(tcp)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
print_epoll_event(ev)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
sys_epoll_ctl(tcp)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
sys_epoll_wait(tcp)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
sys_io_setup(tcp)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
sys_io_destroy(tcp)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
sys_io_submit(tcp)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
sys_io_cancel(tcp)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
sys_io_getevents(tcp)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
sys_select(tcp)871 sys_select(tcp)
872 struct tcb *tcp;
873 {
874 	long *args = tcp->u_arg;
875 	return decode_select(tcp, args, 0);
876 }
877