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