1 /* 2 * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * @(#)sys_generic.c 7.20 (Berkeley) 06/22/90 18 */ 19 20 #include "param.h" 21 #include "systm.h" 22 #include "syscontext.h" 23 #include "ioctl.h" 24 #include "file.h" 25 #include "proc.h" 26 #include "uio.h" 27 #include "kernel.h" 28 #include "stat.h" 29 #include "malloc.h" 30 #ifdef KTRACE 31 #include "ktrace.h" 32 #endif 33 34 /* 35 * Read system call. 36 */ 37 read(p, uap, retval) 38 struct proc *p; 39 register struct args { 40 int fdes; 41 char *cbuf; 42 unsigned count; 43 } *uap; 44 int *retval; 45 { 46 register struct file *fp; 47 struct uio auio; 48 struct iovec aiov; 49 long cnt, error = 0; 50 #ifdef KTRACE 51 struct iovec ktriov; 52 #endif 53 54 if (((unsigned)uap->fdes) >= NOFILE || 55 (fp = u.u_ofile[uap->fdes]) == NULL || 56 (fp->f_flag & FREAD) == 0) 57 RETURN (EBADF); 58 aiov.iov_base = (caddr_t)uap->cbuf; 59 aiov.iov_len = uap->count; 60 auio.uio_iov = &aiov; 61 auio.uio_iovcnt = 1; 62 auio.uio_resid = uap->count; 63 auio.uio_rw = UIO_READ; 64 auio.uio_segflg = UIO_USERSPACE; 65 #ifdef KTRACE 66 /* 67 * if tracing, save a copy of iovec 68 */ 69 if (KTRPOINT(p, KTR_GENIO)) 70 ktriov = aiov; 71 #endif 72 cnt = uap->count; 73 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 74 if (auio.uio_resid != cnt && (error == ERESTART || 75 error == EINTR || error == EWOULDBLOCK)) 76 error = 0; 77 cnt -= auio.uio_resid; 78 #ifdef KTRACE 79 if (KTRPOINT(p, KTR_GENIO) && error == 0) 80 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, &ktriov, cnt, error); 81 #endif 82 *retval = cnt; 83 RETURN (error); 84 } 85 86 /* 87 * Scatter read system call. 88 */ 89 readv(p, uap, retval) 90 struct proc *p; 91 register struct args { 92 int fdes; 93 struct iovec *iovp; 94 unsigned iovcnt; 95 } *uap; 96 int *retval; 97 { 98 register struct file *fp; 99 struct uio auio; 100 register struct iovec *iov; 101 struct iovec aiov[UIO_SMALLIOV]; 102 long i, cnt, error = 0; 103 #ifdef KTRACE 104 struct iovec *ktriov = NULL; 105 #endif 106 107 if (((unsigned)uap->fdes) >= NOFILE || 108 (fp = u.u_ofile[uap->fdes]) == NULL || 109 (fp->f_flag & FREAD) == 0) 110 RETURN (EBADF); 111 if (uap->iovcnt > UIO_SMALLIOV) { 112 if (uap->iovcnt > UIO_MAXIOV) 113 RETURN (EINVAL); 114 MALLOC(iov, struct iovec *, 115 sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 116 } else 117 iov = aiov; 118 auio.uio_iov = iov; 119 auio.uio_iovcnt = uap->iovcnt; 120 auio.uio_rw = UIO_READ; 121 auio.uio_segflg = UIO_USERSPACE; 122 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 123 uap->iovcnt * sizeof (struct iovec))) 124 goto done; 125 auio.uio_resid = 0; 126 for (i = 0; i < uap->iovcnt; i++) { 127 if (iov->iov_len < 0) { 128 error = EINVAL; 129 goto done; 130 } 131 auio.uio_resid += iov->iov_len; 132 if (auio.uio_resid < 0) { 133 error = EINVAL; 134 goto done; 135 } 136 iov++; 137 } 138 #ifdef KTRACE 139 /* 140 * if tracing, save a copy of iovec 141 */ 142 if (KTRPOINT(p, KTR_GENIO)) { 143 unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 144 145 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 146 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 147 } 148 #endif 149 cnt = auio.uio_resid; 150 if (error = (*fp->f_ops->fo_read)(fp, &auio, fp->f_cred)) 151 if (auio.uio_resid != cnt && (error == ERESTART || 152 error == EINTR || error == EWOULDBLOCK)) 153 error = 0; 154 cnt -= auio.uio_resid; 155 #ifdef KTRACE 156 if (ktriov != NULL) { 157 if (error == 0) 158 ktrgenio(p->p_tracep, uap->fdes, UIO_READ, ktriov, 159 cnt, error); 160 FREE(ktriov, M_TEMP); 161 } 162 #endif 163 *retval = cnt; 164 done: 165 if (uap->iovcnt > UIO_SMALLIOV) 166 FREE(iov, M_IOV); 167 RETURN (error); 168 } 169 170 /* 171 * Write system call 172 */ 173 write(p, uap, retval) 174 struct proc *p; 175 register struct args { 176 int fdes; 177 char *cbuf; 178 unsigned count; 179 } *uap; 180 int *retval; 181 { 182 register struct file *fp; 183 struct uio auio; 184 struct iovec aiov; 185 long cnt, error = 0; 186 #ifdef KTRACE 187 struct iovec ktriov; 188 #endif 189 190 if (((unsigned)uap->fdes) >= NOFILE || 191 (fp = u.u_ofile[uap->fdes]) == NULL || 192 (fp->f_flag & FWRITE) == 0) 193 RETURN (EBADF); 194 aiov.iov_base = (caddr_t)uap->cbuf; 195 aiov.iov_len = uap->count; 196 auio.uio_iov = &aiov; 197 auio.uio_iovcnt = 1; 198 auio.uio_resid = uap->count; 199 auio.uio_rw = UIO_WRITE; 200 auio.uio_segflg = UIO_USERSPACE; 201 #ifdef KTRACE 202 /* 203 * if tracing, save a copy of iovec 204 */ 205 if (KTRPOINT(p, KTR_GENIO)) 206 ktriov = aiov; 207 #endif 208 cnt = uap->count; 209 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 210 if (auio.uio_resid != cnt && (error == ERESTART || 211 error == EINTR || error == EWOULDBLOCK)) 212 error = 0; 213 if (error == EPIPE) 214 psignal(p, SIGPIPE); 215 } 216 cnt -= auio.uio_resid; 217 #ifdef KTRACE 218 if (KTRPOINT(p, KTR_GENIO) && error == 0) 219 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 220 &ktriov, cnt, error); 221 #endif 222 *retval = cnt; 223 RETURN (error); 224 } 225 226 /* 227 * Gather write system call 228 */ 229 writev(p, uap, retval) 230 struct proc *p; 231 register struct args { 232 int fdes; 233 struct iovec *iovp; 234 unsigned iovcnt; 235 } *uap; 236 int *retval; 237 { 238 register struct file *fp; 239 struct uio auio; 240 register struct iovec *iov; 241 struct iovec aiov[UIO_SMALLIOV]; 242 long i, cnt, error = 0; 243 #ifdef KTRACE 244 struct iovec *ktriov = NULL; 245 #endif 246 247 if (((unsigned)uap->fdes) >= NOFILE || 248 (fp = u.u_ofile[uap->fdes]) == NULL || 249 (fp->f_flag & FWRITE) == 0) 250 RETURN (EBADF); 251 if (uap->iovcnt > UIO_SMALLIOV) { 252 if (uap->iovcnt > UIO_MAXIOV) 253 RETURN (EINVAL); 254 MALLOC(iov, struct iovec *, 255 sizeof(struct iovec) * uap->iovcnt, M_IOV, M_WAITOK); 256 } else 257 iov = aiov; 258 auio.uio_iov = iov; 259 auio.uio_iovcnt = uap->iovcnt; 260 auio.uio_rw = UIO_WRITE; 261 auio.uio_segflg = UIO_USERSPACE; 262 if (error = copyin((caddr_t)uap->iovp, (caddr_t)iov, 263 uap->iovcnt * sizeof (struct iovec))) 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 unsigned iovlen = auio.uio_iovcnt * sizeof (struct iovec); 284 285 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK); 286 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen); 287 } 288 #endif 289 cnt = auio.uio_resid; 290 if (error = (*fp->f_ops->fo_write)(fp, &auio, fp->f_cred)) { 291 if (auio.uio_resid != cnt && (error == ERESTART || 292 error == EINTR || error == EWOULDBLOCK)) 293 error = 0; 294 if (error == EPIPE) 295 psignal(p, SIGPIPE); 296 } 297 cnt -= auio.uio_resid; 298 #ifdef KTRACE 299 if (ktriov != NULL) { 300 if (error == 0) 301 ktrgenio(p->p_tracep, uap->fdes, UIO_WRITE, 302 ktriov, cnt, error); 303 FREE(ktriov, M_TEMP); 304 } 305 #endif 306 *retval = cnt; 307 done: 308 if (uap->iovcnt > UIO_SMALLIOV) 309 FREE(iov, M_IOV); 310 RETURN (error); 311 } 312 313 /* 314 * Ioctl system call 315 */ 316 /* ARGSUSED */ 317 ioctl(p, uap, retval) 318 struct proc *p; 319 register struct args { 320 int fdes; 321 int cmd; 322 caddr_t cmarg; 323 } *uap; 324 int *retval; 325 { 326 register struct file *fp; 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 >= NOFILE || 335 (fp = u.u_ofile[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 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 343 RETURN (0); 344 } 345 if (com == FIONCLEX) { 346 u.u_pofile[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 > NOFILE) 434 uap->nd = NOFILE; /* forgiving, if 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(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(ibits, obits, nfd, retval) 508 fd_set *ibits, *obits; 509 int nfd, *retval; 510 { 511 register int which, i, j; 512 register fd_mask bits; 513 int flag; 514 struct file *fp; 515 int error = 0, n = 0; 516 517 for (which = 0; which < 3; which++) { 518 switch (which) { 519 520 case 0: 521 flag = FREAD; break; 522 523 case 1: 524 flag = FWRITE; break; 525 526 case 2: 527 flag = 0; break; 528 } 529 for (i = 0; i < nfd; i += NFDBITS) { 530 bits = ibits[which].fds_bits[i/NFDBITS]; 531 while ((j = ffs(bits)) && i + --j < nfd) { 532 bits &= ~(1 << j); 533 fp = u.u_ofile[i + j]; 534 if (fp == NULL) { 535 error = EBADF; 536 break; 537 } 538 if ((*fp->f_ops->fo_select)(fp, flag)) { 539 FD_SET(i + j, &obits[which]); 540 n++; 541 } 542 } 543 } 544 } 545 *retval = n; 546 return (error); 547 } 548 549 /*ARGSUSED*/ 550 seltrue(dev, flag) 551 dev_t dev; 552 int flag; 553 { 554 555 return (1); 556 } 557 558 selwakeup(p, coll) 559 register struct proc *p; 560 int coll; 561 { 562 563 if (coll) { 564 nselcoll++; 565 wakeup((caddr_t)&selwait); 566 } 567 if (p) { 568 int s = splhigh(); 569 if (p->p_wchan == (caddr_t)&selwait) { 570 if (p->p_stat == SSLEEP) 571 setrun(p); 572 else 573 unsleep(p); 574 } else if (p->p_flag & SSEL) 575 p->p_flag &= ~SSEL; 576 splx(s); 577 } 578 } 579