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