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