desc.c revision f240005701067569f9a9c97d9b01cdaba247c56a
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#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 56static 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 154static 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 163static 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 173static 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 186static 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 */ 195static void 196printflock(tcp, addr, getlk) 197struct tcb *tcp; 198long addr; 199int 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 */ 221static void 222printflock64(tcp, addr, getlk) 223struct tcb *tcp; 224long addr; 225int 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 245static const char * 246sprintflags(const struct xlat *xlat, int flags) 247{ 248 static char outstr[1024]; 249 const char *sep; 250 251 strcpy(outstr, "flags "); 252 sep = ""; 253 for (; xlat->str; xlat++) { 254 if ((flags & xlat->val) == xlat->val) { 255 sprintf(outstr + strlen(outstr), 256 "%s%s", sep, xlat->str); 257 sep = "|"; 258 flags &= ~xlat->val; 259 } 260 } 261 if (flags) 262 sprintf(outstr + strlen(outstr), 263 "%s%#x", sep, flags); 264 return outstr; 265} 266 267/* 268 * low bits of the open(2) flags define access mode, 269 * other bits are real flags. 270 */ 271static const char * 272sprint_open_modes(mode_t flags) 273{ 274 extern const struct xlat open_access_modes[]; 275 extern const struct xlat open_mode_flags[]; 276 static char outstr[1024]; 277 const char *str = xlookup(open_access_modes, flags & 3); 278 const char *sep = ""; 279 const struct xlat *x; 280 281 strcpy(outstr, "flags "); 282 if (str) 283 { 284 strcat(outstr, str); 285 flags &= ~3; 286 if (!flags) 287 return outstr; 288 strcat(outstr, "|"); 289 } 290 291 for (x = open_mode_flags; x->str; x++) 292 { 293 if ((flags & x->val) == x->val) 294 { 295 sprintf(outstr + strlen(outstr), 296 "%s%s", sep, x->str); 297 sep = "|"; 298 flags &= ~x->val; 299 } 300 } 301 if (flags) 302 sprintf(outstr + strlen(outstr), "%s%#x", sep, flags); 303 return outstr; 304} 305 306int 307sys_fcntl(struct tcb *tcp) 308{ 309 if (entering(tcp)) { 310 tprintf("%ld, ", tcp->u_arg[0]); 311 printxval(fcntlcmds, tcp->u_arg[1], "F_???"); 312 switch (tcp->u_arg[1]) { 313 case F_SETFD: 314 tprintf(", "); 315 printflags(fdflags, tcp->u_arg[2], "FD_???"); 316 break; 317 case F_SETOWN: case F_DUPFD: 318 tprintf(", %ld", tcp->u_arg[2]); 319 break; 320 case F_SETFL: 321 tprintf(", "); 322 tprint_open_modes(tcp, tcp->u_arg[2]); 323 break; 324 case F_SETLK: case F_SETLKW: 325#ifdef F_FREESP 326 case F_FREESP: 327#endif 328 tprintf(", "); 329 printflock(tcp, tcp->u_arg[2], 0); 330 break; 331#if _LFS64_LARGEFILE 332#ifdef F_FREESP64 333 case F_FREESP64: 334#endif 335 /* Linux glibc defines SETLK64 as SETLK, 336 even though the kernel has different values - as does Solaris. */ 337#if defined(F_SETLK64) && F_SETLK64+0!=F_SETLK 338 case F_SETLK64: 339#endif 340#if defined(F_SETLKW64) && F_SETLKW64+0!=F_SETLKW 341 case F_SETLKW64: 342#endif 343 tprintf(", "); 344 printflock64(tcp, tcp->u_arg[2], 0); 345 break; 346#endif 347 } 348 } 349 else { 350 switch (tcp->u_arg[1]) { 351 case F_DUPFD: 352 case F_SETFD: case F_SETFL: 353 case F_SETLK: case F_SETLKW: 354 case F_SETOWN: case F_GETOWN: 355 break; 356 case F_GETFD: 357 if (tcp->u_rval == 0) 358 return 0; 359 tcp->auxstr = sprintflags(fdflags, tcp->u_rval); 360 return RVAL_HEX|RVAL_STR; 361 case F_GETFL: 362 tcp->auxstr = sprint_open_modes(tcp->u_rval); 363 return RVAL_HEX|RVAL_STR; 364 case F_GETLK: 365 tprintf(", "); 366 printflock(tcp, tcp->u_arg[2], 1); 367 break; 368#if _LFS64_LARGEFILE 369#if defined(F_GETLK64) && F_GETLK64+0!=F_GETLK 370 case F_GETLK64: 371#endif 372 tprintf(", "); 373 printflock64(tcp, tcp->u_arg[2], 1); 374 break; 375#endif 376 default: 377 tprintf(", %#lx", tcp->u_arg[2]); 378 break; 379 } 380 } 381 return 0; 382} 383 384#ifdef LOCK_SH 385 386int 387sys_flock(tcp) 388struct tcb *tcp; 389{ 390 if (entering(tcp)) { 391 tprintf("%ld, ", tcp->u_arg[0]); 392 printflags(flockcmds, tcp->u_arg[1], "LOCK_???"); 393 } 394 return 0; 395} 396#endif /* LOCK_SH */ 397 398int 399sys_close(tcp) 400struct tcb *tcp; 401{ 402 if (entering(tcp)) { 403 tprintf("%ld", tcp->u_arg[0]); 404 } 405 return 0; 406} 407 408int 409sys_dup(tcp) 410struct tcb *tcp; 411{ 412 if (entering(tcp)) { 413 tprintf("%ld", tcp->u_arg[0]); 414 } 415 return 0; 416} 417 418int 419sys_dup2(tcp) 420struct tcb *tcp; 421{ 422 if (entering(tcp)) { 423 tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]); 424 } 425 return 0; 426} 427 428#if defined(ALPHA) || defined(FREEBSD) || defined(SUNOS4) 429int 430sys_getdtablesize(tcp) 431struct tcb *tcp; 432{ 433 return 0; 434} 435#endif /* ALPHA || FREEBSD || SUNOS4 */ 436 437static int 438decode_select(struct tcb *tcp, long *args, enum bitness_t bitness) 439{ 440 int i, j, nfds; 441 unsigned int fdsize = ((((args[0] + 7) / 8) + sizeof(long) - 1) 442 & -sizeof(long)); 443 fd_set *fds; 444 static char outstr[1024]; 445 char *sep; 446 long arg; 447 448 if (entering(tcp)) { 449 fds = (fd_set *) malloc(fdsize); 450 if (fds == NULL) 451 fprintf(stderr, "out of memory\n"); 452 nfds = args[0]; 453 tprintf("%d", nfds); 454 for (i = 0; i < 3; i++) { 455 arg = args[i+1]; 456 if (arg == 0) { 457 tprintf(", NULL"); 458 continue; 459 } 460 if (fds == NULL || !verbose(tcp)) { 461 tprintf(", %#lx", arg); 462 continue; 463 } 464 if (umoven(tcp, arg, fdsize, (char *) fds) < 0) { 465 tprintf(", [?]"); 466 continue; 467 } 468 tprintf(", ["); 469 for (j = 0, sep = ""; j < nfds; j++) { 470 if (FD_ISSET(j, fds)) { 471 tprintf("%s%u", sep, j); 472 sep = " "; 473 } 474 } 475 tprintf("]"); 476 } 477 free(fds); 478 tprintf(", "); 479 printtv_bitness(tcp, args[4], bitness, 0); 480 } 481 else 482 { 483 unsigned int cumlen = 0; 484 char *sep = ""; 485 486 if (syserror(tcp)) 487 return 0; 488 489 if ((nfds = tcp->u_rval) == 0) { 490 tcp->auxstr = "Timeout"; 491 return RVAL_STR; 492 } 493 494 fds = (fd_set *) malloc(fdsize); 495 if (fds == NULL) 496 fprintf(stderr, "out of memory\n"); 497 498 outstr[0] = '\0'; 499 for (i = 0; i < 3; i++) { 500 int first = 1; 501 char str[20]; 502 503 tcp->auxstr = outstr; 504 arg = args[i+1]; 505 if (fds == NULL || !arg || 506 umoven(tcp, arg, fdsize, (char *) fds) < 0) 507 continue; 508 for (j = 0; j < args[0]; j++) { 509 if (FD_ISSET(j, fds)) { 510 if (first) { 511 sprintf(str, "%s%s [%u", sep, 512 i == 0 ? "in" : 513 i == 1 ? "out" : 514 "except", j); 515 first = 0; 516 sep = ", "; 517 } 518 else 519 sprintf(str, " %u", j); 520 cumlen += strlen(str); 521 if (cumlen < sizeof(outstr)) 522 strcat(outstr, str); 523 nfds--; 524 } 525 } 526 if (cumlen) 527 strcat(outstr, "]"); 528 if (nfds == 0) 529 break; 530 } 531 free(fds); 532#ifdef LINUX 533 /* This contains no useful information on SunOS. */ 534 if (args[4]) { 535 char str[128]; 536 537 sprintf(str, "%sleft ", sep); 538 sprinttv(tcp, args[4], bitness, str + strlen(str)); 539 if ((cumlen += strlen(str)) < sizeof(outstr)) 540 strcat(outstr, str); 541 } 542#endif /* LINUX */ 543 return RVAL_STR; 544 } 545 return 0; 546} 547 548#ifdef LINUX 549 550int 551sys_oldselect(tcp) 552struct tcb *tcp; 553{ 554 long args[5]; 555 556 if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) { 557 tprintf("[...]"); 558 return 0; 559 } 560 return decode_select(tcp, args, BITNESS_CURRENT); 561} 562 563#ifdef ALPHA 564int 565sys_osf_select(tcp) 566struct tcb *tcp; 567{ 568 long *args = tcp->u_arg; 569 return decode_select(tcp, args, BITNESS_32); 570} 571#endif 572 573static struct xlat epollctls[] = { 574#ifdef EPOLL_CTL_ADD 575 { EPOLL_CTL_ADD, "EPOLL_CTL_ADD" }, 576#endif 577#ifdef EPOLL_CTL_MOD 578 { EPOLL_CTL_MOD, "EPOLL_CTL_MOD" }, 579#endif 580#ifdef EPOLL_CTL_DEL 581 { EPOLL_CTL_DEL, "EPOLL_CTL_DEL" }, 582#endif 583 { 0, NULL } 584}; 585 586static struct xlat epollevents[] = { 587#ifdef EPOLLIN 588 { EPOLLIN, "EPOLLIN" }, 589#endif 590#ifdef EPOLLPRI 591 { EPOLLPRI, "EPOLLPRI" }, 592#endif 593#ifdef EPOLLOUT 594 { EPOLLOUT, "EPOLLOUT" }, 595#endif 596#ifdef EPOLLRDNORM 597 { EPOLLRDNORM, "EPOLLRDNORM" }, 598#endif 599#ifdef EPOLLRDBAND 600 { EPOLLRDBAND, "EPOLLRDBAND" }, 601#endif 602#ifdef EPOLLWRNORM 603 { EPOLLWRNORM, "EPOLLWRNORM" }, 604#endif 605#ifdef EPOLLWRBAND 606 { EPOLLWRBAND, "EPOLLWRBAND" }, 607#endif 608#ifdef EPOLLMSG 609 { EPOLLMSG, "EPOLLMSG" }, 610#endif 611#ifdef EPOLLERR 612 { EPOLLERR, "EPOLLERR" }, 613#endif 614#ifdef EPOLLHUP 615 { EPOLLHUP, "EPOLLHUP" }, 616#endif 617#ifdef EPOLLONESHOT 618 { EPOLLONESHOT, "EPOLLONESHOT" }, 619#endif 620#ifdef EPOLLET 621 { EPOLLET, "EPOLLET" }, 622#endif 623 { 0, NULL } 624}; 625 626int 627sys_epoll_create(tcp) 628struct tcb *tcp; 629{ 630 if (entering(tcp)) 631 tprintf("%ld", tcp->u_arg[0]); 632 return 0; 633} 634 635#ifdef HAVE_SYS_EPOLL_H 636static void 637print_epoll_event(ev) 638struct epoll_event *ev; 639{ 640 tprintf("{"); 641 printflags(epollevents, ev->events, "EPOLL???"); 642 /* We cannot know what format the program uses, so print u32 and u64 643 which will cover every value. */ 644 tprintf(", {u32=%" PRIu32 ", u64=%" PRIu64 "}}", 645 ev->data.u32, ev->data.u64); 646} 647#endif 648 649int 650sys_epoll_ctl(tcp) 651struct tcb *tcp; 652{ 653 if (entering(tcp)) { 654 tprintf("%ld, ", tcp->u_arg[0]); 655 printxval(epollctls, tcp->u_arg[1], "EPOLL_CTL_???"); 656 tprintf(", %ld, ", tcp->u_arg[2]); 657 if (tcp->u_arg[3] == 0) 658 tprintf("NULL"); 659 else { 660#ifdef HAVE_SYS_EPOLL_H 661 struct epoll_event ev; 662 if (umove(tcp, tcp->u_arg[3], &ev) == 0) 663 print_epoll_event(&ev); 664 else 665#endif 666 tprintf("{...}"); 667 } 668 } 669 return 0; 670} 671 672static void 673epoll_wait_common(tcp) 674struct tcb *tcp; 675{ 676 if (entering(tcp)) 677 tprintf("%ld, ", tcp->u_arg[0]); 678 else { 679 if (syserror(tcp)) 680 tprintf("%lx", tcp->u_arg[1]); 681 else if (tcp->u_rval == 0) 682 tprintf("{}"); 683 else { 684#ifdef HAVE_SYS_EPOLL_H 685 struct epoll_event ev, *start, *cur, *end; 686 int failed = 0; 687 688 tprintf("{"); 689 start = (struct epoll_event *) tcp->u_arg[1]; 690 end = start + tcp->u_rval; 691 for (cur = start; cur < end; ++cur) { 692 if (cur > start) 693 tprintf(", "); 694 if (umove(tcp, (long) cur, &ev) == 0) 695 print_epoll_event(&ev); 696 else { 697 tprintf("?"); 698 failed = 1; 699 break; 700 } 701 } 702 tprintf("}"); 703 if (failed) 704 tprintf(" %#lx", (long) start); 705#else 706 tprintf("{...}"); 707#endif 708 } 709 tprintf(", %ld, %ld", tcp->u_arg[2], tcp->u_arg[3]); 710 } 711} 712 713int 714sys_epoll_wait(tcp) 715struct tcb *tcp; 716{ 717 epoll_wait_common(tcp); 718 return 0; 719} 720 721int 722sys_epoll_pwait(tcp) 723struct tcb *tcp; 724{ 725 epoll_wait_common(tcp); 726 if (exiting(tcp)) 727 print_sigset(tcp, tcp->u_arg[4], 0); 728 return 0; 729} 730 731int 732sys_io_setup(tcp) 733struct tcb *tcp; 734{ 735 if (entering(tcp)) 736 tprintf("%ld, ", tcp->u_arg[0]); 737 else { 738 if (syserror(tcp)) 739 tprintf("0x%0lx", tcp->u_arg[1]); 740 else { 741 unsigned long user_id; 742 if (umove(tcp, tcp->u_arg[1], &user_id) == 0) 743 tprintf("{%lu}", user_id); 744 else 745 tprintf("{...}"); 746 } 747 } 748 return 0; 749} 750 751int 752sys_io_destroy(tcp) 753struct tcb *tcp; 754{ 755 if (entering(tcp)) 756 tprintf("%lu", tcp->u_arg[0]); 757 return 0; 758} 759 760int 761sys_io_submit(tcp) 762struct tcb *tcp; 763{ 764 long nr; 765 if (entering(tcp)) { 766 tprintf("%lu, %ld, ", tcp->u_arg[0], tcp->u_arg[1]); 767 nr = tcp->u_arg[1]; 768 /* and if nr is negative? */ 769 if (nr == 0) 770 tprintf("{}"); 771 else { 772#ifdef HAVE_LIBAIO_H 773 long i; 774 struct iocb *iocbp, **iocbs = (void *)tcp->u_arg[2]; 775 776 for (i = 0; i < nr; i++, iocbs++) { 777 struct iocb iocb; 778 if (i == 0) 779 tprintf("{"); 780 else 781 tprintf(", "); 782 783 if (umove(tcp, (unsigned long)iocbs, &iocbp) || 784 umove(tcp, (unsigned long)iocbp, &iocb)) { 785 tprintf("{...}"); 786 continue; 787 } 788 tprintf("{%p, %u, %hu, %hu, %d}", 789 iocb.data, iocb.key, 790 iocb.aio_lio_opcode, 791 iocb.aio_reqprio, iocb.aio_fildes); 792 } 793 if (i) 794 tprintf("}"); 795#else 796 tprintf("{...}"); 797#endif 798 } 799 } 800 return 0; 801} 802 803int 804sys_io_cancel(tcp) 805struct tcb *tcp; 806{ 807 if (entering(tcp)) { 808#ifdef HAVE_LIBAIO_H 809 struct iocb iocb; 810#endif 811 tprintf("%lu, ", tcp->u_arg[0]); 812#ifdef HAVE_LIBAIO_H 813 if (umove(tcp, tcp->u_arg[1], &iocb) == 0) { 814 tprintf("{%p, %u, %hu, %hu, %d}, ", 815 iocb.data, iocb.key, 816 iocb.aio_lio_opcode, 817 iocb.aio_reqprio, iocb.aio_fildes); 818 } else 819#endif 820 tprintf("{...}, "); 821 } else { 822 if (tcp->u_rval < 0) 823 tprintf("{...}"); 824 else { 825#ifdef HAVE_LIBAIO_H 826 struct io_event event; 827 if (umove(tcp, tcp->u_arg[2], &event) == 0) 828 tprintf("{%p, %p, %ld, %ld}", 829 event.data, event.obj, 830 event.res, event.res2); 831 else 832#endif 833 tprintf("{...}"); 834 } 835 } 836 return 0; 837} 838 839int 840sys_io_getevents(tcp) 841struct tcb *tcp; 842{ 843 if (entering(tcp)) { 844 tprintf("%ld, %ld, %ld, ", tcp->u_arg[0], tcp->u_arg[1], 845 tcp->u_arg[2]); 846 } else { 847 if (tcp->u_rval == 0) { 848 tprintf("{}"); 849 } else { 850#ifdef HAVE_LIBAIO_H 851 struct io_event *events = (void *)tcp->u_arg[3]; 852 long i, nr = tcp->u_rval; 853 854 for (i = 0; i < nr; i++, events++) { 855 struct io_event event; 856 857 if (i == 0) 858 tprintf("{"); 859 else 860 tprintf(", "); 861 862 if (umove(tcp, (unsigned long)events, &event) != 0) { 863 tprintf("{...}"); 864 continue; 865 } 866 tprintf("{%p, %p, %ld, %ld}", event.data, 867 event.obj, event.res, event.res2); 868 } 869 tprintf("}, "); 870#else 871 tprintf("{...}"); 872#endif 873 } 874 875 if (tcp->u_arg[4] == 0) 876 tprintf("NULL"); 877 else { 878 struct timespec to; 879 if (umove(tcp, tcp->u_arg[4], &to) == 0) 880 tprintf("{%lu, %lu}", to.tv_sec, to.tv_nsec); 881 else 882 tprintf("{...}"); 883 } 884 } 885 return 0; 886} 887#endif /* LINUX */ 888 889int 890sys_select(tcp) 891struct tcb *tcp; 892{ 893 return decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 894} 895 896#ifdef LINUX 897int 898sys_pselect6(struct tcb *tcp) 899{ 900 int rc = decode_select(tcp, tcp->u_arg, BITNESS_CURRENT); 901 if (exiting(tcp)) { 902 struct { 903 void *ss; 904 unsigned long len; 905 } data; 906 if (umove(tcp, tcp->u_arg[5], &data) < 0) 907 tprintf(", %#lx", tcp->u_arg[5]); 908 else { 909 tprintf(", {"); 910 if (data.len < sizeof(sigset_t)) 911 tprintf("%#lx", (long)data.ss); 912 else 913 print_sigset(tcp, (long)data.ss, 0); 914 tprintf(", %lu}", data.len); 915 } 916 } 917 return rc; 918} 919#endif 920