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