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