1 /* sys_generic.c 5.35 83/05/21 */ 2 3 #include "../h/param.h" 4 #include "../h/systm.h" 5 #include "../h/dir.h" 6 #include "../h/user.h" 7 #include "../h/ioctl.h" 8 #include "../h/tty.h" 9 #include "../h/file.h" 10 #include "../h/inode.h" 11 #include "../h/buf.h" 12 #include "../h/proc.h" 13 #include "../h/conf.h" 14 #include "../h/socket.h" 15 #include "../h/socketvar.h" 16 #include "../h/fs.h" 17 #include "../h/descrip.h" 18 #include "../h/uio.h" 19 #include "../h/cmap.h" 20 21 /* 22 * Read system call. 23 */ 24 read() 25 { 26 register struct a { 27 int fdes; 28 char *cbuf; 29 unsigned count; 30 } *uap = (struct a *)u.u_ap; 31 struct uio auio; 32 struct iovec aiov; 33 34 aiov.iov_base = (caddr_t)uap->cbuf; 35 aiov.iov_len = uap->count; 36 auio.uio_iov = &aiov; 37 auio.uio_iovcnt = 1; 38 rwuio(&auio, UIO_READ); 39 } 40 41 readv() 42 { 43 register struct a { 44 int fdes; 45 struct iovec *iovp; 46 int iovcnt; 47 } *uap = (struct a *)u.u_ap; 48 struct uio auio; 49 struct iovec aiov[16]; /* XXX */ 50 51 if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 52 u.u_error = EINVAL; 53 return; 54 } 55 auio.uio_iov = aiov; 56 auio.uio_iovcnt = uap->iovcnt; 57 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 58 (unsigned)(uap->iovcnt * sizeof (struct iovec))); 59 if (u.u_error) 60 return; 61 rwuio(&auio, UIO_READ); 62 } 63 64 /* 65 * Write system call 66 */ 67 write() 68 { 69 register struct a { 70 int fdes; 71 char *cbuf; 72 int count; 73 } *uap = (struct a *)u.u_ap; 74 struct uio auio; 75 struct iovec aiov; 76 77 auio.uio_iov = &aiov; 78 auio.uio_iovcnt = 1; 79 aiov.iov_base = uap->cbuf; 80 aiov.iov_len = uap->count; 81 rwuio(&auio, UIO_WRITE); 82 } 83 84 writev() 85 { 86 register struct a { 87 int fdes; 88 struct iovec *iovp; 89 int iovcnt; 90 } *uap = (struct a *)u.u_ap; 91 struct uio auio; 92 struct iovec aiov[16]; /* XXX */ 93 94 if (uap->iovcnt <= 0 || uap->iovcnt > sizeof(aiov)/sizeof(aiov[0])) { 95 u.u_error = EINVAL; 96 return; 97 } 98 auio.uio_iov = aiov; 99 auio.uio_iovcnt = uap->iovcnt; 100 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 101 (unsigned)(uap->iovcnt * sizeof (struct iovec))); 102 if (u.u_error) 103 return; 104 rwuio(&auio, UIO_WRITE); 105 } 106 107 rwuio(uio, rw) 108 register struct uio *uio; 109 enum uio_rw rw; 110 { 111 struct a { 112 int fdes; 113 }; 114 register struct file *fp; 115 register struct iovec *iov; 116 register struct inode *ip; 117 int i, count; 118 119 GETF(fp, ((struct a *)u.u_ap)->fdes); 120 if ((fp->f_flag&(rw==UIO_READ ? FREAD : FWRITE)) == 0) { 121 u.u_error = EBADF; 122 return; 123 } 124 uio->uio_resid = 0; 125 uio->uio_segflg = 0; 126 iov = uio->uio_iov; 127 for (i = 0; i < uio->uio_iovcnt; i++) { 128 if (iov->iov_len < 0) { 129 u.u_error = EINVAL; 130 return; 131 } 132 uio->uio_resid += iov->iov_len; 133 if (uio->uio_resid < 0) { 134 u.u_error = EINVAL; 135 return; 136 } 137 } 138 count = uio->uio_resid; 139 if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 140 if (uio->uio_resid == count) 141 u.u_eosys = RESTARTSYS; 142 } else if (fp->f_type == DTYPE_SOCKET) { 143 int sosend(), soreceive(); 144 u.u_error = 145 (*(rw==UIO_READ?soreceive:sosend)) 146 (fp->f_socket, (struct sockaddr *)0, uio, 0); 147 } else { 148 ip = fp->f_inode; 149 uio->uio_offset = fp->f_offset; 150 if ((ip->i_mode&IFMT) == IFREG) { 151 ILOCK(ip); 152 if (fp->f_flag&FAPPEND && rw == UIO_WRITE) 153 uio->uio_offset = fp->f_offset = ip->i_size; 154 u.u_error = rwip(ip, uio, rw); 155 IUNLOCK(ip); 156 } else 157 u.u_error = rwip(ip, uio, rw); 158 fp->f_offset += count - uio->uio_resid; 159 } 160 u.u_r.r_val1 = count - uio->uio_resid; 161 } 162 163 rdwri(rw, ip, base, len, offset, segflg, aresid) 164 struct inode *ip; 165 caddr_t base; 166 int len, offset, segflg; 167 int *aresid; 168 enum uio_rw rw; 169 { 170 struct uio auio; 171 struct iovec aiov; 172 int error; 173 174 auio.uio_iov = &aiov; 175 auio.uio_iovcnt = 1; 176 aiov.iov_base = base; 177 aiov.iov_len = len; 178 auio.uio_resid = len; 179 auio.uio_offset = offset; 180 auio.uio_segflg = segflg; 181 error = rwip(ip, &auio, rw); 182 if (aresid) 183 *aresid = auio.uio_resid; 184 else 185 if (auio.uio_resid) 186 error = EIO; 187 return (error); 188 } 189 190 rwip(ip, uio, rw) 191 register struct inode *ip; 192 register struct uio *uio; 193 enum uio_rw rw; 194 { 195 dev_t dev = (dev_t)ip->i_rdev; 196 struct buf *bp; 197 struct fs *fs; 198 daddr_t lbn, bn; 199 register int n, on, type; 200 int size; 201 long bsize; 202 extern int mem_no; 203 int error = 0; 204 205 if (rw != UIO_READ && rw != UIO_WRITE) 206 panic("rwip"); 207 if (rw == UIO_READ && uio->uio_resid == 0) 208 return (0); 209 if (uio->uio_offset < 0 && 210 ((ip->i_mode&IFMT) != IFCHR || mem_no != major(dev))) 211 return (EINVAL); 212 if (rw == UIO_READ) 213 ip->i_flag |= IACC; 214 type = ip->i_mode&IFMT; 215 if (type == IFCHR) { 216 if (rw == UIO_READ) 217 u.u_error = (*cdevsw[major(dev)].d_read)(dev, uio); 218 else { 219 ip->i_flag |= IUPD|ICHG; 220 u.u_error = (*cdevsw[major(dev)].d_write)(dev, uio); 221 } 222 return (u.u_error); 223 } 224 if (uio->uio_resid == 0) 225 return (0); 226 if (rw == UIO_WRITE && type == IFREG && 227 uio->uio_offset + uio->uio_resid > 228 u.u_rlimit[RLIMIT_FSIZE].rlim_cur) { 229 psignal(u.u_procp, SIGXFSZ); 230 return (EMFILE); 231 } 232 if (type != IFBLK) { 233 dev = ip->i_dev; 234 fs = ip->i_fs; 235 bsize = fs->fs_bsize; 236 } else 237 bsize = BLKDEV_IOSIZE; 238 do { 239 lbn = uio->uio_offset / bsize; 240 on = uio->uio_offset % bsize; 241 n = MIN((unsigned)(bsize - on), uio->uio_resid); 242 if (type != IFBLK) { 243 if (rw == UIO_READ) { 244 int diff = ip->i_size - uio->uio_offset; 245 if (diff <= 0) 246 return (0); 247 if (diff < n) 248 n = diff; 249 } 250 bn = fsbtodb(fs, 251 bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n))); 252 if (u.u_error || rw == UIO_WRITE && (long)bn<0) 253 return (u.u_error); 254 if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && 255 (type == IFDIR || type == IFREG || type == IFLNK)) 256 ip->i_size = uio->uio_offset + n; 257 size = blksize(fs, ip, lbn); 258 } else { 259 bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 260 rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 261 rasize = size = bsize; 262 } 263 if (rw == UIO_READ) { 264 if ((long)bn<0) { 265 bp = geteblk(size); 266 clrbuf(bp); 267 } else if (ip->i_lastr + 1 == lbn) 268 bp = breada(dev, bn, size, rablock, rasize); 269 else 270 bp = bread(dev, bn, size); 271 ip->i_lastr = lbn; 272 } else { 273 int i, count; 274 extern struct cmap *mfind(); 275 276 count = howmany(size, DEV_BSIZE); 277 for (i = 0; i < count; i += CLSIZE) 278 if (mfind(dev, bn + i)) 279 munhash(dev, bn + i); 280 if (n == bsize) 281 bp = getblk(dev, bn, size); 282 else 283 bp = bread(dev, bn, size); 284 } 285 n = MIN(n, size - bp->b_resid); 286 if (bp->b_flags & B_ERROR) { 287 error = EIO; 288 brelse(bp); 289 goto bad; 290 } 291 u.u_error = 292 uiomove(bp->b_un.b_addr+on, n, rw, uio); 293 if (rw == UIO_READ) { 294 if (n + on == bsize || uio->uio_offset == ip->i_size) 295 bp->b_flags |= B_AGE; 296 brelse(bp); 297 } else { 298 if ((ip->i_mode&IFMT) == IFDIR) 299 bwrite(bp); 300 else if (n + on == bsize) { 301 bp->b_flags |= B_AGE; 302 bawrite(bp); 303 } else 304 bdwrite(bp); 305 ip->i_flag |= IUPD|ICHG; 306 if (u.u_ruid != 0) 307 ip->i_mode &= ~(ISUID|ISGID); 308 } 309 } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0); 310 bad: 311 return (error); 312 } 313 314 uiomove(cp, n, rw, uio) 315 register caddr_t cp; 316 register int n; 317 enum uio_rw rw; 318 register struct uio *uio; 319 { 320 register struct iovec *iov; 321 u_int cnt; 322 int error = 0; 323 324 while (n > 0 && uio->uio_resid) { 325 iov = uio->uio_iov; 326 cnt = iov->iov_len; 327 if (cnt == 0) { 328 uio->uio_iov++; 329 uio->uio_iovcnt--; 330 continue; 331 } 332 if (cnt > n) 333 cnt = n; 334 switch (uio->uio_segflg) { 335 336 case 0: 337 case 2: 338 if (rw == UIO_READ) 339 error = copyout(cp, iov->iov_base, cnt); 340 else 341 error = copyin(iov->iov_base, cp, cnt); 342 if (error) 343 return (error); 344 break; 345 346 case 1: 347 if (rw == UIO_READ) 348 bcopy((caddr_t)cp, iov->iov_base, cnt); 349 else 350 bcopy(iov->iov_base, (caddr_t)cp, cnt); 351 break; 352 } 353 iov->iov_base += cnt; 354 iov->iov_len -= cnt; 355 uio->uio_resid -= cnt; 356 uio->uio_offset += cnt; 357 cp += cnt; 358 n -= cnt; 359 } 360 return (error); 361 } 362 363 /* 364 * Give next character to user as result of read. 365 */ 366 ureadc(c, uio) 367 register int c; 368 register struct uio *uio; 369 { 370 register struct iovec *iov; 371 372 again: 373 if (uio->uio_iovcnt == 0) 374 panic("ureadc"); 375 iov = uio->uio_iov; 376 if (iov->iov_len <= 0 || uio->uio_resid <= 0) { 377 uio->uio_iovcnt--; 378 uio->uio_iov++; 379 goto again; 380 } 381 switch (uio->uio_segflg) { 382 383 case 0: 384 if (subyte(iov->iov_base, c) < 0) 385 return (EFAULT); 386 break; 387 388 case 1: 389 *iov->iov_base = c; 390 break; 391 392 case 2: 393 if (suibyte(iov->iov_base, c) < 0) 394 return (EFAULT); 395 break; 396 } 397 iov->iov_base++; 398 iov->iov_len--; 399 uio->uio_resid--; 400 uio->uio_offset++; 401 return (0); 402 } 403 404 #ifdef notdef 405 /* 406 * Get next character written in by user from uio. 407 */ 408 uwritec(uio) 409 struct uio *uio; 410 { 411 register struct iovec *iov; 412 register int c; 413 414 again: 415 if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0) 416 panic("uwritec"); 417 iov = uio->uio_iov; 418 if (iov->iov_len == 0) { 419 uio->uio_iovcnt--; 420 uio->uio_iov++; 421 goto again; 422 } 423 switch (uio->uio_segflg) { 424 425 case 0: 426 c = fubyte(iov->iov_base); 427 break; 428 429 case 1: 430 c = *iov->iov_base & 0377; 431 break; 432 433 case 2: 434 c = fuibyte(iov->iov_base); 435 break; 436 } 437 if (c < 0) 438 return (-1); 439 iov->iov_base++; 440 iov->iov_len--; 441 uio->uio_resid--; 442 uio->uio_offset++; 443 return (c & 0377); 444 } 445 #endif 446 447 /* 448 * Ioctl system call 449 * Check legality, execute common code, 450 * and switch out to individual device routine. 451 */ 452 ioctl() 453 { 454 register struct file *fp; 455 struct a { 456 int fdes; 457 int cmd; 458 caddr_t cmarg; 459 } *uap; 460 register int com; 461 register u_int size; 462 char data[IOCPARM_MASK+1]; 463 464 uap = (struct a *)u.u_ap; 465 if ((fp = getf(uap->fdes)) == NULL) 466 return; 467 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 468 u.u_error = EBADF; 469 return; 470 } 471 com = uap->cmd; 472 473 #ifndef NOCOMPAT 474 /* 475 * Map old style ioctl's into new for the 476 * sake of backwards compatibility (sigh). 477 */ 478 if ((com&~0xffff) == 0) { 479 com = mapioctl(com); 480 if (com == 0) { 481 u.u_error = EINVAL; 482 return; 483 } 484 } 485 #endif 486 if (com == FIOCLEX) { 487 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 488 return; 489 } 490 if (com == FIONCLEX) { 491 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 492 return; 493 } 494 495 /* 496 * Interpret high order word to find 497 * amount of data to be copied to/from the 498 * user's address space. 499 */ 500 size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 501 if (size > sizeof (data)) { 502 u.u_error = EFAULT; 503 return; 504 } 505 if (com&IOC_IN) { 506 if (size) { 507 u.u_error = 508 copyin(uap->cmarg, (caddr_t)data, (u_int)size); 509 if (u.u_error) 510 return; 511 } else 512 *(caddr_t *)data = uap->cmarg; 513 } else if ((com&IOC_OUT) && size) 514 /* 515 * Zero the buffer on the stack so the user 516 * always gets back something deterministic. 517 */ 518 bzero((caddr_t)data, size); 519 else if (com&IOC_VOID) 520 *(caddr_t *)data = uap->cmarg; 521 522 if (fp->f_type == DTYPE_SOCKET) 523 u.u_error = soioctl(fp->f_socket, com, data); 524 else { 525 register struct inode *ip = fp->f_inode; 526 int fmt = ip->i_mode & IFMT; 527 dev_t dev; 528 529 if (fmt != IFCHR) { 530 if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 531 *(off_t *)data = ip->i_size - fp->f_offset; 532 goto returndata; 533 } 534 if (com != FIONBIO && com != FIOASYNC) 535 u.u_error = ENOTTY; 536 return; 537 } 538 dev = ip->i_rdev; 539 u.u_r.r_val1 = 0; 540 if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 541 u.u_eosys = RESTARTSYS; 542 return; 543 } 544 u.u_error = 545 (*cdevsw[major(dev)].d_ioctl)(dev, com, data, fp->f_flag); 546 } 547 548 returndata: 549 /* 550 * Copy any data to user, size was 551 * already set and checked above. 552 */ 553 if (u.u_error == 0 && (com&IOC_OUT) && size) 554 u.u_error = copyout(data, uap->cmarg, (u_int)size); 555 } 556 557 /* 558 * Do nothing specific version of line 559 * discipline specific ioctl command. 560 */ 561 /*ARGSUSED*/ 562 nullioctl(tp, cmd, data, flags) 563 struct tty *tp; 564 char *data; 565 int flags; 566 { 567 568 #ifdef lint 569 tp = tp; data = data; flags = flags; 570 #endif 571 return (-1); 572 } 573 574 ostty() 575 { 576 577 } 578 579 ogtty() 580 { 581 582 } 583