desc.c revision 7b3346be42d6a1f539e95d385ee498f8b3c529f8
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 38#if HAVE_LONG_LONG_OFF_T 39/* 40 * Hacks for systems that have a long long off_t 41 */ 42#define flock64 flock /* Horrid hack */ 43#define printflock printflock64 /* Horrider hack */ 44#endif 45 46 47static struct xlat fcntlcmds[] = { 48 { F_DUPFD, "F_DUPFD" }, 49 { F_GETFD, "F_GETFD" }, 50 { F_SETFD, "F_SETFD" }, 51 { F_GETFL, "F_GETFL" }, 52 { F_SETFL, "F_SETFL" }, 53 { F_GETLK, "F_GETLK" }, 54 { F_SETLK, "F_SETLK" }, 55 { F_SETLKW, "F_SETLKW" }, 56 { F_GETOWN, "F_GETOWN" }, 57 { F_SETOWN, "F_SETOWN" }, 58#ifdef F_RSETLK 59 { F_RSETLK, "F_RSETLK" }, 60#endif 61#ifdef F_RSETLKW 62 { F_RSETLKW, "F_RSETLKW" }, 63#endif 64#ifdef F_RGETLK 65 { F_RGETLK, "F_RGETLK" }, 66#endif 67#ifdef F_CNVT 68 { F_CNVT, "F_CNVT" }, 69#endif 70#ifdef F_SETSIG 71 { F_SETSIG, "F_SETSIG" }, 72#endif 73#ifdef F_GETSIG 74 { F_GETSIG, "F_GETSIG" }, 75#endif 76#ifdef F_CHKFL 77 { F_CHKFL, "F_CHKFL" }, 78#endif 79#ifdef F_DUP2FD 80 { F_DUP2FD, "F_DUP2FD" }, 81#endif 82#ifdef F_ALLOCSP 83 { F_ALLOCSP, "F_ALLOCSP" }, 84#endif 85#ifdef F_ISSTREAM 86 { F_ISSTREAM, "F_ISSTREAM" }, 87#endif 88#ifdef F_PRIV 89 { F_PRIV, "F_PRIV" }, 90#endif 91#ifdef F_NPRIV 92 { F_NPRIV, "F_NPRIV" }, 93#endif 94#ifdef F_QUOTACL 95 { F_QUOTACL, "F_QUOTACL" }, 96#endif 97#ifdef F_BLOCKS 98 { F_BLOCKS, "F_BLOCKS" }, 99#endif 100#ifdef F_BLKSIZE 101 { F_BLKSIZE, "F_BLKSIZE" }, 102#endif 103#ifdef F_GETOWN 104 { F_GETOWN, "F_GETOWN" }, 105#endif 106#ifdef F_SETOWN 107 { F_SETOWN, "F_SETOWN" }, 108#endif 109#ifdef F_REVOKE 110 { F_REVOKE, "F_REVOKE" }, 111#endif 112#ifdef F_SETLK 113 { F_SETLK, "F_SETLK" }, 114#endif 115#ifdef F_SETLKW 116 { F_SETLKW, "F_SETLKW" }, 117#endif 118#ifdef F_FREESP 119 { F_FREESP, "F_FREESP" }, 120#endif 121#ifdef F_GETLK 122 { F_GETLK, "F_GETLK" }, 123#endif 124#ifdef F_SETLK64 125 { F_SETLK64, "F_SETLK64" }, 126#endif 127#ifdef F_SETLKW64 128 { F_SETLKW64, "F_SETLKW64" }, 129#endif 130#ifdef F_FREESP64 131 { F_FREESP64, "F_FREESP64" }, 132#endif 133#ifdef F_GETLK64 134 { F_GETLK64, "F_GETLK64" }, 135#endif 136#ifdef F_SHARE 137 { F_SHARE, "F_SHARE" }, 138#endif 139#ifdef F_UNSHARE 140 { F_UNSHARE, "F_UNSHARE" }, 141#endif 142 { 0, NULL }, 143}; 144 145static struct xlat fdflags[] = { 146#ifdef FD_CLOEXEC 147 { FD_CLOEXEC, "FD_CLOEXEC" }, 148#endif 149 { 0, NULL }, 150}; 151 152#ifdef LOCK_SH 153 154static struct xlat flockcmds[] = { 155 { LOCK_SH, "LOCK_SH" }, 156 { LOCK_EX, "LOCK_EX" }, 157 { LOCK_NB, "LOCK_NB" }, 158 { LOCK_UN, "LOCK_UN" }, 159 { 0, NULL }, 160}; 161 162#endif /* LOCK_SH */ 163 164static struct xlat lockfcmds[] = { 165 { F_RDLCK, "F_RDLCK" }, 166 { F_WRLCK, "F_WRLCK" }, 167 { F_UNLCK, "F_UNLCK" }, 168#ifdef F_EXLCK 169 { F_EXLCK, "F_EXLCK" }, 170#endif 171#ifdef F_SHLCK 172 { F_SHLCK, "F_SHLCK" }, 173#endif 174 { 0, NULL }, 175}; 176 177static struct xlat whence[] = { 178 { SEEK_SET, "SEEK_SET" }, 179 { SEEK_CUR, "SEEK_CUR" }, 180 { SEEK_END, "SEEK_END" }, 181 { 0, NULL }, 182}; 183 184#ifndef HAVE_LONG_LONG_OFF_T 185/* fcntl/lockf */ 186static void 187printflock(tcp, addr, getlk) 188struct tcb *tcp; 189long addr; 190int getlk; 191{ 192 struct flock fl; 193 194 if (umove(tcp, addr, &fl) < 0) { 195 tprintf("{...}"); 196 return; 197 } 198 tprintf("{type="); 199 printxval(lockfcmds, fl.l_type, "F_???"); 200 tprintf(", whence="); 201 printxval(whence, fl.l_whence, "SEEK_???"); 202 tprintf(", start=%ld, len=%ld", fl.l_start, fl.l_len); 203 if (getlk) 204 tprintf(", pid=%lu}", (unsigned long) fl.l_pid); 205 else 206 tprintf("}"); 207} 208#endif 209 210#if _LFS64_LARGEFILE || HAVE_LONG_LONG_OFF_T 211/* fcntl/lockf */ 212static void 213printflock64(tcp, addr, getlk) 214struct tcb *tcp; 215int addr; 216int getlk; 217{ 218 struct flock64 fl; 219 220 if (umove(tcp, addr, &fl) < 0) { 221 tprintf("{...}"); 222 return; 223 } 224 tprintf("{type="); 225 printxval(lockfcmds, fl.l_type, "F_???"); 226 tprintf(", whence="); 227 printxval(whence, fl.l_whence, "SEEK_???"); 228 tprintf(", start=%lld, len=%lld", (long long) fl.l_start, (long long) fl.l_len); 229 if (getlk) 230 tprintf(", pid=%lu}", (unsigned long) fl.l_pid); 231 else 232 tprintf("}"); 233} 234#endif 235 236static char * 237sprintflags(xlat, flags) 238struct xlat *xlat; 239int flags; 240{ 241 static char outstr[1024]; 242 char *sep; 243 244 strcpy(outstr, "flags "); 245 sep = ""; 246 for (; xlat->str; xlat++) { 247 if ((flags & xlat->val) == xlat->val) { 248 sprintf(outstr + strlen(outstr), 249 "%s%s", sep, xlat->str); 250 sep = "|"; 251 flags &= ~xlat->val; 252 } 253 } 254 if (flags) 255 sprintf(outstr + strlen(outstr), 256 "%s%#x", sep, flags); 257 return outstr; 258} 259 260int 261sys_fcntl(tcp) 262struct tcb *tcp; 263{ 264 extern struct xlat openmodes[]; 265 266 if (entering(tcp)) { 267 tprintf("%ld, ", tcp->u_arg[0]); 268 printxval(fcntlcmds, tcp->u_arg[1], "F_???"); 269 switch (tcp->u_arg[1]) { 270 case F_SETFD: 271 tprintf(", "); 272 if (printflags(fdflags, tcp->u_arg[2]) == 0) 273 tprintf("0"); 274 break; 275 case F_SETOWN: case F_DUPFD: 276 tprintf(", %ld", tcp->u_arg[2]); 277 break; 278 case F_SETFL: 279 tprintf(", "); 280 if (printflags(openmodes, tcp->u_arg[2] + 1) == 0) 281 tprintf("0"); 282 break; 283 case F_SETLK: case F_SETLKW: 284#ifdef F_FREESP 285 case F_FREESP: 286#endif 287 tprintf(", "); 288 printflock(tcp, tcp->u_arg[2], 0); 289 break; 290#if _LFS64_LARGEFILE 291#ifdef F_FREESP64 292 case F_FREESP64: 293#endif 294 /* Linux glibc defines SETLK64 as SETLK, 295 even though the kernel has different values - as does Solaris. */ 296#if defined(F_SETLK64) && F_SETLK64+0!=F_SETLK 297 case F_SETLK64: 298#endif 299#if defined(F_SETLKW64) && F_SETLKW64+0!=F_SETLKW 300 case F_SETLKW64: 301#endif 302 tprintf(", "); 303 printflock64(tcp, tcp->u_arg[2], 0); 304 break; 305#endif 306 } 307 } 308 else { 309 switch (tcp->u_arg[1]) { 310 case F_DUPFD: 311 case F_SETFD: case F_SETFL: 312 case F_SETLK: case F_SETLKW: 313 case F_SETOWN: case F_GETOWN: 314 break; 315 case F_GETFD: 316 if (tcp->u_rval == 0) 317 return 0; 318 tcp->auxstr = sprintflags(fdflags, tcp->u_rval); 319 return RVAL_HEX|RVAL_STR; 320 case F_GETFL: 321 tcp->auxstr = sprintflags(openmodes, tcp->u_rval + 1); 322 return RVAL_HEX|RVAL_STR; 323 case F_GETLK: 324 tprintf(", "); 325 printflock(tcp, tcp->u_arg[2], 1); 326 break; 327#if _LFS64_LARGEFILE 328#if defined(F_GETLK64) && F_GETLK64+0!=F_GETLK 329 case F_GETLK64: 330#endif 331 tprintf(", "); 332 printflock64(tcp, tcp->u_arg[2], 1); 333 break; 334#endif 335 default: 336 tprintf(", %#lx", tcp->u_arg[2]); 337 break; 338 } 339 } 340 return 0; 341} 342 343#ifdef LOCK_SH 344 345int 346sys_flock(tcp) 347struct tcb *tcp; 348{ 349 if (entering(tcp)) { 350 tprintf("%ld, ", tcp->u_arg[0]); 351 if (!printflags(flockcmds, tcp->u_arg[1])) 352 tprintf("LOCK_???"); 353 } 354 return 0; 355} 356#endif /* LOCK_SH */ 357 358int 359sys_close(tcp) 360struct tcb *tcp; 361{ 362 if (entering(tcp)) { 363 tprintf("%ld", tcp->u_arg[0]); 364 } 365 return 0; 366} 367 368int 369sys_dup(tcp) 370struct tcb *tcp; 371{ 372 if (entering(tcp)) { 373 tprintf("%ld", tcp->u_arg[0]); 374 } 375 return 0; 376} 377 378int 379sys_dup2(tcp) 380struct tcb *tcp; 381{ 382 if (entering(tcp)) { 383 tprintf("%ld, %ld", tcp->u_arg[0], tcp->u_arg[1]); 384 } 385 return 0; 386} 387 388int 389sys_getdtablesize(tcp) 390struct tcb *tcp; 391{ 392 return 0; 393} 394 395static int 396decode_select(tcp, args, bitness) 397struct tcb *tcp; 398long *args; 399int bitness; 400{ 401 int i, j, nfds; 402 fd_set fds; 403 struct timeval tv; 404#ifdef ALPHA 405 struct timeval32 { 406 unsigned tv_sec; 407 unsigned tv_usec; 408 } *tv32; 409#endif 410 static char outstr[1024]; 411 char *sep; 412 long arg; 413 414 if (entering(tcp)) { 415 nfds = args[0]; 416 tprintf("%d", nfds); 417 for (i = 0; i < 3; i++) { 418 arg = args[i+1]; 419 if (arg == 0) { 420 tprintf(", NULL"); 421 continue; 422 } 423 if (!verbose(tcp)) { 424 tprintf(", %#lx", arg); 425 continue; 426 } 427 if (umove(tcp, arg, &fds) < 0) { 428 tprintf(", [?]"); 429 continue; 430 } 431 tprintf(", ["); 432 for (j = 0, sep = ""; j < nfds; j++) { 433 if (FD_ISSET(j, &fds)) { 434 tprintf("%s%u", sep, j); 435 sep = " "; 436 } 437 } 438 tprintf("]"); 439 } 440 if (!args[4]) 441 tprintf(", NULL"); 442 else if (!verbose(tcp)) 443 tprintf(", %#lx", args[4]); 444 else if (umove(tcp, args[4], &tv) < 0) 445 tprintf(", {...}"); 446 else { 447#ifdef ALPHA 448 if (bitness) { 449 tv32=(struct timeval32*)&tv; 450 tprintf(", {%u, %u}", tv32->tv_sec, tv32->tv_usec); 451 } else 452#endif 453 tprintf(", {%lu, %lu}", 454 (long) tv.tv_sec, (long) tv.tv_usec); 455 } 456 } 457 else 458 { 459 unsigned int cumlen = 0; 460 char *sep = ""; 461 462 if (syserror(tcp)) 463 return 0; 464 465 if ((nfds = tcp->u_rval) == 0) { 466 tcp->auxstr = "Timeout"; 467 return RVAL_STR; 468 } 469 outstr[0] = '\0'; 470 for (i = 0; i < 3; i++) { 471 int first = 1; 472 char str[20]; 473 474 tcp->auxstr = outstr; 475 arg = args[i+1]; 476 if (!arg || umove(tcp, arg, &fds) < 0) 477 continue; 478 for (j = 0; j < args[0]; j++) { 479 if (FD_ISSET(j, &fds)) { 480 if (first) { 481 sprintf(str, "%s%s [%u", sep, 482 i == 0 ? "in" : 483 i == 1 ? "out" : 484 "except", j); 485 first = 0; 486 sep = ", "; 487 } 488 else 489 sprintf(str, " %u", j); 490 cumlen += strlen(str); 491 if (cumlen < sizeof(outstr)) 492 strcat(outstr, str); 493 nfds--; 494 } 495 } 496 if (cumlen) 497 strcat(outstr, "]"); 498 if (nfds == 0) 499 break; 500 } 501#ifdef LINUX 502 /* This contains no useful information on SunOS. */ 503 if (args[4]) { 504 char str[20]; 505 506 if (umove(tcp, args[4], &tv) >= 0) { 507#ifdef ALPHA 508 if (bitness) { 509 tv32=(struct timeval32*)&tv; 510 sprintf(str, "%sleft {%u, %u}", sep, 511 tv32->tv_sec, tv32->tv_usec); 512 } else 513#endif 514 sprintf(str, "%sleft {%lu, %lu}", sep, 515 (long) tv.tv_sec, (long) tv.tv_usec); 516 517 if ((cumlen += strlen(str)) < sizeof(outstr)) 518 strcat(outstr, str); 519 } 520 } 521#endif /* LINUX */ 522 return RVAL_STR; 523 } 524 return 0; 525} 526 527#ifdef LINUX 528 529int 530sys_oldselect(tcp) 531struct tcb *tcp; 532{ 533 long args[5]; 534 535 if (umoven(tcp, tcp->u_arg[0], sizeof args, (char *) args) < 0) { 536 tprintf("[...]"); 537 return 0; 538 } 539 return decode_select(tcp, args, 0); 540} 541 542#ifdef ALPHA 543sys_osf_select(tcp) 544struct tcb *tcp; 545{ 546 long *args = tcp->u_arg; 547 return decode_select(tcp, args, 1); 548} 549#endif 550 551#endif /* LINUX */ 552 553int 554sys_select(tcp) 555struct tcb *tcp; 556{ 557 long *args = tcp->u_arg; 558 return decode_select(tcp, args, 0); 559} 560