1 /* sys_generic.c 5.34 83/05/08 */ 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 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 64 (unsigned)(uap->iovcnt * sizeof (struct iovec))); 65 if (u.u_error) 66 return; 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 u.u_error = copyin((caddr_t)uap->iovp, (caddr_t)aiov, 107 (unsigned)(uap->iovcnt * sizeof (struct iovec))); 108 if (u.u_error) 109 return; 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 if (fp->f_flag&FAPPEND && rw == UIO_WRITE) 159 uio->uio_offset = fp->f_offset = ip->i_size; 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 bn = fsbtodb(fs, 261 bmap(ip, lbn, rw == UIO_WRITE ? B_WRITE: B_READ, (int)(on+n))); 262 if (u.u_error || rw == UIO_WRITE && (long)bn<0) 263 return (u.u_error); 264 if (rw == UIO_WRITE && uio->uio_offset + n > ip->i_size && 265 (type == IFDIR || type == IFREG || type == IFLNK)) 266 ip->i_size = uio->uio_offset + n; 267 size = blksize(fs, ip, lbn); 268 } else { 269 bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 270 rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 271 rasize = size = bsize; 272 } 273 if (rw == UIO_READ) { 274 if ((long)bn<0) { 275 bp = geteblk(size); 276 clrbuf(bp); 277 } else if (ip->i_lastr + 1 == lbn) 278 bp = breada(dev, bn, size, rablock, rasize); 279 else 280 bp = bread(dev, bn, size); 281 ip->i_lastr = lbn; 282 } else { 283 int i, count; 284 extern struct cmap *mfind(); 285 286 count = howmany(size, DEV_BSIZE); 287 for (i = 0; i < count; i += CLSIZE) 288 if (mfind(dev, bn + i)) 289 munhash(dev, bn + i); 290 if (n == bsize) 291 bp = getblk(dev, bn, size); 292 else 293 bp = bread(dev, bn, size); 294 } 295 n = MIN(n, size - bp->b_resid); 296 if (bp->b_flags & B_ERROR) { 297 error = EIO; 298 brelse(bp); 299 goto bad; 300 } 301 u.u_error = 302 uiomove(bp->b_un.b_addr+on, n, rw, uio); 303 if (rw == UIO_READ) { 304 if (n + on == bsize || uio->uio_offset == ip->i_size) 305 bp->b_flags |= B_AGE; 306 brelse(bp); 307 } else { 308 if ((ip->i_mode&IFMT) == IFDIR) 309 bwrite(bp); 310 else if (n + on == bsize) { 311 bp->b_flags |= B_AGE; 312 bawrite(bp); 313 } else 314 bdwrite(bp); 315 ip->i_flag |= IUPD|ICHG; 316 if (u.u_ruid != 0) 317 ip->i_mode &= ~(ISUID|ISGID); 318 } 319 } while (u.u_error == 0 && uio->uio_resid > 0 && n != 0); 320 bad: 321 return (error); 322 } 323 324 uiomove(cp, n, rw, uio) 325 register caddr_t cp; 326 register int n; 327 enum uio_rw rw; 328 register struct uio *uio; 329 { 330 register struct iovec *iov; 331 u_int cnt; 332 int error = 0; 333 334 while (n > 0 && uio->uio_resid) { 335 iov = uio->uio_iov; 336 cnt = iov->iov_len; 337 if (cnt == 0) { 338 uio->uio_iov++; 339 uio->uio_iovcnt--; 340 continue; 341 } 342 if (cnt > n) 343 cnt = n; 344 switch (uio->uio_segflg) { 345 346 case 0: 347 case 2: 348 if (rw == UIO_READ) 349 error = copyout(cp, iov->iov_base, cnt); 350 else 351 error = copyin(iov->iov_base, cp, cnt); 352 if (error) 353 return (error); 354 break; 355 356 case 1: 357 if (rw == UIO_READ) 358 bcopy((caddr_t)cp, iov->iov_base, cnt); 359 else 360 bcopy(iov->iov_base, (caddr_t)cp, cnt); 361 break; 362 } 363 iov->iov_base += cnt; 364 iov->iov_len -= cnt; 365 uio->uio_resid -= cnt; 366 uio->uio_offset += cnt; 367 cp += cnt; 368 n -= cnt; 369 } 370 return (error); 371 } 372 373 /* 374 * Give next character to user as result of read. 375 */ 376 ureadc(c, uio) 377 register int c; 378 register struct uio *uio; 379 { 380 register struct iovec *iov; 381 382 again: 383 if (uio->uio_iovcnt == 0) 384 panic("ureadc"); 385 iov = uio->uio_iov; 386 if (iov->iov_len <= 0 || uio->uio_resid <= 0) { 387 uio->uio_iovcnt--; 388 uio->uio_iov++; 389 goto again; 390 } 391 switch (uio->uio_segflg) { 392 393 case 0: 394 if (subyte(iov->iov_base, c) < 0) 395 return (EFAULT); 396 break; 397 398 case 1: 399 *iov->iov_base = c; 400 break; 401 402 case 2: 403 if (suibyte(iov->iov_base, c) < 0) 404 return (EFAULT); 405 break; 406 } 407 iov->iov_base++; 408 iov->iov_len--; 409 uio->uio_resid--; 410 uio->uio_offset++; 411 return (0); 412 } 413 414 #ifdef notdef 415 /* 416 * Get next character written in by user from uio. 417 */ 418 uwritec(uio) 419 struct uio *uio; 420 { 421 register struct iovec *iov; 422 register int c; 423 424 again: 425 if (uio->uio_iovcnt <= 0 || uio->uio_resid <= 0) 426 panic("uwritec"); 427 iov = uio->uio_iov; 428 if (iov->iov_len == 0) { 429 uio->uio_iovcnt--; 430 uio->uio_iov++; 431 goto again; 432 } 433 switch (uio->uio_segflg) { 434 435 case 0: 436 c = fubyte(iov->iov_base); 437 break; 438 439 case 1: 440 c = *iov->iov_base & 0377; 441 break; 442 443 case 2: 444 c = fuibyte(iov->iov_base); 445 break; 446 } 447 if (c < 0) 448 return (-1); 449 iov->iov_base++; 450 iov->iov_len--; 451 uio->uio_resid--; 452 uio->uio_offset++; 453 return (c & 0377); 454 } 455 #endif 456 457 /* 458 * Ioctl system call 459 * Check legality, execute common code, 460 * and switch out to individual device routine. 461 */ 462 ioctl() 463 { 464 register struct file *fp; 465 struct a { 466 int fdes; 467 int cmd; 468 caddr_t cmarg; 469 } *uap; 470 register int com; 471 register u_int size; 472 char data[IOCPARM_MASK+1]; 473 474 uap = (struct a *)u.u_ap; 475 if ((fp = getf(uap->fdes)) == NULL) 476 return; 477 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 478 u.u_error = EBADF; 479 return; 480 } 481 com = uap->cmd; 482 483 #ifndef NOCOMPAT 484 /* 485 * Map old style ioctl's into new for the 486 * sake of backwards compatibility (sigh). 487 */ 488 if ((com&~0xffff) == 0) { 489 com = mapioctl(com); 490 if (com == 0) { 491 u.u_error = EINVAL; 492 return; 493 } 494 } 495 #endif 496 if (com == FIOCLEX) { 497 u.u_pofile[uap->fdes] |= UF_EXCLOSE; 498 return; 499 } 500 if (com == FIONCLEX) { 501 u.u_pofile[uap->fdes] &= ~UF_EXCLOSE; 502 return; 503 } 504 505 /* 506 * Interpret high order word to find 507 * amount of data to be copied to/from the 508 * user's address space. 509 */ 510 size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 511 if (size > sizeof (data)) { 512 u.u_error = EFAULT; 513 return; 514 } 515 if (com&IOC_IN) { 516 if (size) { 517 u.u_error = 518 copyin(uap->cmarg, (caddr_t)data, (u_int)size); 519 if (u.u_error) 520 return; 521 } else 522 *(caddr_t *)data = uap->cmarg; 523 } else if ((com&IOC_OUT) && size) 524 /* 525 * Zero the buffer on the stack so the user 526 * always gets back something deterministic. 527 */ 528 bzero((caddr_t)data, size); 529 else if (com&IOC_VOID) 530 *(caddr_t *)data = uap->cmarg; 531 532 if (fp->f_type == DTYPE_SOCKET) 533 u.u_error = soioctl(fp->f_socket, com, data); 534 else { 535 register struct inode *ip = fp->f_inode; 536 int fmt = ip->i_mode & IFMT; 537 dev_t dev; 538 539 if (fmt != IFCHR) { 540 if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 541 *(off_t *)data = ip->i_size - fp->f_offset; 542 goto returndata; 543 } 544 if (com != FIONBIO && com != FIOASYNC) 545 u.u_error = ENOTTY; 546 return; 547 } 548 dev = ip->i_rdev; 549 u.u_r.r_val1 = 0; 550 if ((u.u_procp->p_flag&SNUSIG) && setjmp(&u.u_qsave)) { 551 u.u_eosys = RESTARTSYS; 552 return; 553 } 554 u.u_error = 555 (*cdevsw[major(dev)].d_ioctl)(dev, com, data, fp->f_flag); 556 } 557 558 returndata: 559 /* 560 * Copy any data to user, size was 561 * already set and checked above. 562 */ 563 if (u.u_error == 0 && (com&IOC_OUT) && size) 564 u.u_error = copyout(data, uap->cmarg, (u_int)size); 565 } 566 567 /* 568 * Do nothing specific version of line 569 * discipline specific ioctl command. 570 */ 571 /*ARGSUSED*/ 572 nullioctl(tp, cmd, data, flags) 573 struct tty *tp; 574 char *data; 575 int flags; 576 { 577 578 #ifdef lint 579 tp = tp; data = data; flags = flags; 580 #endif 581 return (-1); 582 } 583 584 ostty() 585 { 586 587 } 588 589 ogtty() 590 { 591 592 } 593