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