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