1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. The name of the author may not be used to endorse or promote products 16 * derived from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 21 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * $Id: time.c,v 1.12 2005/06/01 19:02:38 roland Exp $ 30 */ 31 32 #include "defs.h" 33 34 #ifdef LINUX 35 #include <linux/version.h> 36 #ifdef HAVE_ANDROID_OS 37 #include <linux/timex.h> 38 #else 39 #include <sys/timex.h> 40 #endif 41 #include <linux/ioctl.h> 42 #include <linux/rtc.h> 43 #endif /* LINUX */ 44 45 void 46 printtv(tcp, addr) 47 struct tcb *tcp; 48 long addr; 49 { 50 struct timeval tv; 51 52 if (addr == 0) 53 tprintf("NULL"); 54 else if (!verbose(tcp)) 55 tprintf("%#lx", addr); 56 else if (umove(tcp, addr, &tv) < 0) 57 tprintf("{...}"); 58 else 59 tprintf("{%lu, %lu}", (long) tv.tv_sec, (long) tv.tv_usec); 60 } 61 62 #ifdef ALPHA 63 struct timeval32 64 { 65 unsigned tv_sec; 66 unsigned tv_usec; 67 }; 68 69 void 70 printtv32(tcp, addr) 71 struct tcb *tcp; 72 long addr; 73 { 74 struct timeval32 tv; 75 76 if (addr == 0) 77 tprintf("NULL"); 78 else if (!verbose(tcp)) 79 tprintf("%#lx", addr); 80 else if (umove(tcp, addr, &tv) < 0) 81 tprintf("{...}"); 82 else 83 tprintf("{%u, %u}", tv.tv_sec, tv.tv_usec); 84 } 85 #endif 86 87 88 int 89 sys_time(tcp) 90 struct tcb *tcp; 91 { 92 if (exiting(tcp)) { 93 #ifndef SVR4 94 printnum(tcp, tcp->u_arg[0], "%ld"); 95 #endif /* SVR4 */ 96 } 97 return 0; 98 } 99 100 int 101 sys_stime(tcp) 102 struct tcb *tcp; 103 { 104 if (exiting(tcp)) { 105 printnum(tcp, tcp->u_arg[0], "%ld"); 106 } 107 return 0; 108 } 109 110 int 111 sys_gettimeofday(tcp) 112 struct tcb *tcp; 113 { 114 if (exiting(tcp)) { 115 if (syserror(tcp)) { 116 tprintf("%#lx, %#lx", 117 tcp->u_arg[0], tcp->u_arg[1]); 118 return 0; 119 } 120 printtv(tcp, tcp->u_arg[0]); 121 #ifndef SVR4 122 tprintf(", "); 123 printtv(tcp, tcp->u_arg[1]); 124 #endif /* !SVR4 */ 125 } 126 return 0; 127 } 128 129 130 #ifdef ALPHA 131 int 132 sys_osf_gettimeofday(tcp) 133 struct tcb *tcp; 134 { 135 if (exiting(tcp)) { 136 if (syserror(tcp)) { 137 tprintf("%#lx, %#lx", 138 tcp->u_arg[0], tcp->u_arg[1]); 139 return 0; 140 } 141 printtv32(tcp, tcp->u_arg[0]); 142 #ifndef SVR4 143 tprintf(", "); 144 printtv32(tcp, tcp->u_arg[1]); 145 #endif /* !SVR4 */ 146 } 147 return 0; 148 } 149 #endif 150 151 int 152 sys_settimeofday(tcp) 153 struct tcb *tcp; 154 { 155 if (entering(tcp)) { 156 printtv(tcp, tcp->u_arg[0]); 157 #ifndef SVR4 158 tprintf(", "); 159 printtv(tcp, tcp->u_arg[1]); 160 #endif /* !SVR4 */ 161 } 162 return 0; 163 } 164 165 #ifdef ALPHA 166 int 167 sys_osf_settimeofday(tcp) 168 struct tcb *tcp; 169 { 170 if (entering(tcp)) { 171 printtv32(tcp, tcp->u_arg[0]); 172 #ifndef SVR4 173 tprintf(", "); 174 printtv32(tcp, tcp->u_arg[1]); 175 #endif /* !SVR4 */ 176 } 177 return 0; 178 } 179 #endif 180 181 int 182 sys_adjtime(tcp) 183 struct tcb *tcp; 184 { 185 if (entering(tcp)) { 186 printtv(tcp, tcp->u_arg[0]); 187 tprintf(", "); 188 } else { 189 if (syserror(tcp)) 190 tprintf("%#lx", tcp->u_arg[1]); 191 else 192 printtv(tcp, tcp->u_arg[1]); 193 } 194 return 0; 195 } 196 197 static const struct xlat which[] = { 198 { ITIMER_REAL, "ITIMER_REAL" }, 199 { ITIMER_VIRTUAL,"ITIMER_VIRTUAL"}, 200 { ITIMER_PROF, "ITIMER_PROF" }, 201 { 0, NULL }, 202 }; 203 204 static void 205 printitv(tcp, addr) 206 struct tcb *tcp; 207 long addr; 208 { 209 struct itimerval itv; 210 211 if (addr == 0) 212 tprintf("NULL"); 213 else if (!verbose(tcp)) 214 tprintf("%#lx", addr); 215 else if (umove(tcp, addr, &itv) < 0) 216 tprintf("{...}"); 217 else { 218 tprintf("{it_interval={%lu, %lu}, it_value={%lu, %lu}}", 219 (long) itv.it_interval.tv_sec, (long) itv.it_interval.tv_usec, 220 (long) itv.it_value.tv_sec, (long) itv.it_value.tv_usec); 221 } 222 } 223 224 225 #ifdef ALPHA 226 static void 227 printitv32(tcp, addr) 228 struct tcb *tcp; 229 long addr; 230 { 231 struct itimerval32 232 { 233 struct timeval32 it_interval; 234 struct timeval32 it_value; 235 } itv; 236 237 if (addr == 0) 238 tprintf("NULL"); 239 else if (!verbose(tcp)) 240 tprintf("%#lx", addr); 241 else if (umove(tcp, addr, &itv) < 0) 242 tprintf("{...}"); 243 else { 244 tprintf("{it_interval={%u, %u}, it_value={%u, %u}}", 245 itv.it_interval.tv_sec, itv.it_interval.tv_usec, 246 itv.it_value.tv_sec, itv.it_value.tv_usec); 247 } 248 } 249 #endif 250 251 int 252 sys_getitimer(tcp) 253 struct tcb *tcp; 254 { 255 if (entering(tcp)) { 256 printxval(which, tcp->u_arg[0], "ITIMER_???"); 257 tprintf(", "); 258 } else { 259 if (syserror(tcp)) 260 tprintf("%#lx", tcp->u_arg[1]); 261 else 262 printitv(tcp, tcp->u_arg[1]); 263 } 264 return 0; 265 } 266 267 268 #ifdef ALPHA 269 int 270 sys_osf_getitimer(tcp) 271 struct tcb *tcp; 272 { 273 if (entering(tcp)) { 274 printxval(which, tcp->u_arg[0], "ITIMER_???"); 275 tprintf(", "); 276 } else { 277 if (syserror(tcp)) 278 tprintf("%#lx", tcp->u_arg[1]); 279 else 280 printitv32(tcp, tcp->u_arg[1]); 281 } 282 return 0; 283 } 284 #endif 285 286 int 287 sys_setitimer(tcp) 288 struct tcb *tcp; 289 { 290 if (entering(tcp)) { 291 printxval(which, tcp->u_arg[0], "ITIMER_???"); 292 tprintf(", "); 293 printitv(tcp, tcp->u_arg[1]); 294 tprintf(", "); 295 } else { 296 if (syserror(tcp)) 297 tprintf("%#lx", tcp->u_arg[2]); 298 else 299 printitv(tcp, tcp->u_arg[2]); 300 } 301 return 0; 302 } 303 304 #ifdef ALPHA 305 int 306 sys_osf_setitimer(tcp) 307 struct tcb *tcp; 308 { 309 if (entering(tcp)) { 310 printxval(which, tcp->u_arg[0], "ITIMER_???"); 311 tprintf(", "); 312 printitv32(tcp, tcp->u_arg[1]); 313 tprintf(", "); 314 } else { 315 if (syserror(tcp)) 316 tprintf("%#lx", tcp->u_arg[2]); 317 else 318 printitv32(tcp, tcp->u_arg[2]); 319 } 320 return 0; 321 } 322 #endif 323 324 #ifdef LINUX 325 326 int 327 sys_adjtimex(tcp) 328 struct tcb *tcp; 329 { 330 struct timex txc; 331 332 if (exiting(tcp)) { 333 if (tcp->u_arg[0] == 0) 334 tprintf("NULL"); 335 else if (syserror(tcp) || !verbose(tcp)) 336 tprintf("%#lx", tcp->u_arg[0]); 337 else if (umove(tcp, tcp->u_arg[0], &txc) < 0) 338 tprintf("{...}"); 339 else { 340 #if LINUX_VERSION_CODE < 66332 341 tprintf("{mode=%d, offset=%ld, frequency=%ld, ", 342 txc.mode, txc.offset, txc.frequency); 343 tprintf("maxerror=%ld, esterror=%lu, status=%u, ", 344 txc.maxerror, txc.esterror, txc.status); 345 tprintf("time_constant=%ld, precision=%lu, ", 346 txc.time_constant, txc.precision); 347 tprintf("tolerance=%ld, time={%lu, %lu}}", 348 txc.tolerance, (long) txc.time.tv_sec, 349 (long) txc.time.tv_usec); 350 #else 351 tprintf("{modes=%d, offset=%ld, freq=%ld, ", 352 txc.modes, txc.offset, txc.freq); 353 tprintf("maxerror=%ld, esterror=%lu, status=%u, ", 354 txc.maxerror, txc.esterror, txc.status); 355 tprintf("constant=%ld, precision=%lu, ", 356 txc.constant, txc.precision); 357 tprintf("tolerance=%ld, time={%lu, %lu}}", 358 txc.tolerance, (long) txc.time.tv_sec, 359 (long) txc.time.tv_usec); 360 /* there's a bunch of other stuff, but it's not 361 * worth the time or the trouble to include */ 362 #endif 363 } 364 } 365 return 0; 366 } 367 368 static const struct xlat clockflags[] = { 369 { TIMER_ABSTIME, "TIMER_ABSTIME" }, 370 { 0, NULL } 371 }; 372 373 static const struct xlat clocknames[] = { 374 #ifdef CLOCK_REALTIME 375 { CLOCK_REALTIME, "CLOCK_REALTIME" }, 376 #endif 377 #ifdef CLOCK_MONOTONIC 378 { CLOCK_MONOTONIC, "CLOCK_MONOTONIC" }, 379 #endif 380 { 0, NULL } 381 }; 382 383 int 384 sys_clock_settime(tcp) 385 struct tcb *tcp; 386 { 387 if (entering(tcp)) { 388 printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); 389 tprintf(", "); 390 printtv(tcp, tcp->u_arg[1]); 391 } 392 return 0; 393 } 394 395 int 396 sys_clock_gettime(tcp) 397 struct tcb *tcp; 398 { 399 if (entering(tcp)) { 400 printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); 401 tprintf(", "); 402 } else { 403 if (syserror(tcp)) 404 tprintf("%#lx", tcp->u_arg[1]); 405 else 406 printtv(tcp, tcp->u_arg[1]); 407 } 408 return 0; 409 } 410 411 int 412 sys_clock_nanosleep(tcp) 413 struct tcb *tcp; 414 { 415 if (entering(tcp)) { 416 printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); 417 tprintf(", "); 418 printflags(clockflags, tcp->u_arg[1], "TIMER_???"); 419 tprintf(", "); 420 printtv(tcp, tcp->u_arg[2]); 421 tprintf(", "); 422 } else { 423 if (syserror(tcp)) 424 tprintf("%#lx", tcp->u_arg[3]); 425 else 426 printtv(tcp, tcp->u_arg[3]); 427 } 428 return 0; 429 } 430 431 #ifndef SIGEV_THREAD_ID 432 # define SIGEV_THREAD_ID 4 433 #endif 434 static const struct xlat sigev_value[] = { 435 { SIGEV_SIGNAL+1, "SIGEV_SIGNAL" }, 436 { SIGEV_NONE+1, "SIGEV_NONE" }, 437 { SIGEV_THREAD+1, "SIGEV_THREAD" }, 438 { SIGEV_THREAD_ID+1, "SIGEV_THREAD_ID" }, 439 { 0, NULL } 440 }; 441 442 void 443 printsigevent(tcp, arg) 444 struct tcb *tcp; 445 long arg; 446 { 447 struct sigevent sev; 448 if (umove (tcp, arg, &sev) < 0) 449 tprintf("{...}"); 450 else { 451 tprintf("{%p, ", sev.sigev_value.sival_ptr); 452 if (sev.sigev_notify == SIGEV_SIGNAL) 453 tprintf("%s, ", signame(sev.sigev_signo)); 454 else 455 tprintf("%u, ", sev.sigev_signo); 456 printxval(sigev_value, sev.sigev_notify+1, "SIGEV_???"); 457 tprintf(", "); 458 if (sev.sigev_notify == SIGEV_THREAD_ID) 459 /* _pad[0] is the _tid field which might not be 460 present in the userlevel definition of the 461 struct. */ 462 tprintf("{%d}", sev._sigev_un._pad[0]); 463 else if (sev.sigev_notify == SIGEV_THREAD) 464 tprintf("{%p, %p}", sev.sigev_notify_function, 465 sev.sigev_notify_attributes); 466 else 467 tprintf("{...}"); 468 tprintf("}"); 469 } 470 } 471 472 int 473 sys_timer_create(tcp) 474 struct tcb *tcp; 475 { 476 if (entering(tcp)) { 477 printxval(clocknames, tcp->u_arg[0], "CLOCK_???"); 478 tprintf(", "); 479 printsigevent(tcp, tcp->u_arg[1]); 480 tprintf(", "); 481 } else { 482 if (syserror(tcp)) 483 tprintf("%#lx", tcp->u_arg[2]); 484 else { 485 void *p; 486 umove(tcp, tcp->u_arg[2], &p); 487 tprintf("{%p}", p); 488 } 489 } 490 return 0; 491 } 492 493 int 494 sys_timer_settime(tcp) 495 struct tcb *tcp; 496 { 497 if (entering(tcp)) { 498 tprintf("%#lx, ", tcp->u_arg[0]); 499 printflags(clockflags, tcp->u_arg[1], "TIMER_???"); 500 tprintf(", "); 501 printitv(tcp, tcp->u_arg[2]); 502 tprintf(", "); 503 } else { 504 if (syserror(tcp)) 505 tprintf("%#lx", tcp->u_arg[3]); 506 else 507 printitv(tcp, tcp->u_arg[3]); 508 } 509 return 0; 510 } 511 512 int 513 sys_timer_gettime(tcp) 514 struct tcb *tcp; 515 { 516 if (entering(tcp)) { 517 tprintf("%#lx, ", tcp->u_arg[0]); 518 } else { 519 if (syserror(tcp)) 520 tprintf("%#lx", tcp->u_arg[1]); 521 else 522 printitv(tcp, tcp->u_arg[1]); 523 } 524 return 0; 525 } 526 527 static void 528 print_rtc(tcp, rt) 529 struct tcb *tcp; 530 const struct rtc_time *rt; 531 { 532 tprintf("{tm_sec=%d, tm_min=%d, tm_hour=%d, " 533 "tm_mday=%d, tm_mon=%d, tm_year=%d, ", 534 rt->tm_sec, rt->tm_min, rt->tm_hour, 535 rt->tm_mday, rt->tm_mon, rt->tm_year); 536 if (!abbrev(tcp)) 537 tprintf("tm_wday=%d, tm_yday=%d, tm_isdst=%d}", 538 rt->tm_wday, rt->tm_yday, rt->tm_isdst); 539 else 540 tprintf("...}"); 541 } 542 543 int 544 rtc_ioctl(tcp, code, arg) 545 struct tcb *tcp; 546 long code; 547 long arg; 548 { 549 switch (code) { 550 case RTC_ALM_SET: 551 case RTC_SET_TIME: 552 if (entering(tcp)) { 553 struct rtc_time rt; 554 if (umove(tcp, arg, &rt) < 0) 555 tprintf(", %#lx", arg); 556 else { 557 tprintf(", "); 558 print_rtc(tcp, &rt); 559 } 560 } 561 break; 562 case RTC_ALM_READ: 563 case RTC_RD_TIME: 564 if (exiting(tcp)) { 565 struct rtc_time rt; 566 if (syserror(tcp) || umove(tcp, arg, &rt) < 0) 567 tprintf(", %#lx", arg); 568 else { 569 tprintf(", "); 570 print_rtc(tcp, &rt); 571 } 572 } 573 break; 574 case RTC_IRQP_SET: 575 case RTC_EPOCH_SET: 576 if (entering(tcp)) 577 tprintf(", %lu", arg); 578 break; 579 case RTC_IRQP_READ: 580 case RTC_EPOCH_READ: 581 if (exiting(tcp)) 582 tprintf(", %lu", arg); 583 break; 584 case RTC_WKALM_SET: 585 if (entering(tcp)) { 586 struct rtc_wkalrm wk; 587 if (umove(tcp, arg, &wk) < 0) 588 tprintf(", %#lx", arg); 589 else { 590 tprintf(", {enabled=%d, pending=%d, ", 591 wk.enabled, wk.pending); 592 print_rtc(tcp, &wk.time); 593 tprintf("}"); 594 } 595 } 596 break; 597 case RTC_WKALM_RD: 598 if (exiting(tcp)) { 599 struct rtc_wkalrm wk; 600 if (syserror(tcp) || umove(tcp, arg, &wk) < 0) 601 tprintf(", %#lx", arg); 602 else { 603 tprintf(", {enabled=%d, pending=%d, ", 604 wk.enabled, wk.pending); 605 print_rtc(tcp, &wk.time); 606 tprintf("}"); 607 } 608 } 609 break; 610 default: 611 if (entering(tcp)) 612 tprintf(", %#lx", arg); 613 break; 614 } 615 return 1; 616 } 617 #endif /* LINUX */ 618