1 /* $NetBSD: kern_time_50.c,v 1.16 2010/05/30 19:31:39 drochner Exp $ */ 2 3 /*- 4 * Copyright (c) 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 #include <sys/cdefs.h> 32 __KERNEL_RCSID(0, "$NetBSD: kern_time_50.c,v 1.16 2010/05/30 19:31:39 drochner Exp $"); 33 34 #ifdef _KERNEL_OPT 35 #include "opt_aio.h" 36 #include "opt_ntp.h" 37 #include "opt_mqueue.h" 38 #endif 39 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/namei.h> 43 #include <sys/filedesc.h> 44 #include <sys/kernel.h> 45 #include <sys/file.h> 46 #include <sys/stat.h> 47 #include <sys/socketvar.h> 48 #include <sys/vnode.h> 49 #include <sys/mount.h> 50 #include <sys/proc.h> 51 #include <sys/uio.h> 52 #include <sys/dirent.h> 53 #include <sys/malloc.h> 54 #include <sys/kauth.h> 55 #include <sys/time.h> 56 #include <sys/timex.h> 57 #include <sys/aio.h> 58 #include <sys/poll.h> 59 #include <sys/syscallargs.h> 60 #include <sys/resource.h> 61 62 #include <compat/common/compat_util.h> 63 #include <compat/sys/time.h> 64 #include <compat/sys/timex.h> 65 #include <compat/sys/resource.h> 66 #include <compat/sys/clockctl.h> 67 68 static int 69 compat_50_kevent_fetch_timeout(const void *src, void *dest, size_t length) 70 { 71 struct timespec50 ts50; 72 int error; 73 74 KASSERT(length == sizeof(struct timespec)); 75 76 error = copyin(src, &ts50, sizeof(ts50)); 77 if (error) 78 return error; 79 timespec50_to_timespec(&ts50, (struct timespec *)dest); 80 return 0; 81 } 82 83 int 84 compat_50_sys_kevent(struct lwp *l, const struct compat_50_sys_kevent_args *uap, 85 register_t *retval) 86 { 87 /* { 88 syscallarg(int) fd; 89 syscallarg(keventp_t) changelist; 90 syscallarg(size_t) nchanges; 91 syscallarg(keventp_t) eventlist; 92 syscallarg(size_t) nevents; 93 syscallarg(struct timespec50) timeout; 94 } */ 95 static const struct kevent_ops compat_50_kevent_ops = { 96 .keo_private = NULL, 97 .keo_fetch_timeout = compat_50_kevent_fetch_timeout, 98 .keo_fetch_changes = kevent_fetch_changes, 99 .keo_put_events = kevent_put_events, 100 }; 101 102 return kevent1(retval, SCARG(uap, fd), SCARG(uap, changelist), 103 SCARG(uap, nchanges), SCARG(uap, eventlist), SCARG(uap, nevents), 104 (const struct timespec *)(const void *)SCARG(uap, timeout), 105 &compat_50_kevent_ops); 106 } 107 108 int 109 compat_50_sys_clock_gettime(struct lwp *l, 110 const struct compat_50_sys_clock_gettime_args *uap, register_t *retval) 111 { 112 /* { 113 syscallarg(clockid_t) clock_id; 114 syscallarg(struct timespec50 *) tp; 115 } */ 116 int error; 117 struct timespec ats; 118 struct timespec50 ats50; 119 120 error = clock_gettime1(SCARG(uap, clock_id), &ats); 121 if (error != 0) 122 return error; 123 124 timespec_to_timespec50(&ats, &ats50); 125 126 return copyout(&ats50, SCARG(uap, tp), sizeof(ats50)); 127 } 128 129 /* ARGSUSED */ 130 int 131 compat_50_sys_clock_settime(struct lwp *l, 132 const struct compat_50_sys_clock_settime_args *uap, register_t *retval) 133 { 134 /* { 135 syscallarg(clockid_t) clock_id; 136 syscallarg(const struct timespec50 *) tp; 137 } */ 138 int error; 139 struct timespec ats; 140 struct timespec50 ats50; 141 142 error = copyin(SCARG(uap, tp), &ats50, sizeof(ats50)); 143 if (error) 144 return error; 145 timespec50_to_timespec(&ats50, &ats); 146 147 return clock_settime1(l->l_proc, SCARG(uap, clock_id), &ats, 148 true); 149 } 150 151 152 int 153 compat_50_sys_clock_getres(struct lwp *l, 154 const struct compat_50_sys_clock_getres_args *uap, register_t *retval) 155 { 156 /* { 157 syscallarg(clockid_t) clock_id; 158 syscallarg(struct timespec50 *) tp; 159 } */ 160 struct timespec50 ats50; 161 struct timespec ats; 162 int error = 0; 163 164 error = clock_getres1(SCARG(uap, clock_id), &ats); 165 if (error != 0) 166 return error; 167 168 if (SCARG(uap, tp)) { 169 timespec_to_timespec50(&ats, &ats50); 170 error = copyout(&ats50, SCARG(uap, tp), sizeof(ats50)); 171 } 172 173 return error; 174 } 175 176 /* ARGSUSED */ 177 int 178 compat_50_sys_nanosleep(struct lwp *l, 179 const struct compat_50_sys_nanosleep_args *uap, register_t *retval) 180 { 181 /* { 182 syscallarg(struct timespec50 *) rqtp; 183 syscallarg(struct timespec50 *) rmtp; 184 } */ 185 struct timespec rmt, rqt; 186 struct timespec50 rmt50, rqt50; 187 int error, error1; 188 189 error = copyin(SCARG(uap, rqtp), &rqt50, sizeof(rqt50)); 190 if (error) 191 return error; 192 timespec50_to_timespec(&rqt50, &rqt); 193 194 error = nanosleep1(l, &rqt, SCARG(uap, rmtp) ? &rmt : NULL); 195 if (SCARG(uap, rmtp) == NULL || (error != 0 && error != EINTR)) 196 return error; 197 198 timespec_to_timespec50(&rmt, &rmt50); 199 error1 = copyout(&rmt50, SCARG(uap, rmtp), sizeof(*SCARG(uap, rmtp))); 200 return error1 ? error1 : error; 201 } 202 203 /* ARGSUSED */ 204 int 205 compat_50_sys_gettimeofday(struct lwp *l, 206 const struct compat_50_sys_gettimeofday_args *uap, register_t *retval) 207 { 208 /* { 209 syscallarg(struct timeval50 *) tp; 210 syscallarg(void *) tzp; really "struct timezone *"; 211 } */ 212 struct timeval atv; 213 struct timeval50 atv50; 214 int error = 0; 215 struct timezone tzfake; 216 217 if (SCARG(uap, tp)) { 218 microtime(&atv); 219 timeval_to_timeval50(&atv, &atv50); 220 error = copyout(&atv50, SCARG(uap, tp), sizeof(*SCARG(uap, tp))); 221 if (error) 222 return error; 223 } 224 if (SCARG(uap, tzp)) { 225 /* 226 * NetBSD has no kernel notion of time zone, so we just 227 * fake up a timezone struct and return it if demanded. 228 */ 229 tzfake.tz_minuteswest = 0; 230 tzfake.tz_dsttime = 0; 231 error = copyout(&tzfake, SCARG(uap, tzp), sizeof(tzfake)); 232 } 233 return error; 234 } 235 236 /* ARGSUSED */ 237 int 238 compat_50_sys_settimeofday(struct lwp *l, 239 const struct compat_50_sys_settimeofday_args *uap, register_t *retval) 240 { 241 /* { 242 syscallarg(const struct timeval50 *) tv; 243 syscallarg(const void *) tzp; really "const struct timezone *"; 244 } */ 245 struct timeval50 atv50; 246 struct timeval atv; 247 int error = copyin(SCARG(uap, tv), &atv50, sizeof(atv50)); 248 if (error) 249 return error; 250 timeval50_to_timeval(&atv50, &atv); 251 return settimeofday1(&atv, false, SCARG(uap, tzp), l, true); 252 } 253 254 /* ARGSUSED */ 255 int 256 compat_50_sys_adjtime(struct lwp *l, 257 const struct compat_50_sys_adjtime_args *uap, register_t *retval) 258 { 259 /* { 260 syscallarg(const struct timeval50 *) delta; 261 syscallarg(struct timeval50 *) olddelta; 262 } */ 263 int error; 264 struct timeval50 delta50, olddelta50; 265 struct timeval delta, olddelta; 266 267 if ((error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_TIME, 268 KAUTH_REQ_SYSTEM_TIME_ADJTIME, NULL, NULL, NULL)) != 0) 269 return error; 270 271 if (SCARG(uap, delta)) { 272 error = copyin(SCARG(uap, delta), &delta50, 273 sizeof(*SCARG(uap, delta))); 274 if (error) 275 return (error); 276 timeval50_to_timeval(&delta50, &delta); 277 } 278 adjtime1(SCARG(uap, delta) ? &delta : NULL, 279 SCARG(uap, olddelta) ? &olddelta : NULL, l->l_proc); 280 if (SCARG(uap, olddelta)) { 281 timeval_to_timeval50(&olddelta, &olddelta50); 282 error = copyout(&olddelta50, SCARG(uap, olddelta), 283 sizeof(*SCARG(uap, olddelta))); 284 } 285 return error; 286 } 287 288 /* BSD routine to set/arm an interval timer. */ 289 /* ARGSUSED */ 290 int 291 compat_50_sys_getitimer(struct lwp *l, 292 const struct compat_50_sys_getitimer_args *uap, register_t *retval) 293 { 294 /* { 295 syscallarg(int) which; 296 syscallarg(struct itimerval50 *) itv; 297 } */ 298 struct proc *p = l->l_proc; 299 struct itimerval aitv; 300 struct itimerval50 aitv50; 301 int error; 302 303 error = dogetitimer(p, SCARG(uap, which), &aitv); 304 if (error) 305 return error; 306 itimerval_to_itimerval50(&aitv, &aitv50); 307 return copyout(&aitv50, SCARG(uap, itv), sizeof(*SCARG(uap, itv))); 308 } 309 310 int 311 compat_50_sys_setitimer(struct lwp *l, 312 const struct compat_50_sys_setitimer_args *uap, register_t *retval) 313 { 314 /* { 315 syscallarg(int) which; 316 syscallarg(const struct itimerval50 *) itv; 317 syscallarg(struct itimerval50 *) oitv; 318 } */ 319 struct proc *p = l->l_proc; 320 int which = SCARG(uap, which); 321 struct compat_50_sys_getitimer_args getargs; 322 const struct itimerval50 *itvp; 323 struct itimerval50 aitv50; 324 struct itimerval aitv; 325 int error; 326 327 if ((u_int)which > ITIMER_PROF) 328 return (EINVAL); 329 itvp = SCARG(uap, itv); 330 if (itvp && 331 (error = copyin(itvp, &aitv50, sizeof(aitv50)) != 0)) 332 return (error); 333 itimerval50_to_itimerval(&aitv50, &aitv); 334 if (SCARG(uap, oitv) != NULL) { 335 SCARG(&getargs, which) = which; 336 SCARG(&getargs, itv) = SCARG(uap, oitv); 337 if ((error = compat_50_sys_getitimer(l, &getargs, retval)) != 0) 338 return (error); 339 } 340 if (itvp == 0) 341 return (0); 342 343 return dosetitimer(p, which, &aitv); 344 } 345 346 int 347 compat_50_sys_aio_suspend(struct lwp *l, 348 const struct compat_50_sys_aio_suspend_args *uap, register_t *retval) 349 { 350 /* { 351 syscallarg(const struct aiocb *const[]) list; 352 syscallarg(int) nent; 353 syscallarg(const struct timespec50 *) timeout; 354 } */ 355 #ifdef AIO 356 struct aiocb **list; 357 struct timespec ts; 358 struct timespec50 ts50; 359 int error, nent; 360 361 nent = SCARG(uap, nent); 362 if (nent <= 0 || nent > aio_listio_max) 363 return EAGAIN; 364 365 if (SCARG(uap, timeout)) { 366 /* Convert timespec to ticks */ 367 error = copyin(SCARG(uap, timeout), &ts50, 368 sizeof(*SCARG(uap, timeout))); 369 if (error) 370 return error; 371 timespec50_to_timespec(&ts50, &ts); 372 } 373 list = kmem_alloc(nent * sizeof(*list), KM_SLEEP); 374 error = copyin(SCARG(uap, list), list, nent * sizeof(*list)); 375 if (error) 376 goto out; 377 error = aio_suspend1(l, list, nent, SCARG(uap, timeout) ? &ts : NULL); 378 out: 379 kmem_free(list, nent * sizeof(*list)); 380 return error; 381 #else 382 return ENOSYS; 383 #endif 384 } 385 386 int 387 compat_50_sys_select(struct lwp *l, 388 const struct compat_50_sys_select_args *uap, register_t *retval) 389 { 390 /* { 391 syscallarg(int) nd; 392 syscallarg(fd_set *) in; 393 syscallarg(fd_set *) ou; 394 syscallarg(fd_set *) ex; 395 syscallarg(struct timeval50 *) tv; 396 } */ 397 struct timespec ats, *ts = NULL; 398 struct timeval50 atv50; 399 int error; 400 401 if (SCARG(uap, tv)) { 402 error = copyin(SCARG(uap, tv), (void *)&atv50, sizeof(atv50)); 403 if (error) 404 return error; 405 ats.tv_sec = atv50.tv_sec; 406 ats.tv_nsec = atv50.tv_usec * 1000; 407 ts = &ats; 408 } 409 410 return selcommon(retval, SCARG(uap, nd), SCARG(uap, in), 411 SCARG(uap, ou), SCARG(uap, ex), ts, NULL); 412 } 413 414 int 415 compat_50_sys_pselect(struct lwp *l, 416 const struct compat_50_sys_pselect_args *uap, register_t *retval) 417 { 418 /* { 419 syscallarg(int) nd; 420 syscallarg(fd_set *) in; 421 syscallarg(fd_set *) ou; 422 syscallarg(fd_set *) ex; 423 syscallarg(const struct timespec50 *) ts; 424 syscallarg(sigset_t *) mask; 425 } */ 426 struct timespec50 ats50; 427 struct timespec ats, *ts = NULL; 428 sigset_t amask, *mask = NULL; 429 int error; 430 431 if (SCARG(uap, ts)) { 432 error = copyin(SCARG(uap, ts), &ats50, sizeof(ats50)); 433 if (error) 434 return error; 435 timespec50_to_timespec(&ats50, &ats); 436 ts = &ats; 437 } 438 if (SCARG(uap, mask) != NULL) { 439 error = copyin(SCARG(uap, mask), &amask, sizeof(amask)); 440 if (error) 441 return error; 442 mask = &amask; 443 } 444 445 return selcommon(retval, SCARG(uap, nd), SCARG(uap, in), 446 SCARG(uap, ou), SCARG(uap, ex), ts, mask); 447 } 448 int 449 compat_50_sys_pollts(struct lwp *l, const struct compat_50_sys_pollts_args *uap, 450 register_t *retval) 451 { 452 /* { 453 syscallarg(struct pollfd *) fds; 454 syscallarg(u_int) nfds; 455 syscallarg(const struct timespec50 *) ts; 456 syscallarg(const sigset_t *) mask; 457 } */ 458 struct timespec ats, *ts = NULL; 459 struct timespec50 ats50; 460 sigset_t amask, *mask = NULL; 461 int error; 462 463 if (SCARG(uap, ts)) { 464 error = copyin(SCARG(uap, ts), &ats50, sizeof(ats50)); 465 if (error) 466 return error; 467 timespec50_to_timespec(&ats50, &ats); 468 ts = &ats; 469 } 470 if (SCARG(uap, mask)) { 471 error = copyin(SCARG(uap, mask), &amask, sizeof(amask)); 472 if (error) 473 return error; 474 mask = &amask; 475 } 476 477 return pollcommon(retval, SCARG(uap, fds), SCARG(uap, nfds), ts, mask); 478 } 479 480 int 481 compat_50_sys__lwp_park(struct lwp *l, 482 const struct compat_50_sys__lwp_park_args *uap, register_t *retval) 483 { 484 /* { 485 syscallarg(const struct timespec50 *) ts; 486 syscallarg(lwpid_t) unpark; 487 syscallarg(const void *) hint; 488 syscallarg(const void *) unparkhint; 489 } */ 490 struct timespec ts, *tsp; 491 struct timespec50 ts50; 492 int error; 493 494 if (SCARG(uap, ts) == NULL) 495 tsp = NULL; 496 else { 497 error = copyin(SCARG(uap, ts), &ts50, sizeof(ts50)); 498 if (error != 0) 499 return error; 500 timespec50_to_timespec(&ts50, &ts); 501 tsp = &ts; 502 } 503 504 if (SCARG(uap, unpark) != 0) { 505 error = lwp_unpark(SCARG(uap, unpark), SCARG(uap, unparkhint)); 506 if (error != 0) 507 return error; 508 } 509 510 return lwp_park(tsp, SCARG(uap, hint)); 511 } 512 513 int 514 compat_50_sys_mq_timedsend(struct lwp *l, 515 const struct compat_50_sys_mq_timedsend_args *uap, register_t *retval) 516 { 517 /* { 518 syscallarg(mqd_t) mqdes; 519 syscallarg(const char *) msg_ptr; 520 syscallarg(size_t) msg_len; 521 syscallarg(unsigned) msg_prio; 522 syscallarg(const struct timespec50 *) abs_timeout; 523 } */ 524 #ifdef MQUEUE 525 struct timespec50 ts50; 526 struct timespec ts, *tsp; 527 int error; 528 529 /* Get and convert time value */ 530 if (SCARG(uap, abs_timeout)) { 531 error = copyin(SCARG(uap, abs_timeout), &ts50, sizeof(ts50)); 532 if (error) 533 return error; 534 timespec50_to_timespec(&ts50, &ts); 535 tsp = &ts; 536 } else { 537 tsp = NULL; 538 } 539 540 return mq_send1(SCARG(uap, mqdes), SCARG(uap, msg_ptr), 541 SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp); 542 #else 543 return ENOSYS; 544 #endif 545 } 546 547 int 548 compat_50_sys_mq_timedreceive(struct lwp *l, 549 const struct compat_50_sys_mq_timedreceive_args *uap, register_t *retval) 550 { 551 /* { 552 syscallarg(mqd_t) mqdes; 553 syscallarg(char *) msg_ptr; 554 syscallarg(size_t) msg_len; 555 syscallarg(unsigned *) msg_prio; 556 syscallarg(const struct timespec50 *) abs_timeout; 557 } */ 558 #ifdef MQUEUE 559 struct timespec ts, *tsp; 560 struct timespec50 ts50; 561 ssize_t mlen; 562 int error; 563 564 /* Get and convert time value */ 565 if (SCARG(uap, abs_timeout)) { 566 error = copyin(SCARG(uap, abs_timeout), &ts50, sizeof(ts50)); 567 if (error) 568 return error; 569 570 timespec50_to_timespec(&ts50, &ts); 571 tsp = &ts; 572 } else { 573 tsp = NULL; 574 } 575 576 error = mq_recv1(SCARG(uap, mqdes), SCARG(uap, msg_ptr), 577 SCARG(uap, msg_len), SCARG(uap, msg_prio), tsp, &mlen); 578 if (error == 0) 579 *retval = mlen; 580 581 return error; 582 #else 583 return ENOSYS; 584 #endif 585 } 586 587 static int 588 tscopyin(const void *u, void *s, size_t len) 589 { 590 struct timespec50 ts50; 591 KASSERT(len == sizeof(ts50)); 592 int error = copyin(u, &ts50, len); 593 if (error) 594 return error; 595 timespec50_to_timespec(&ts50, s); 596 return 0; 597 } 598 599 static int 600 tscopyout(const void *s, void *u, size_t len) 601 { 602 struct timespec50 ts50; 603 KASSERT(len == sizeof(ts50)); 604 timespec_to_timespec50(s, &ts50); 605 int error = copyout(&ts50, u, len); 606 if (error) 607 return error; 608 return 0; 609 } 610 611 int 612 compat_50_sys___sigtimedwait(struct lwp *l, 613 const struct compat_50_sys___sigtimedwait_args *uap, register_t *retval) 614 { 615 int res; 616 617 res = sigtimedwait1(l, 618 (const struct sys_____sigtimedwait50_args *)uap, retval, copyout, 619 tscopyin, tscopyout); 620 if (!res) 621 *retval = 0; /* XXX NetBSD<=5 was not POSIX compliant */ 622 return res; 623 } 624 625 void 626 rusage_to_rusage50(const struct rusage *ru, struct rusage50 *ru50) 627 { 628 (void)memcpy(&ru50->ru_first, &ru->ru_first, 629 (char *)&ru50->ru_last - (char *)&ru50->ru_first + 630 sizeof(ru50->ru_last)); 631 ru50->ru_maxrss = ru->ru_maxrss; 632 timeval_to_timeval50(&ru->ru_utime, &ru50->ru_utime); 633 timeval_to_timeval50(&ru->ru_stime, &ru50->ru_stime); 634 } 635 636 int 637 compat_50_sys_getrusage(struct lwp *l, 638 const struct compat_50_sys_getrusage_args *uap, register_t *retval) 639 { 640 /* { 641 syscallarg(int) who; 642 syscallarg(struct rusage50 *) rusage; 643 } */ 644 struct rusage ru; 645 struct rusage50 ru50; 646 struct proc *p = l->l_proc; 647 648 switch (SCARG(uap, who)) { 649 case RUSAGE_SELF: 650 mutex_enter(p->p_lock); 651 memcpy(&ru, &p->p_stats->p_ru, sizeof(ru)); 652 calcru(p, &ru.ru_utime, &ru.ru_stime, NULL, NULL); 653 mutex_exit(p->p_lock); 654 break; 655 656 case RUSAGE_CHILDREN: 657 mutex_enter(p->p_lock); 658 memcpy(&ru, &p->p_stats->p_cru, sizeof(ru)); 659 mutex_exit(p->p_lock); 660 break; 661 662 default: 663 return EINVAL; 664 } 665 rusage_to_rusage50(&ru, &ru50); 666 return copyout(&ru50, SCARG(uap, rusage), sizeof(ru50)); 667 } 668 669 670 /* Return the time remaining until a POSIX timer fires. */ 671 int 672 compat_50_sys_timer_gettime(struct lwp *l, 673 const struct compat_50_sys_timer_gettime_args *uap, register_t *retval) 674 { 675 /* { 676 syscallarg(timer_t) timerid; 677 syscallarg(struct itimerspec50 *) value; 678 } */ 679 struct itimerspec its; 680 struct itimerspec50 its50; 681 int error; 682 683 if ((error = dotimer_gettime(SCARG(uap, timerid), l->l_proc, 684 &its)) != 0) 685 return error; 686 itimerspec_to_itimerspec50(&its, &its50); 687 688 return copyout(&its50, SCARG(uap, value), sizeof(its50)); 689 } 690 691 /* Set and arm a POSIX realtime timer */ 692 int 693 compat_50_sys_timer_settime(struct lwp *l, 694 const struct compat_50_sys_timer_settime_args *uap, register_t *retval) 695 { 696 /* { 697 syscallarg(timer_t) timerid; 698 syscallarg(int) flags; 699 syscallarg(const struct itimerspec50 *) value; 700 syscallarg(struct itimerspec50 *) ovalue; 701 } */ 702 int error; 703 struct itimerspec value, ovalue, *ovp = NULL; 704 struct itimerspec50 value50, ovalue50; 705 706 if ((error = copyin(SCARG(uap, value), &value50, sizeof(value50))) != 0) 707 return error; 708 709 itimerspec50_to_itimerspec(&value50, &value); 710 if (SCARG(uap, ovalue)) 711 ovp = &ovalue; 712 713 if ((error = dotimer_settime(SCARG(uap, timerid), &value, ovp, 714 SCARG(uap, flags), l->l_proc)) != 0) 715 return error; 716 717 if (ovp) { 718 itimerspec_to_itimerspec50(&ovalue, &ovalue50); 719 return copyout(&ovalue50, SCARG(uap, ovalue), sizeof(ovalue50)); 720 } 721 return 0; 722 } 723 724 /* 725 * ntp_gettime() - NTP user application interface 726 */ 727 int 728 compat_50_sys___ntp_gettime30(struct lwp *l, 729 const struct compat_50_sys___ntp_gettime30_args *uap, register_t *retval) 730 { 731 #ifdef NTP 732 /* { 733 syscallarg(struct ntptimeval *) ntvp; 734 } */ 735 struct ntptimeval ntv; 736 struct ntptimeval50 ntv50; 737 int error; 738 739 if (SCARG(uap, ntvp)) { 740 ntp_gettime(&ntv); 741 timespec_to_timespec50(&ntv.time, &ntv50.time); 742 ntv50.maxerror = ntv.maxerror; 743 ntv50.esterror = ntv.esterror; 744 ntv50.tai = ntv.tai; 745 ntv50.time_state = ntv.time_state; 746 747 error = copyout(&ntv50, SCARG(uap, ntvp), sizeof(ntv50)); 748 if (error) 749 return error; 750 } 751 *retval = ntp_timestatus(); 752 return 0; 753 #else 754 return ENOSYS; 755 #endif 756 } 757 int 758 compat50_clockctlioctl(dev_t dev, u_long cmd, void *data, int flags, 759 struct lwp *l) 760 { 761 int error = 0; 762 763 switch (cmd) { 764 case CLOCKCTL_OSETTIMEOFDAY: { 765 struct timeval50 tv50; 766 struct timeval tv; 767 struct clockctl50_settimeofday *args = data; 768 769 error = copyin(args->tv, &tv50, sizeof(tv50)); 770 if (error) 771 return (error); 772 timeval50_to_timeval(&tv50, &tv); 773 error = settimeofday1(&tv, false, args->tzp, l, false); 774 break; 775 } 776 case CLOCKCTL_OADJTIME: { 777 struct timeval atv, oldatv; 778 struct timeval50 atv50; 779 struct clockctl50_adjtime *args = data; 780 781 if (args->delta) { 782 error = copyin(args->delta, &atv50, sizeof(atv50)); 783 if (error) 784 return (error); 785 timeval50_to_timeval(&atv50, &atv); 786 } 787 adjtime1(args->delta ? &atv : NULL, 788 args->olddelta ? &oldatv : NULL, l->l_proc); 789 if (args->olddelta) { 790 timeval_to_timeval50(&oldatv, &atv50); 791 error = copyout(&atv50, args->olddelta, sizeof(atv50)); 792 } 793 break; 794 } 795 case CLOCKCTL_OCLOCK_SETTIME: { 796 struct timespec50 tp50; 797 struct timespec tp; 798 struct clockctl50_clock_settime *args = data; 799 800 error = copyin(args->tp, &tp50, sizeof(tp50)); 801 if (error) 802 return (error); 803 timespec50_to_timespec(&tp50, &tp); 804 error = clock_settime1(l->l_proc, args->clock_id, &tp, true); 805 break; 806 } 807 default: 808 error = EINVAL; 809 } 810 811 return (error); 812 } 813 int 814 compat_50_sys_wait4(struct lwp *l, const struct compat_50_sys_wait4_args *uap, 815 register_t *retval) 816 { 817 /* { 818 syscallarg(int) pid; 819 syscallarg(int *) status; 820 syscallarg(int) options; 821 syscallarg(struct rusage50 *) rusage; 822 } */ 823 int status, error, pid = SCARG(uap, pid); 824 struct rusage50 ru50; 825 struct rusage ru; 826 827 error = do_sys_wait(&pid, &status, SCARG(uap, options), 828 SCARG(uap, rusage) != NULL ? &ru : NULL); 829 830 retval[0] = pid; 831 if (pid == 0) 832 return error; 833 834 if (SCARG(uap, rusage)) { 835 rusage_to_rusage50(&ru, &ru50); 836 error = copyout(&ru50, SCARG(uap, rusage), sizeof(ru50)); 837 } 838 839 if (error == 0 && SCARG(uap, status)) 840 error = copyout(&status, SCARG(uap, status), sizeof(status)); 841 842 return error; 843 } 844