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