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