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