1 /* 2 * Copyright (c) 1982, 1986, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * (c) UNIX System Laboratories, Inc. 5 * All or some portions of this file are derived from material licensed 6 * to the University of California by American Telephone and Telegraph 7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with 8 * the permission of UNIX System Laboratories, Inc. 9 * 10 * %sccs.include.redist.c% 11 * 12 * @(#)sys_generic.c 8.5 (Berkeley) 01/21/94 13 */ 14 15 #include <sys/param.h> 16 #include <sys/systm.h> 17 #include <sys/filedesc.h> 18 #include <sys/ioctl.h> 19 #include <sys/file.h> 20 #include <sys/proc.h> 21 #include <sys/socketvar.h> 22 #include <sys/uio.h> 23 #include <sys/kernel.h> 24 #include <sys/stat.h> 25 #include <sys/malloc.h> 26 #ifdef KTRACE 27 #include <sys/ktrace.h> 28 #endif 29 30 /* 31 * Read system call. 32 */ 33 struct read_args { 34 int fd; 35 char *buf; 36 u_int nbyte; 37 }; 38 /* ARGSUSED */ 39 read(p, uap, retval) 40 struct proc *p; 41 register struct read_args *uap; 42 int *retval; 43 { 44 register struct file *fp; 45 register struct filedesc *fdp = p->p_fd; 46 struct uio auio; 47 struct iovec aiov; 48 long cnt, error = 0; 49 #ifdef KTRACE 50 struct iovec ktriov; 51 #endif 52 53 if (((u_int)uap->fd) >= fdp->fd_nfiles || 54 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 55 (fp->f_flag & FREAD) == 0) 56 return (EBADF); 57 aiov.iov_base = (caddr_t)uap->buf; 58 aiov.iov_len = uap->nbyte; 59 auio.uio_iov = &aiov; 60 auio.uio_iovcnt = 1; 61 auio.uio_resid = uap->nbyte; 62 auio.uio_rw = UIO_READ; 63 auio.uio_segflg = UIO_USERSPACE; 64 auio.uio_procp = p; 65 #ifdef KTRACE 66 /* 67 * if tracing, save a copy of iovec 68 */ 69 if (KTRPOINT(p, KTR_GENIO)) 70 ktriov = aiov; 71 #endif 72 cnt = uap->nbyte; 73 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 74 if (auio.uio_resid != cnt && (error == ERESTART || 75 error == EINTR || error == EWOULDBLOCK)) 76 error = 0; 77 cnt -= auio.uio_resid; 78 #ifdef KTRACE 79 if (KTRPOINT(p, KTR_GENIO) && error == 0) 80 ktrgenio(p->p_tracep, uap->fd, UIO_READ, &ktriov, cnt, error); 81 #endif 82 *retval = cnt; 83 return (error); 84 } 85 86 /* 87 * Scatter read system call. 88 */ 89 struct readv_args { 90 int fdes; 91 struct iovec *iovp; 92 u_int iovcnt; 93 }; 94 readv(p, uap, retval) 95 struct proc *p; 96 register struct readv_args *uap; 97 int *retval; 98 { 99 register struct file *fp; 100 register struct filedesc *fdp = p->p_fd; 101 struct uio auio; 102 register struct iovec *iov; 103 struct iovec *needfree; 104 struct iovec aiov[UIO_SMALLIOV]; 105 long i, cnt, error = 0; 106 u_int iovlen; 107 #ifdef KTRACE 108 struct iovec *ktriov = NULL; 109 #endif 110 111 if (((u_int)uap->fdes) >= fdp->fd_nfiles || 112 (fp = fdp->fd_ofiles[uap->fdes]) == NULL || 113 (fp->f_flag & FREAD) == 0) 114 return (EBADF); 115 /* note: can't use iovlen until iovcnt is validated */ 116 iovlen = uap->iovcnt * sizeof (struct iovec); 117 if (uap->iovcnt > UIO_SMALLIOV) { 118 if (uap->iovcnt > UIO_MAXIOV) 119 return (EINVAL); 120 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 121 needfree = iov; 122 } else { 123 iov = aiov; 124 needfree = NULL; 125 } 126 auio.uio_iov = iov; 127 auio.uio_iovcnt = uap->iovcnt; 128 auio.uio_rw = UIO_READ; 129 auio.uio_segflg = UIO_USERSPACE; 130 auio.uio_procp = p; 131 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 132 goto done; 133 auio.uio_resid = 0; 134 for (i = 0; i < uap->iovcnt; i++) { 135 if (iov->iov_len < 0) { 136 error = EINVAL; 137 goto done; 138 } 139 auio.uio_resid += iov->iov_len; 140 if (auio.uio_resid < 0) { 141 error = EINVAL; 142 goto done; 143 } 144 iov++; 145 } 146 #ifdef KTRACE 147 /* 148 * if tracing, save a copy of iovec 149 */ 150 if (KTRPOINT(p, KTR_GENIO)) { 151 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 152 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 153 } 154 #endif 155 cnt = auio.uio_resid; 156 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 157 if (auio.uio_resid != cnt && (error == ERESTART || 158 error == EINTR || error == EWOULDBLOCK)) 159 error = 0; 160 cnt -= auio.uio_resid; 161 #ifdef KTRACE 162 if (ktriov != NULL) { 163 if (error == 0) 164 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 165 cnt, error); 166 FREE(ktriov, M_TEMP); 167 } 168 #endif 169 *retval = cnt; 170 done: 171 if (needfree) 172 FREE(needfree, M_IOV); 173 return (error); 174 } 175 176 /* 177 * Write system call 178 */ 179 struct write_args { 180 int fd; 181 char *buf; 182 u_int nbyte; 183 }; 184 write(p, uap, retval) 185 struct proc *p; 186 register struct write_args *uap; 187 int *retval; 188 { 189 register struct file *fp; 190 register struct filedesc *fdp = p->p_fd; 191 struct uio auio; 192 struct iovec aiov; 193 long cnt, error = 0; 194 #ifdef KTRACE 195 struct iovec ktriov; 196 #endif 197 198 if (((u_int)uap->fd) >= fdp->fd_nfiles || 199 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 200 (fp->f_flag & FWRITE) == 0) 201 return (EBADF); 202 aiov.iov_base = (caddr_t)uap->buf; 203 aiov.iov_len = uap->nbyte; 204 auio.uio_iov = &aiov; 205 auio.uio_iovcnt = 1; 206 auio.uio_resid = uap->nbyte; 207 auio.uio_rw = UIO_WRITE; 208 auio.uio_segflg = UIO_USERSPACE; 209 auio.uio_procp = p; 210 #ifdef KTRACE 211 /* 212 * if tracing, save a copy of iovec 213 */ 214 if (KTRPOINT(p, KTR_GENIO)) 215 ktriov = aiov; 216 #endif 217 cnt = uap->nbyte; 218 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 219 if (auio.uio_resid != cnt && (error == ERESTART || 220 error == EINTR || error == EWOULDBLOCK)) 221 error = 0; 222 if (error == EPIPE) 223 psignal(p, SIGPIPE); 224 } 225 cnt -= auio.uio_resid; 226 #ifdef KTRACE 227 if (KTRPOINT(p, KTR_GENIO) && error == 0) 228 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 229 &ktriov, cnt, error); 230 #endif 231 *retval = cnt; 232 return (error); 233 } 234 235 /* 236 * Gather write system call 237 */ 238 struct writev_args { 239 int fd; 240 struct iovec *iovp; 241 u_int iovcnt; 242 }; 243 writev(p, uap, retval) 244 struct proc *p; 245 register struct writev_args *uap; 246 int *retval; 247 { 248 register struct file *fp; 249 register struct filedesc *fdp = p->p_fd; 250 struct uio auio; 251 register struct iovec *iov; 252 struct iovec *needfree; 253 struct iovec aiov[UIO_SMALLIOV]; 254 long i, cnt, error = 0; 255 u_int iovlen; 256 #ifdef KTRACE 257 struct iovec *ktriov = NULL; 258 #endif 259 260 if (((u_int)uap->fd) >= fdp->fd_nfiles || 261 (fp = fdp->fd_ofiles[uap->fd]) == NULL || 262 (fp->f_flag & FWRITE) == 0) 263 return (EBADF); 264 /* note: can't use iovlen until iovcnt is validated */ 265 iovlen = uap->iovcnt * sizeof (struct iovec); 266 if (uap->iovcnt > UIO_SMALLIOV) { 267 if (uap->iovcnt > UIO_MAXIOV) 268 return (EINVAL); 269 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK); 270 needfree = iov; 271 } else { 272 iov = aiov; 273 needfree = NULL; 274 } 275 auio.uio_iov = iov; 276 auio.uio_iovcnt = uap->iovcnt; 277 auio.uio_rw = UIO_WRITE; 278 auio.uio_segflg = UIO_USERSPACE; 279 auio.uio_procp = p; 280 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)) 281 goto done; 282 auio.uio_resid = 0; 283 for (i = 0; i < uap->iovcnt; i++) { 284 if (iov->iov_len < 0) { 285 error = EINVAL; 286 goto done; 287 } 288 auio.uio_resid += iov->iov_len; 289 if (auio.uio_resid < 0) { 290 error = EINVAL; 291 goto done; 292 } 293 iov++; 294 } 295 #ifdef KTRACE 296 /* 297 * if tracing, save a copy of iovec 298 */ 299 if (KTRPOINT(p, KTR_GENIO)) { 300 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 301 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 302 } 303 #endif 304 cnt = auio.uio_resid; 305 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 306 if (auio.uio_resid != cnt && (error == ERESTART || 307 error == EINTR || error == EWOULDBLOCK)) 308 error = 0; 309 if (error == EPIPE) 310 psignal(p, SIGPIPE); 311 } 312 cnt -= auio.uio_resid; 313 #ifdef KTRACE 314 if (ktriov != NULL) { 315 if (error == 0) 316 ktrgenio(p->p_tracep, uap->fd, UIO_WRITE, 317 ktriov, cnt, error); 318 FREE(ktriov, M_TEMP); 319 } 320 #endif 321 *retval = cnt; 322 done: 323 if (needfree) 324 FREE(needfree, M_IOV); 325 return (error); 326 } 327 328 /* 329 * Ioctl system call 330 */ 331 struct ioctl_args { 332 int fd; 333 int com; 334 caddr_t data; 335 }; 336 /* ARGSUSED */ 337 ioctl(p, uap, retval) 338 struct proc *p; 339 register struct ioctl_args *uap; 340 int *retval; 341 { 342 register struct file *fp; 343 register struct filedesc *fdp; 344 register int com, error; 345 register u_int size; 346 caddr_t data, memp; 347 int tmp; 348 #define STK_PARAMS 128 349 char stkbuf[STK_PARAMS]; 350 351 fdp = p->p_fd; 352 if ((u_int)uap->fd >= fdp->fd_nfiles || 353 (fp = fdp->fd_ofiles[uap->fd]) == NULL) 354 return (EBADF); 355 356 if ((fp->f_flag & (FREAD | FWRITE)) == 0) 357 return (EBADF); 358 359 switch (com = uap->com) { 360 case FIONCLEX: 361 fdp->fd_ofileflags[uap->fd] &= ~UF_EXCLOSE; 362 return (0); 363 case FIOCLEX: 364 fdp->fd_ofileflags[uap->fd] |= UF_EXCLOSE; 365 return (0); 366 } 367 368 /* 369 * Interpret high order word to find amount of data to be 370 * copied to/from the user's address space. 371 */ 372 size = IOCPARM_LEN(com); 373 if (size > IOCPARM_MAX) 374 return (ENOTTY); 375 memp = NULL; 376 if (size > sizeof (stkbuf)) { 377 memp = (caddr_t)malloc((u_long)size, M_IOCTLOPS, M_WAITOK); 378 data = memp; 379 } else 380 data = stkbuf; 381 if (com&IOC_IN) { 382 if (size) { 383 error = copyin(uap->data, data, (u_int)size); 384 if (error) { 385 if (memp) 386 free(memp, M_IOCTLOPS); 387 return (error); 388 } 389 } else 390 *(caddr_t *)data = uap->data; 391 } else if ((com&IOC_OUT) && size) 392 /* 393 * Zero the buffer so the user always 394 * gets back something deterministic. 395 */ 396 bzero(data, size); 397 else if (com&IOC_VOID) 398 *(caddr_t *)data = uap->data; 399 400 switch (com) { 401 402 case FIONBIO: 403 if (tmp = *(int *)data) 404 fp->f_flag |= FNONBLOCK; 405 else 406 fp->f_flag &= ~FNONBLOCK; 407 error = (*fp->f_ops->fo_ioctl)(fp, FIONBIO, (caddr_t)&tmp, p); 408 break; 409 410 case FIOASYNC: 411 if (tmp = *(int *)data) 412 fp->f_flag |= FASYNC; 413 else 414 fp->f_flag &= ~FASYNC; 415 error = (*fp->f_ops->fo_ioctl)(fp, FIOASYNC, (caddr_t)&tmp, p); 416 break; 417 418 case FIOSETOWN: 419 tmp = *(int *)data; 420 if (fp->f_type == DTYPE_SOCKET) { 421 ((struct socket *)fp->f_data)->so_pgid = tmp; 422 error = 0; 423 break; 424 } 425 if (tmp <= 0) { 426 tmp = -tmp; 427 } else { 428 struct proc *p1 = pfind(tmp); 429 if (p1 == 0) { 430 error = ESRCH; 431 break; 432 } 433 tmp = p1->p_pgrp->pg_id; 434 } 435 error = (*fp->f_ops->fo_ioctl) 436 (fp, (int)TIOCSPGRP, (caddr_t)&tmp, p); 437 break; 438 439 case FIOGETOWN: 440 if (fp->f_type == DTYPE_SOCKET) { 441 error = 0; 442 *(int *)data = ((struct socket *)fp->f_data)->so_pgid; 443 break; 444 } 445 error = (*fp->f_ops->fo_ioctl)(fp, (int)TIOCGPGRP, data, p); 446 *(int *)data = -*(int *)data; 447 break; 448 449 default: 450 error = (*fp->f_ops->fo_ioctl)(fp, com, data, p); 451 /* 452 * Copy any data to user, size was 453 * already set and checked above. 454 */ 455 if (error == 0 && (com&IOC_OUT) && size) 456 error = copyout(data, uap->data, (u_int)size); 457 break; 458 } 459 if (memp) 460 free(memp, M_IOCTLOPS); 461 return (error); 462 } 463 464 int selwait, nselcoll; 465 466 /* 467 * Select system call. 468 */ 469 struct select_args { 470 u_int nd; 471 fd_set *in, *ou, *ex; 472 struct timeval *tv; 473 }; 474 select(p, uap, retval) 475 register struct proc *p; 476 register struct select_args *uap; 477 int *retval; 478 { 479 fd_set ibits[3], obits[3]; 480 struct timeval atv; 481 int s, ncoll, error = 0, timo; 482 u_int ni; 483 484 bzero((caddr_t)ibits, sizeof(ibits)); 485 bzero((caddr_t)obits, sizeof(obits)); 486 if (uap->nd > FD_SETSIZE) 487 return (EINVAL); 488 if (uap->nd > p->p_fd->fd_nfiles) 489 uap->nd = p->p_fd->fd_nfiles; /* forgiving; slightly wrong */ 490 ni = howmany(uap->nd, NFDBITS) * sizeof(fd_mask); 491 492 #define getbits(name, x) \ 493 if (uap->name && \ 494 (error = copyin((caddr_t)uap->name, (caddr_t)&ibits[x], ni))) \ 495 goto done; 496 getbits(in, 0); 497 getbits(ou, 1); 498 getbits(ex, 2); 499 #undef getbits 500 501 if (uap->tv) { 502 error = copyin((caddr_t)uap->tv, (caddr_t)&atv, 503 sizeof (atv)); 504 if (error) 505 goto done; 506 if (itimerfix(&atv)) { 507 error = EINVAL; 508 goto done; 509 } 510 s = splclock(); 511 timevaladd(&atv, (struct timeval *)&time); 512 timo = hzto(&atv); 513 /* 514 * Avoid inadvertently sleeping forever. 515 */ 516 if (timo == 0) 517 timo = 1; 518 splx(s); 519 } else 520 timo = 0; 521 retry: 522 ncoll = nselcoll; 523 p->p_flag |= P_SELECT; 524 error = selscan(p, ibits, obits, uap->nd, retval); 525 if (error || *retval) 526 goto done; 527 s = splhigh(); 528 /* this should be timercmp(&time, &atv, >=) */ 529 if (uap->tv && (time.tv_sec > atv.tv_sec || 530 time.tv_sec == atv.tv_sec && time.tv_usec >= atv.tv_usec)) { 531 splx(s); 532 goto done; 533 } 534 if ((p->p_flag & P_SELECT) == 0 || nselcoll != ncoll) { 535 splx(s); 536 goto retry; 537 } 538 p->p_flag &= ~P_SELECT; 539 error = tsleep((caddr_t)&selwait, PSOCK | PCATCH, "select", timo); 540 splx(s); 541 if (error == 0) 542 goto retry; 543 done: 544 p->p_flag &= ~P_SELECT; 545 /* select is not restarted after signals... */ 546 if (error == ERESTART) 547 error = EINTR; 548 if (error == EWOULDBLOCK) 549 error = 0; 550 #define putbits(name, x) \ 551 if (uap->name && \ 552 (error2 = copyout((caddr_t)&obits[x], (caddr_t)uap->name, ni))) \ 553 error = error2; 554 if (error == 0) { 555 int error2; 556 557 putbits(in, 0); 558 putbits(ou, 1); 559 putbits(ex, 2); 560 #undef putbits 561 } 562 return (error); 563 } 564 565 selscan(p, ibits, obits, nfd, retval) 566 struct proc *p; 567 fd_set *ibits, *obits; 568 int nfd, *retval; 569 { 570 register struct filedesc *fdp = p->p_fd; 571 register int msk, i, j, fd; 572 register fd_mask bits; 573 struct file *fp; 574 int n = 0; 575 static int flag[3] = { FREAD, FWRITE, 0 }; 576 577 for (msk = 0; msk < 3; msk++) { 578 for (i = 0; i < nfd; i += NFDBITS) { 579 bits = ibits[msk].fds_bits[i/NFDBITS]; 580 while ((j = ffs(bits)) && (fd = i + --j) < nfd) { 581 bits &= ~(1 << j); 582 fp = fdp->fd_ofiles[fd]; 583 if (fp == NULL) 584 return (EBADF); 585 if ((*fp->f_ops->fo_select)(fp, flag[msk], p)) { 586 FD_SET(fd, &obits[msk]); 587 n++; 588 } 589 } 590 } 591 } 592 *retval = n; 593 return (0); 594 } 595 596 /*ARGSUSED*/ 597 seltrue(dev, flag, p) 598 dev_t dev; 599 int flag; 600 struct proc *p; 601 { 602 603 return (1); 604 } 605 606 /* 607 * Record a select request. 608 */ 609 void 610 selrecord(selector, sip) 611 struct proc *selector; 612 struct selinfo *sip; 613 { 614 struct proc *p; 615 pid_t mypid; 616 617 mypid = selector->p_pid; 618 if (sip->si_pid == mypid) 619 return; 620 if (sip->si_pid && (p = pfind(sip->si_pid)) && 621 p->p_wchan == (caddr_t)&selwait) 622 sip->si_flags |= SI_COLL; 623 else 624 sip->si_pid = mypid; 625 } 626 627 /* 628 * Do a wakeup when a selectable event occurs. 629 */ 630 void 631 selwakeup(sip) 632 register struct selinfo *sip; 633 { 634 register struct proc *p; 635 int s; 636 637 if (sip->si_pid == 0) 638 return; 639 if (sip->si_flags & SI_COLL) { 640 nselcoll++; 641 sip->si_flags &= ~SI_COLL; 642 wakeup((caddr_t)&selwait); 643 } 644 p = pfind(sip->si_pid); 645 sip->si_pid = 0; 646 if (p != NULL) { 647 s = splhigh(); 648 if (p->p_wchan == (caddr_t)&selwait) { 649 if (p->p_stat == SSLEEP) 650 setrunnable(p); 651 else 652 unsleep(p); 653 } else if (p->p_flag & P_SELECT) 654 p->p_flag &= ~P_SELECT; 655 splx(s); 656 } 657 } 658