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