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