]> granicus.if.org Git - strace/blob - desc.c
Cleanup after non-Linux code removal.
[strace] / desc.c
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$
31  */
32
33 #include "defs.h"
34
35 #include <fcntl.h>
36 #include <sys/file.h>
37 #include <inttypes.h>
38 #ifdef HAVE_SYS_EPOLL_H
39 #include <sys/epoll.h>
40 #endif
41 #ifdef HAVE_LIBAIO_H
42 #include <libaio.h>
43 #endif
44
45 #if HAVE_LONG_LONG_OFF_T
46 /*
47  * Hacks for systems that have a long long off_t
48  */
49 #define flock64 flock           /* Horrid hack */
50 #define printflock printflock64 /* Horrider hack */
51 #endif
52
53
54 static const struct xlat fcntlcmds[] = {
55         { F_DUPFD,      "F_DUPFD"       },
56         { F_GETFD,      "F_GETFD"       },
57         { F_SETFD,      "F_SETFD"       },
58         { F_GETFL,      "F_GETFL"       },
59         { F_SETFL,      "F_SETFL"       },
60         { F_GETLK,      "F_GETLK"       },
61         { F_SETLK,      "F_SETLK"       },
62         { F_SETLKW,     "F_SETLKW"      },
63         { F_GETOWN,     "F_GETOWN"      },
64         { F_SETOWN,     "F_SETOWN"      },
65 #ifdef F_RSETLK
66         { F_RSETLK,     "F_RSETLK"      },
67 #endif
68 #ifdef F_RSETLKW
69         { F_RSETLKW,    "F_RSETLKW"     },
70 #endif
71 #ifdef F_RGETLK
72         { F_RGETLK,     "F_RGETLK"      },
73 #endif
74 #ifdef F_CNVT
75         { F_CNVT,       "F_CNVT"        },
76 #endif
77 #ifdef F_SETSIG
78         { F_SETSIG,     "F_SETSIG"      },
79 #endif
80 #ifdef F_GETSIG
81         { F_GETSIG,     "F_GETSIG"      },
82 #endif
83 #ifdef F_CHKFL
84         { F_CHKFL,      "F_CHKFL"       },
85 #endif
86 #ifdef F_DUP2FD
87         { F_DUP2FD,     "F_DUP2FD"      },
88 #endif
89 #ifdef F_ALLOCSP
90         { F_ALLOCSP,    "F_ALLOCSP"     },
91 #endif
92 #ifdef F_ISSTREAM
93         { F_ISSTREAM,   "F_ISSTREAM"    },
94 #endif
95 #ifdef F_PRIV
96         { F_PRIV,       "F_PRIV"        },
97 #endif
98 #ifdef F_NPRIV
99         { F_NPRIV,      "F_NPRIV"       },
100 #endif
101 #ifdef F_QUOTACL
102         { F_QUOTACL,    "F_QUOTACL"     },
103 #endif
104 #ifdef F_BLOCKS
105         { F_BLOCKS,     "F_BLOCKS"      },
106 #endif
107 #ifdef F_BLKSIZE
108         { F_BLKSIZE,    "F_BLKSIZE"     },
109 #endif
110 #ifdef F_GETOWN
111         { F_GETOWN,     "F_GETOWN"      },
112 #endif
113 #ifdef F_SETOWN
114         { F_SETOWN,     "F_SETOWN"      },
115 #endif
116 #ifdef F_REVOKE
117         { F_REVOKE,     "F_REVOKE"      },
118 #endif
119 #ifdef F_SETLK
120         { F_SETLK,      "F_SETLK"       },
121 #endif
122 #ifdef F_SETLKW
123         { F_SETLKW,     "F_SETLKW"      },
124 #endif
125 #ifdef F_FREESP
126         { F_FREESP,     "F_FREESP"      },
127 #endif
128 #ifdef F_GETLK
129         { F_GETLK,      "F_GETLK"       },
130 #endif
131 #ifdef F_SETLK64
132         { F_SETLK64,    "F_SETLK64"     },
133 #endif
134 #ifdef F_SETLKW64
135         { F_SETLKW64,   "F_SETLKW64"    },
136 #endif
137 #ifdef F_FREESP64
138         { F_FREESP64,   "F_FREESP64"    },
139 #endif
140 #ifdef F_GETLK64
141         { F_GETLK64,    "F_GETLK64"     },
142 #endif
143 #ifdef F_SHARE
144         { F_SHARE,      "F_SHARE"       },
145 #endif
146 #ifdef F_UNSHARE
147         { F_UNSHARE,    "F_UNSHARE"     },
148 #endif
149 #ifdef F_SETLEASE
150         { F_SETLEASE,   "F_SETLEASE"    },
151 #endif
152 #ifdef F_GETLEASE
153         { F_GETLEASE,   "F_GETLEASE"    },
154 #endif
155 #ifdef F_NOTIFY
156         { F_NOTIFY,     "F_NOTIFY"      },
157 #endif
158 #ifdef F_DUPFD_CLOEXEC
159         { F_DUPFD_CLOEXEC,"F_DUPFD_CLOEXEC"},
160 #endif
161         { 0,            NULL            },
162 };
163
164 static const struct xlat fdflags[] = {
165 #ifdef FD_CLOEXEC
166         { FD_CLOEXEC,   "FD_CLOEXEC"    },
167 #endif
168         { 0,            NULL            },
169 };
170
171 #ifdef LOCK_SH
172
173 static const struct xlat flockcmds[] = {
174         { LOCK_SH,      "LOCK_SH"       },
175         { LOCK_EX,      "LOCK_EX"       },
176         { LOCK_NB,      "LOCK_NB"       },
177         { LOCK_UN,      "LOCK_UN"       },
178         { 0,            NULL            },
179 };
180
181 #endif /* LOCK_SH */
182
183 static const struct xlat lockfcmds[] = {
184         { F_RDLCK,      "F_RDLCK"       },
185         { F_WRLCK,      "F_WRLCK"       },
186         { F_UNLCK,      "F_UNLCK"       },
187 #ifdef F_EXLCK
188         { F_EXLCK,      "F_EXLCK"       },
189 #endif
190 #ifdef F_SHLCK
191         { F_SHLCK,      "F_SHLCK"       },
192 #endif
193         { 0,            NULL            },
194 };
195
196 #ifdef F_NOTIFY
197 static const struct xlat notifyflags[] = {
198 #ifdef DN_ACCESS
199         { DN_ACCESS,    "DN_ACCESS"     },
200 #endif
201 #ifdef DN_MODIFY
202         { DN_MODIFY,    "DN_MODIFY"     },
203 #endif
204 #ifdef DN_CREATE
205         { DN_CREATE,    "DN_CREATE"     },
206 #endif
207 #ifdef DN_DELETE
208         { DN_DELETE,    "DN_DELETE"     },
209 #endif
210 #ifdef DN_RENAME
211         { DN_RENAME,    "DN_RENAME"     },
212 #endif
213 #ifdef DN_ATTRIB
214         { DN_ATTRIB,    "DN_ATTRIB"     },
215 #endif
216 #ifdef DN_MULTISHOT
217         { DN_MULTISHOT, "DN_MULTISHOT"  },
218 #endif
219         { 0,            NULL            },
220 };
221 #endif
222
223 static const struct xlat whence[] = {
224         { SEEK_SET,     "SEEK_SET"      },
225         { SEEK_CUR,     "SEEK_CUR"      },
226         { SEEK_END,     "SEEK_END"      },
227         { 0,            NULL            },
228 };
229
230 #ifndef HAVE_LONG_LONG_OFF_T
231 /* fcntl/lockf */
232 static void
233 printflock(struct tcb *tcp, long addr, int getlk)
234 {
235         struct flock fl;
236
237 #if SUPPORTED_PERSONALITIES > 1
238         if (personality_wordsize[current_personality] != sizeof(fl.l_start)) {
239                 if (personality_wordsize[current_personality] == 4) {
240                         /* 32-bit x86 app on x86_64 and similar cases */
241                         struct {
242                                 short int l_type;
243                                 short int l_whence;
244                                 int32_t l_start; /* off_t */
245                                 int32_t l_len; /* off_t */
246                                 int32_t l_pid; /* pid_t */
247                         } fl32;
248                         if (umove(tcp, addr, &fl32) < 0) {
249                                 tprints("{...}");
250                                 return;
251                         }
252                         fl.l_type = fl32.l_type;
253                         fl.l_whence = fl32.l_whence;
254                         fl.l_start = fl32.l_start;
255                         fl.l_len = fl32.l_len;
256                         fl.l_pid = fl32.l_pid;
257                 } else {
258                         /* let people know we have a problem here */
259                         tprintf("{ <decode error: unsupported wordsize %d> }",
260                                 personality_wordsize[current_personality]);
261                         return;
262                 }
263         } else
264 #endif
265         {
266                 if (umove(tcp, addr, &fl) < 0) {
267                         tprints("{...}");
268                         return;
269                 }
270         }
271         tprints("{type=");
272         printxval(lockfcmds, fl.l_type, "F_???");
273         tprints(", whence=");
274         printxval(whence, fl.l_whence, "SEEK_???");
275         tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len);
276         if (getlk)
277                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
278         else
279                 tprints("}");
280 }
281 #endif
282
283 #if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T
284 /* fcntl/lockf */
285 static void
286 printflock64(struct tcb *tcp, long addr, int getlk)
287 {
288         struct flock64 fl;
289
290         if (umove(tcp, addr, &fl) < 0) {
291                 tprints("{...}");
292                 return;
293         }
294         tprints("{type=");
295         printxval(lockfcmds, fl.l_type, "F_???");
296         tprints(", whence=");
297         printxval(whence, fl.l_whence, "SEEK_???");
298         tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len);
299         if (getlk)
300                 tprintf(", pid=%lu}", (unsigned long) fl.l_pid);
301         else
302                 tprints("}");
303 }
304 #endif
305
306 int
307 sys_fcntl(struct tcb *tcp)
308 {
309         if (entering(tcp)) {
310                 printfd(tcp, tcp->u_arg[0]);
311                 tprints(", ");
312                 printxval(fcntlcmds, tcp->u_arg[1], "F_???");
313                 switch (tcp->u_arg[1]) {
314                 case F_SETFD:
315                         tprints(", ");
316                         printflags(fdflags, tcp->u_arg[2], "FD_???");
317                         break;
318                 case F_SETOWN: case F_DUPFD:
319 #ifdef F_DUPFD_CLOEXEC
320                 case F_DUPFD_CLOEXEC:
321 #endif
322                         tprintf(", %ld", tcp->u_arg[2]);
323                         break;
324                 case F_SETFL:
325                         tprints(", ");
326                         tprint_open_modes(tcp->u_arg[2]);
327                         break;
328                 case F_SETLK: case F_SETLKW:
329 #ifdef F_FREESP
330                 case F_FREESP:
331 #endif
332                         tprints(", ");
333                         printflock(tcp, tcp->u_arg[2], 0);
334                         break;
335 #if _LFS64_LARGEFILE
336 #ifdef F_FREESP64
337                 case F_FREESP64:
338 #endif
339                 /* Linux glibc defines SETLK64 as SETLK,
340                    even though the kernel has different values - as does Solaris. */
341 #if defined(F_SETLK64) && F_SETLK64 + 0 != F_SETLK
342                 case F_SETLK64:
343 #endif
344 #if defined(F_SETLKW64) && F_SETLKW64 + 0 != F_SETLKW
345                 case F_SETLKW64:
346 #endif
347                         tprints(", ");
348                         printflock64(tcp, tcp->u_arg[2], 0);
349                         break;
350 #endif
351 #ifdef F_NOTIFY
352                 case F_NOTIFY:
353                         tprints(", ");
354                         printflags(notifyflags, tcp->u_arg[2], "DN_???");
355                         break;
356 #endif
357 #ifdef F_SETLEASE
358                 case F_SETLEASE:
359                         tprints(", ");
360                         printxval(lockfcmds, tcp->u_arg[2], "F_???");
361                         break;
362 #endif
363                 }
364         }
365         else {
366                 switch (tcp->u_arg[1]) {
367                 case F_DUPFD:
368 #ifdef F_DUPFD_CLOEXEC
369                 case F_DUPFD_CLOEXEC:
370 #endif
371                 case F_SETFD: case F_SETFL:
372                 case F_SETLK: case F_SETLKW:
373                 case F_SETOWN: case F_GETOWN:
374 #ifdef F_NOTIFY
375                 case F_NOTIFY:
376 #endif
377 #ifdef F_SETLEASE
378                 case F_SETLEASE:
379 #endif
380                         break;
381                 case F_GETFD:
382                         if (syserror(tcp) || tcp->u_rval == 0)
383                                 return 0;
384                         tcp->auxstr = sprintflags("flags ", fdflags, tcp->u_rval);
385                         return RVAL_HEX|RVAL_STR;
386                 case F_GETFL:
387                         if (syserror(tcp))
388                                 return 0;
389                         tcp->auxstr = sprint_open_modes(tcp->u_rval);
390                         return RVAL_HEX|RVAL_STR;
391                 case F_GETLK:
392                         tprints(", ");
393                         printflock(tcp, tcp->u_arg[2], 1);
394                         break;
395 #if _LFS64_LARGEFILE
396 #if defined(F_GETLK64) && F_GETLK64+0 != F_GETLK
397                 case F_GETLK64:
398 #endif
399                         tprints(", ");
400                         printflock64(tcp, tcp->u_arg[2], 1);
401                         break;
402 #endif
403 #ifdef F_GETLEASE
404                 case F_GETLEASE:
405                         if (syserror(tcp))
406                                 return 0;
407                         tcp->auxstr = xlookup(lockfcmds, tcp->u_rval);
408                         return RVAL_HEX|RVAL_STR;
409 #endif
410                 default:
411                         tprintf(", %#lx", tcp->u_arg[2]);
412                         break;
413                 }
414         }
415         return 0;
416 }
417
418 #ifdef LOCK_SH
419
420 int
421 sys_flock(struct tcb *tcp)
422 {
423         if (entering(tcp)) {
424                 printfd(tcp, tcp->u_arg[0]);
425                 tprints(", ");
426                 printflags(flockcmds, tcp->u_arg[1], "LOCK_???");
427         }
428         return 0;
429 }
430 #endif /* LOCK_SH */
431
432 int
433 sys_close(struct tcb *tcp)
434 {
435         if (entering(tcp)) {
436                 printfd(tcp, tcp->u_arg[0]);
437         }
438         return 0;
439 }
440
441 static int
442 do_dup2(struct tcb *tcp, int flags_arg)
443 {
444         if (entering(tcp)) {
445                 printfd(tcp, tcp->u_arg[0]);
446                 tprints(", ");
447                 printfd(tcp, tcp->u_arg[1]);
448                 if (flags_arg >= 0) {
449                         tprints(", ");
450                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
451                 }
452         }
453         return 0;
454 }
455
456 int
457 sys_dup2(struct tcb *tcp)
458 {
459         return do_dup2(tcp, -1);
460 }
461
462 int
463 sys_dup3(struct tcb *tcp)
464 {
465         return do_dup2(tcp, 2);
466 }
467
468 #if defined(ALPHA)
469 int
470 sys_getdtablesize(struct tcb *tcp)
471 {
472         return 0;
473 }
474 #endif
475
476 static int
477 decode_select(struct tcb *tcp, long *args, enum bitness_t bitness)
478 {
479         int i, j;
480         unsigned nfds, fdsize;
481         fd_set *fds;
482         const char *sep;
483         long arg;
484
485         fdsize = args[0];
486         /* Beware of select(2^31-1, NULL, NULL, NULL) and similar... */
487         if (args[0] > 1024*1024)
488                 fdsize = 1024*1024;
489         if (args[0] < 0)
490                 fdsize = 0;
491         fdsize = (((fdsize + 7) / 8) + sizeof(long)-1) & -sizeof(long);
492
493         if (entering(tcp)) {
494                 fds = malloc(fdsize);
495                 if (!fds)
496                         die_out_of_memory();
497                 nfds = args[0];
498                 tprintf("%d", nfds);
499                 for (i = 0; i < 3; i++) {
500                         arg = args[i+1];
501                         if (arg == 0) {
502                                 tprints(", NULL");
503                                 continue;
504                         }
505                         if (!verbose(tcp)) {
506                                 tprintf(", %#lx", arg);
507                                 continue;
508                         }
509                         if (umoven(tcp, arg, fdsize, (char *) fds) < 0) {
510                                 tprints(", [?]");
511                                 continue;
512                         }
513                         tprints(", [");
514                         for (j = 0, sep = ""; j < nfds; j++) {
515                                 if (FD_ISSET(j, fds)) {
516                                         tprints(sep);
517                                         printfd(tcp, j);
518                                         sep = " ";
519                                 }
520                         }
521                         tprints("]");
522                 }
523                 free(fds);
524                 tprints(", ");
525                 printtv_bitness(tcp, args[4], bitness, 0);
526         }
527         else {
528                 static char outstr[1024];
529                 char *outptr;
530 #define end_outstr (outstr + sizeof(outstr))
531                 const char *sep;
532
533                 if (syserror(tcp))
534                         return 0;
535
536                 nfds = tcp->u_rval;
537                 if (nfds == 0) {
538                         tcp->auxstr = "Timeout";
539                         return RVAL_STR;
540                 }
541
542                 fds = malloc(fdsize);
543                 if (!fds)
544                         die_out_of_memory();
545
546                 outptr = outstr;
547                 sep = "";
548                 for (i = 0; i < 3; i++) {
549                         int first = 1;
550
551                         arg = args[i+1];
552                         if (!arg || umoven(tcp, arg, fdsize, (char *) fds) < 0)
553                                 continue;
554                         for (j = 0; j < args[0]; j++) {
555                                 if (FD_ISSET(j, fds)) {
556                                         /* +2 chars needed at the end: ']',NUL */
557                                         if (outptr < end_outstr - (sizeof(", except [") + sizeof(int)*3 + 2)) {
558                                                 if (first) {
559                                                         outptr += sprintf(outptr, "%s%s [%u",
560                                                                 sep,
561                                                                 i == 0 ? "in" : i == 1 ? "out" : "except",
562                                                                 j
563                                                         );
564                                                         first = 0;
565                                                         sep = ", ";
566                                                 }
567                                                 else {
568                                                         outptr += sprintf(outptr, " %u", j);
569                                                 }
570                                         }
571                                         nfds--;
572                                 }
573                         }
574                         if (outptr != outstr)
575                                 *outptr++ = ']';
576                         if (nfds == 0)
577                                 break;
578                 }
579                 free(fds);
580                 /* This contains no useful information on SunOS.  */
581                 if (args[4]) {
582                         if (outptr < end_outstr - (10 + TIMEVAL_TEXT_BUFSIZE)) {
583                                 outptr += sprintf(outptr, "%sleft ", sep);
584                                 outptr = sprinttv(outptr, tcp, args[4], bitness, /*special:*/ 0);
585                         }
586                 }
587                 *outptr = '\0';
588                 tcp->auxstr = outstr;
589                 return RVAL_STR;
590 #undef end_outstr
591         }
592         return 0;
593 }
594
595
596 int
597 sys_oldselect(struct tcb *tcp)
598 {
599         long args[5];
600
601         if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) {
602                 tprints("[...]");
603                 return 0;
604         }
605         return decode_select(tcp, args, BITNESS_CURRENT);
606 }
607
608 #ifdef ALPHA
609 int
610 sys_osf_select(struct tcb *tcp)
611 {
612         long *args = tcp->u_arg;
613         return decode_select(tcp, args, BITNESS_32);
614 }
615 #endif
616
617 static const struct xlat epollctls[] = {
618 #ifdef EPOLL_CTL_ADD
619         { EPOLL_CTL_ADD,        "EPOLL_CTL_ADD" },
620 #endif
621 #ifdef EPOLL_CTL_MOD
622         { EPOLL_CTL_MOD,        "EPOLL_CTL_MOD" },
623 #endif
624 #ifdef EPOLL_CTL_DEL
625         { EPOLL_CTL_DEL,        "EPOLL_CTL_DEL" },
626 #endif
627         { 0,                    NULL            }
628 };
629
630 static const struct xlat epollevents[] = {
631 #ifdef EPOLLIN
632         { EPOLLIN,      "EPOLLIN"       },
633 #endif
634 #ifdef EPOLLPRI
635         { EPOLLPRI,     "EPOLLPRI"      },
636 #endif
637 #ifdef EPOLLOUT
638         { EPOLLOUT,     "EPOLLOUT"      },
639 #endif
640 #ifdef EPOLLRDNORM
641         { EPOLLRDNORM,  "EPOLLRDNORM"   },
642 #endif
643 #ifdef EPOLLRDBAND
644         { EPOLLRDBAND,  "EPOLLRDBAND"   },
645 #endif
646 #ifdef EPOLLWRNORM
647         { EPOLLWRNORM,  "EPOLLWRNORM"   },
648 #endif
649 #ifdef EPOLLWRBAND
650         { EPOLLWRBAND,  "EPOLLWRBAND"   },
651 #endif
652 #ifdef EPOLLMSG
653         { EPOLLMSG,     "EPOLLMSG"      },
654 #endif
655 #ifdef EPOLLERR
656         { EPOLLERR,     "EPOLLERR"      },
657 #endif
658 #ifdef EPOLLHUP
659         { EPOLLHUP,     "EPOLLHUP"      },
660 #endif
661 #ifdef EPOLLRDHUP
662         { EPOLLRDHUP,   "EPOLLRDHUP"    },
663 #endif
664 #ifdef EPOLLONESHOT
665         { EPOLLONESHOT, "EPOLLONESHOT"  },
666 #endif
667 #ifdef EPOLLET
668         { EPOLLET,      "EPOLLET"       },
669 #endif
670         { 0,            NULL            }
671 };
672
673 int
674 sys_epoll_create(struct tcb *tcp)
675 {
676         if (entering(tcp))
677                 tprintf("%ld", tcp->u_arg[0]);
678         return 0;
679 }
680
681 static const struct xlat epollflags[] = {
682 #ifdef EPOLL_CLOEXEC
683         { EPOLL_CLOEXEC,        "EPOLL_CLOEXEC" },
684 #endif
685 #ifdef EPOLL_NONBLOCK
686         { EPOLL_NONBLOCK,       "EPOLL_NONBLOCK"        },
687 #endif
688         { 0,            NULL            }
689 };
690
691 int
692 sys_epoll_create1(struct tcb *tcp)
693 {
694         if (entering(tcp))
695                 printflags(epollflags, tcp->u_arg[0], "EPOLL_???");
696         return 0;
697 }
698
699 #ifdef HAVE_SYS_EPOLL_H
700 static void
701 print_epoll_event(struct epoll_event *ev)
702 {
703         tprints("{");
704         printflags(epollevents, ev->events, "EPOLL???");
705         /* We cannot know what format the program uses, so print u32 and u64
706            which will cover every value.  */
707         tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}",
708                 ev->data.u32, ev->data.u64);
709 }
710 #endif
711
712 int
713 sys_epoll_ctl(struct tcb *tcp)
714 {
715         if (entering(tcp)) {
716                 printfd(tcp, tcp->u_arg[0]);
717                 tprints(", ");
718                 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???");
719                 tprints(", ");
720                 printfd(tcp, tcp->u_arg[2]);
721                 tprints(", ");
722                 if (tcp->u_arg[3] == 0)
723                         tprints("NULL");
724                 else {
725 #ifdef HAVE_SYS_EPOLL_H
726                         struct epoll_event ev;
727                         if (umove(tcp, tcp->u_arg[3], &ev) == 0)
728                                 print_epoll_event(&ev);
729                         else
730 #endif
731                                 tprints("{...}");
732                 }
733         }
734         return 0;
735 }
736
737 static void
738 epoll_wait_common(struct tcb *tcp)
739 {
740         if (entering(tcp)) {
741                 printfd(tcp, tcp->u_arg[0]);
742                 tprints(", ");
743         } else {
744                 if (syserror(tcp))
745                         tprintf("%lx", tcp->u_arg[1]);
746                 else if (tcp->u_rval == 0)
747                         tprints("{}");
748                 else {
749 #ifdef HAVE_SYS_EPOLL_H
750                         struct epoll_event ev, *start, *cur, *end;
751                         int failed = 0;
752
753                         tprints("{");
754                         start = (struct epoll_event *) tcp->u_arg[1];
755                         end = start + tcp->u_rval;
756                         for (cur = start; cur < end; ++cur) {
757                                 if (cur > start)
758                                         tprints(", ");
759                                 if (umove(tcp, (long) cur, &ev) == 0)
760                                         print_epoll_event(&ev);
761                                 else {
762                                         tprints("?");
763                                         failed = 1;
764                                         break;
765                                 }
766                         }
767                         tprints("}");
768                         if (failed)
769                                 tprintf(" %#lx", (long) start);
770 #else
771                         tprints("{...}");
772 #endif
773                 }
774                 tprintf(", %d, %d", (int) tcp->u_arg[2], (int) tcp->u_arg[3]);
775         }
776 }
777
778 int
779 sys_epoll_wait(struct tcb *tcp)
780 {
781         epoll_wait_common(tcp);
782         return 0;
783 }
784
785 int
786 sys_epoll_pwait(struct tcb *tcp)
787 {
788         epoll_wait_common(tcp);
789         if (exiting(tcp)) {
790                 tprints(", ");
791                 print_sigset(tcp, tcp->u_arg[4], 0);
792         }
793         return 0;
794 }
795
796 int
797 sys_io_setup(struct tcb *tcp)
798 {
799         if (entering(tcp))
800                 tprintf("%ld, ", tcp->u_arg[0]);
801         else {
802                 if (syserror(tcp))
803                         tprintf("0x%0lx", tcp->u_arg[1]);
804                 else {
805                         unsigned long user_id;
806                         if (umove(tcp, tcp->u_arg[1], &user_id) == 0)
807                                 tprintf("{%lu}", user_id);
808                         else
809                                 tprints("{...}");
810                 }
811         }
812         return 0;
813 }
814
815 int
816 sys_io_destroy(struct tcb *tcp)
817 {
818         if (entering(tcp))
819                 tprintf("%lu", tcp->u_arg[0]);
820         return 0;
821 }
822
823 #ifdef HAVE_LIBAIO_H
824
825 enum iocb_sub {
826         SUB_NONE, SUB_COMMON, SUB_POLL, SUB_VECTOR
827 };
828
829 static const char *
830 iocb_cmd_lookup(unsigned cmd, enum iocb_sub *sub)
831 {
832         static char buf[sizeof("%u /* SUB_??? */") + sizeof(int)*3];
833         static const struct {
834                 const char *name;
835                 enum iocb_sub sub;
836         } cmds[] = {
837                 { "pread", SUB_COMMON },
838                 { "pwrite", SUB_COMMON },
839                 { "fsync", SUB_NONE },
840                 { "fdsync", SUB_NONE },
841                 { "op4", SUB_NONE },
842                 { "poll", SUB_POLL },
843                 { "noop", SUB_NONE },
844                 { "preadv", SUB_VECTOR },
845                 { "pwritev", SUB_VECTOR },
846         };
847
848         if (cmd < ARRAY_SIZE(cmds)) {
849                 *sub = cmds[cmd].sub;
850                 return cmds[cmd].name;
851         }
852         *sub = SUB_NONE;
853         sprintf(buf, "%u /* SUB_??? */", cmd);
854         return buf;
855 }
856
857 /* Not defined in libaio.h */
858 #ifndef IOCB_RESFD
859 # define IOCB_RESFD (1 << 0)
860 #endif
861
862 static void
863 print_common_flags(struct iocb *iocb)
864 {
865         if (iocb->u.c.flags & IOCB_RESFD)
866                 tprintf("resfd=%d, ", iocb->u.c.resfd);
867         if (iocb->u.c.flags & ~IOCB_RESFD)
868                 tprintf("flags=%x, ", iocb->u.c.flags);
869 }
870
871 #endif /* HAVE_LIBAIO_H */
872
873 int
874 sys_io_submit(struct tcb *tcp)
875 {
876         long nr;
877         if (entering(tcp)) {
878                 tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]);
879                 nr = tcp->u_arg[1];
880                 /* and if nr is negative? */
881                 if (nr == 0)
882                         tprints("{}");
883                 else {
884 #ifdef HAVE_LIBAIO_H
885                         long i;
886                         struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2];
887
888                         for (i = 0; i < nr; i++, iocbs++) {
889                                 enum iocb_sub sub;
890                                 struct iocb iocb;
891                                 if (i == 0)
892                                         tprints("{");
893                                 else
894                                         tprints(", ");
895
896                                 if (umove(tcp, (unsigned long)iocbs, &iocbp) ||
897                                     umove(tcp, (unsigned long)iocbp, &iocb)) {
898                                         tprints("{...}");
899                                         continue;
900                                 }
901                                 tprints("{");
902                                 if (iocb.data)
903                                         tprintf("data:%p, ", iocb.data);
904                                 if (iocb.key)
905                                         tprintf("key:%u, ", iocb.key);
906                                 tprintf("%s, ", iocb_cmd_lookup(iocb.aio_lio_opcode, &sub));
907                                 if (iocb.aio_reqprio)
908                                         tprintf("reqprio:%d, ", iocb.aio_reqprio);
909                                 tprintf("filedes:%d", iocb.aio_fildes);
910                                 switch (sub) {
911                                 case SUB_COMMON:
912                                         if (iocb.aio_lio_opcode == IO_CMD_PWRITE) {
913                                                 tprints(", str:");
914                                                 printstr(tcp, (unsigned long)iocb.u.c.buf,
915                                                          iocb.u.c.nbytes);
916                                         } else {
917                                                 tprintf(", buf:%p", iocb.u.c.buf);
918                                         }
919                                         tprintf(", nbytes:%lu, offset:%llx",
920                                                 iocb.u.c.nbytes,
921                                                 iocb.u.c.offset);
922                                         print_common_flags(&iocb);
923                                         break;
924                                 case SUB_VECTOR:
925                                         tprintf(", %llx, ", iocb.u.v.offset);
926                                         print_common_flags(&iocb);
927                                         tprint_iov(tcp, iocb.u.v.nr,
928                                                    (unsigned long)iocb.u.v.vec,
929                                                    iocb.aio_lio_opcode == IO_CMD_PWRITEV);
930                                         break;
931                                 case SUB_POLL:
932                                         tprintf(", %x", iocb.u.poll.events);
933                                         break;
934                                 case SUB_NONE:
935                                         break;
936                                 }
937                                 tprints("}");
938                         }
939                         if (i)
940                                 tprints("}");
941 #else
942 #warning "libaio-devel is not available => no io_submit decoding"
943                         tprintf("%#lx", tcp->u_arg[2]);
944 #endif
945                 }
946         }
947         return 0;
948 }
949
950 int
951 sys_io_cancel(struct tcb *tcp)
952 {
953         if (entering(tcp)) {
954 #ifdef HAVE_LIBAIO_H
955                 struct iocb iocb;
956 #endif
957                 tprintf("%lu, ", tcp->u_arg[0]);
958 #ifdef HAVE_LIBAIO_H
959                 if (umove(tcp, tcp->u_arg[1], &iocb) == 0) {
960                         tprintf("{%p, %u, %hu, %hu, %d}, ",
961                                 iocb.data, iocb.key,
962                                 iocb.aio_lio_opcode,
963                                 iocb.aio_reqprio, iocb.aio_fildes);
964                 } else
965 #endif
966                         tprints("{...}, ");
967         } else {
968                 if (tcp->u_rval < 0)
969                         tprints("{...}");
970                 else {
971 #ifdef HAVE_LIBAIO_H
972                         struct io_event event;
973                         if (umove(tcp, tcp->u_arg[2], &event) == 0)
974                                 tprintf("{%p, %p, %ld, %ld}",
975                                         event.data, event.obj,
976                                         event.res, event.res2);
977                         else
978 #endif
979                                 tprints("{...}");
980                 }
981         }
982         return 0;
983 }
984
985 int
986 sys_io_getevents(struct tcb *tcp)
987 {
988         if (entering(tcp)) {
989                 tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1],
990                         tcp->u_arg[2]);
991         } else {
992                 if (tcp->u_rval == 0) {
993                         tprints("{}");
994                 } else  {
995 #ifdef HAVE_LIBAIO_H
996                         struct io_event *events = (void *)tcp->u_arg[3];
997                         long i, nr = tcp->u_rval;
998
999                         for (i = 0; i < nr; i++, events++) {
1000                                 struct io_event event;
1001
1002                                 if (i == 0)
1003                                         tprints("{");
1004                                 else
1005                                         tprints(", ");
1006
1007                                 if (umove(tcp, (unsigned long)events, &event) != 0) {
1008                                         tprints("{...}");
1009                                         continue;
1010                                 }
1011                                 tprintf("{%p, %p, %ld, %ld}", event.data,
1012                                         event.obj, event.res, event.res2);
1013                         }
1014                         tprints("}, ");
1015 #else
1016                                 tprints("{...}");
1017 #endif
1018                 }
1019
1020                 print_timespec(tcp, tcp->u_arg[4]);
1021         }
1022         return 0;
1023 }
1024
1025 int
1026 sys_select(struct tcb *tcp)
1027 {
1028         return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
1029 }
1030
1031 int
1032 sys_pselect6(struct tcb *tcp)
1033 {
1034         int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT);
1035         if (entering(tcp)) {
1036                 struct {
1037                         void *ss;
1038                         unsigned long len;
1039                 } data;
1040                 if (umove(tcp, tcp->u_arg[5], &data) < 0)
1041                         tprintf(", %#lx", tcp->u_arg[5]);
1042                 else {
1043                         tprints(", {");
1044                         if (data.len < sizeof(long))
1045                                 tprintf("%#lx", (long)data.ss);
1046                         else
1047                                 print_sigset(tcp, (long)data.ss, 0);
1048                         tprintf(", %lu}", data.len);
1049                 }
1050         }
1051         return rc;
1052 }
1053
1054 static int
1055 do_eventfd(struct tcb *tcp, int flags_arg)
1056 {
1057         if (entering(tcp)) {
1058                 tprintf("%lu", tcp->u_arg[0]);
1059                 if (flags_arg >= 0) {
1060                         tprints(", ");
1061                         printflags(open_mode_flags, tcp->u_arg[flags_arg], "O_???");
1062                 }
1063         }
1064         return 0;
1065 }
1066
1067 int
1068 sys_eventfd(struct tcb *tcp)
1069 {
1070         return do_eventfd(tcp, -1);
1071 }
1072
1073 int
1074 sys_eventfd2(struct tcb *tcp)
1075 {
1076         return do_eventfd(tcp, 1);
1077 }