1 /* sys_generic.c 5.5 82/08/01 */ 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/fcntl.h" 9 #include "../h/file.h" 10 #include "../h/inode.h" 11 #include "../h/buf.h" 12 #include "../h/proc.h" 13 #include "../h/inline.h" 14 #include "../h/conf.h" 15 #include "../h/socket.h" 16 #include "../h/socketvar.h" 17 #include "../h/cmap.h" 18 #include "../h/vlimit.h" 19 #include "../h/fs.h" 20 #ifdef MUSH 21 #include "../h/quota.h" 22 #include "../h/share.h" 23 #else 24 #define CHARGE(nothing) 25 #endif 26 #include "../h/descrip.h" 27 28 /* 29 * Read system call. 30 */ 31 read() 32 { 33 register struct file *fp; 34 register struct inode *ip; 35 register struct a { 36 int fdes; 37 char *cbuf; 38 unsigned count; 39 } *uap; 40 41 uap = (struct a *)u.u_ap; 42 if ((int)uap->count < 0) { 43 u.u_error = EINVAL; 44 return; 45 } 46 GETF(fp, uap->fdes); 47 if ((fp->f_flag&FREAD) == 0) { 48 u.u_error = EBADF; 49 return; 50 } 51 u.u_base = (caddr_t)uap->cbuf; 52 u.u_count = uap->count; 53 u.u_segflg = 0; 54 if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 55 if (u.u_count == uap->count) 56 u.u_eosys = RESTARTSYS; 57 } else if (fp->f_type == DTYPE_SOCKET) 58 u.u_error = soreceive(fp->f_socket, (struct sockaddr *)0); 59 else { 60 ip = fp->f_inode; 61 u.u_offset = fp->f_offset; 62 if ((ip->i_mode&IFMT) == IFREG) { 63 ilock(ip); 64 readi(ip); 65 iunlock(ip); 66 } else 67 readi(ip); 68 fp->f_offset += uap->count - u.u_count; 69 } 70 u.u_r.r_val1 = uap->count - u.u_count; 71 } 72 73 /* 74 * Write system call 75 */ 76 write() 77 { 78 register struct file *fp; 79 register struct inode *ip; 80 register struct a { 81 int fdes; 82 char *cbuf; 83 unsigned count; 84 } *uap; 85 86 uap = (struct a *)u.u_ap; 87 if ((int)uap->count < 0) { 88 u.u_error = EINVAL; 89 return; 90 } 91 GETF(fp, uap->fdes); 92 if ((fp->f_flag&FWRITE) == 0) { 93 u.u_error = EBADF; 94 return; 95 } 96 u.u_base = (caddr_t)uap->cbuf; 97 u.u_count = uap->count; 98 u.u_segflg = 0; 99 if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 100 if (u.u_count == uap->count) 101 u.u_eosys = RESTARTSYS; 102 } else if (fp->f_type == DTYPE_SOCKET) 103 u.u_error = sosend(fp->f_socket, (struct sockaddr *)0); 104 else { 105 ip = fp->f_inode; 106 if (fp->f_flag & O_APPEND) 107 fp->f_offset = ip->i_size; 108 u.u_offset = fp->f_offset; 109 if ((ip->i_mode&IFMT) == IFREG) { 110 ilock(ip); 111 writei(ip); 112 iunlock(ip); 113 } else 114 writei(ip); 115 fp->f_offset += uap->count - u.u_count; 116 } 117 u.u_r.r_val1 = uap->count - u.u_count; 118 } 119 120 readv() 121 { 122 123 } 124 125 writev() 126 { 127 128 } 129 130 /* 131 * Ioctl system call 132 * Check legality, execute common code, 133 * and switch out to individual device routine. 134 */ 135 ioctl() 136 { 137 register struct file *fp; 138 struct a { 139 int fdes; 140 int cmd; 141 caddr_t cmarg; 142 } *uap; 143 register int com, size; 144 char data[IOCPARM_MASK+1]; 145 146 uap = (struct a *)u.u_ap; 147 if ((fp = getf(uap->fdes)) == NULL) 148 return; 149 if ((fp->f_flag & (FREAD|FWRITE)) == 0) { 150 u.u_error = EBADF; 151 return; 152 } 153 com = uap->cmd; 154 155 #ifndef ONLYNEWIOCTLS 156 /* 157 * Map old style ioctl's into new for the 158 * sake of backwards compatibility (sigh). 159 */ 160 if ((com&~0xffff) == 0) { 161 com = mapioctl(com); 162 if (com == 0) { 163 u.u_error = EINVAL; 164 return; 165 } 166 } 167 #endif 168 if (com == FIOCLEX) { 169 u.u_pofile[uap->fdes] |= EXCLOSE; 170 return; 171 } 172 if (com == FIONCLEX) { 173 u.u_pofile[uap->fdes] &= ~EXCLOSE; 174 return; 175 } 176 177 /* 178 * Interpret high order word to find 179 * amount of data to be copied to/from the 180 * user's address space. 181 * (this'll have to change if we have in+out ioctls) 182 */ 183 size = (com &~ (IOC_INOUT|IOC_VOID)) >> 16; 184 if (size > sizeof (data)) { 185 u.u_error = EFAULT; 186 return; 187 } 188 if ((com&IOC_IN) && size) { 189 if (copyin(uap->cmarg, (caddr_t)data, size)) { 190 u.u_error = EFAULT; 191 return; 192 } 193 } else 194 *(caddr_t *)data = uap->cmarg; 195 /* 196 * Zero the buffer on the stack so the user 197 * always gets back something deterministic. 198 */ 199 if ((com&IOC_OUT) && size) 200 bzero((caddr_t)data, size); 201 202 if (fp->f_type == DTYPE_SOCKET) 203 soioctl(fp->f_socket, com, data); 204 else { 205 register struct inode *ip = fp->f_inode; 206 int fmt = ip->i_mode & IFMT; 207 dev_t dev; 208 209 if (fmt != IFCHR) { 210 if (com == FIONREAD && (fmt == IFREG || fmt == IFDIR)) { 211 *(off_t *)data = ip->i_size - fp->f_offset; 212 goto returndata; 213 } 214 if (com != FIONBIO && com != FIOASYNC) 215 u.u_error = ENOTTY; 216 return; 217 } 218 dev = ip->i_rdev; 219 u.u_r.r_val1 = 0; 220 if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) { 221 u.u_eosys = RESTARTSYS; 222 return; 223 } 224 (*cdevsw[major(dev)].d_ioctl)(dev, com, data, 0); 225 } 226 227 returndata: 228 /* 229 * Copy any data to user, size was 230 * already set and checked above. 231 */ 232 if ((com&IOC_OUT) && size && copyout(data, uap->cmarg, size)) 233 u.u_error = EFAULT; 234 } 235 236 /* 237 * Do nothing specific version of line 238 * discipline specific ioctl command. 239 */ 240 /*ARGSUSED*/ 241 nullioctl(tp, cmd, data, flags) 242 struct tty *tp; 243 char *data; 244 int flags; 245 { 246 247 #ifdef lint 248 tp = tp; data = data; flags = flags; 249 #endif 250 return (cmd); 251 } 252 253 /* 254 * Read the file corresponding to 255 * the inode pointed at by the argument. 256 * The actual read arguments are found 257 * in the variables: 258 * u_base core address for destination 259 * u_offset byte offset in file 260 * u_count number of bytes to read 261 * u_segflg read to kernel/user/user I 262 */ 263 readi(ip) 264 register struct inode *ip; 265 { 266 struct buf *bp; 267 struct fs *fs; 268 dev_t dev; 269 daddr_t lbn, bn; 270 off_t diff; 271 register int on, type; 272 register unsigned n; 273 int size; 274 long bsize; 275 extern int mem_no; 276 277 if (u.u_count == 0) 278 return; 279 dev = (dev_t)ip->i_rdev; 280 if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 281 mem_no != major(dev))) { 282 u.u_error = EINVAL; 283 return; 284 } 285 ip->i_flag |= IACC; 286 type = ip->i_mode&IFMT; 287 if (type == IFCHR) { 288 register c = u.u_count; 289 (*cdevsw[major(dev)].d_read)(dev); 290 CHARGE(sc_tio * (c - u.u_count)); 291 return; 292 } 293 if (type != IFBLK) { 294 dev = ip->i_dev; 295 fs = ip->i_fs; 296 bsize = fs->fs_bsize; 297 } else 298 bsize = BLKDEV_IOSIZE; 299 do { 300 lbn = u.u_offset / bsize; 301 on = u.u_offset % bsize; 302 n = MIN((unsigned)(bsize - on), u.u_count); 303 if (type != IFBLK) { 304 diff = ip->i_size - u.u_offset; 305 if (diff <= 0) 306 return; 307 if (diff < n) 308 n = diff; 309 bn = fsbtodb(fs, bmap(ip, lbn, B_READ)); 310 if (u.u_error) 311 return; 312 size = blksize(fs, ip, lbn); 313 } else { 314 size = bsize; 315 bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 316 rablock = bn + (BLKDEV_IOSIZE/DEV_BSIZE); 317 rasize = bsize; 318 } 319 if ((long)bn<0) { 320 bp = geteblk(size); 321 clrbuf(bp); 322 } else if (ip->i_lastr + 1 == lbn) 323 bp = breada(dev, bn, size, rablock, rasize); 324 else 325 bp = bread(dev, bn, size); 326 ip->i_lastr = lbn; 327 n = MIN(n, size - bp->b_resid); 328 if (n != 0) { 329 #ifdef UNFAST 330 iomove(bp->b_un.b_addr + on, n, B_READ); 331 #else 332 if (u.u_segflg != 1) { 333 if (copyout(bp->b_un.b_addr+on, u.u_base, n)) { 334 u.u_error = EFAULT; 335 goto bad; 336 } 337 } else 338 bcopy(bp->b_un.b_addr + on, u.u_base, n); 339 u.u_base += n; 340 u.u_offset += n; 341 u.u_count -= n; 342 bad: 343 ; 344 #endif 345 } 346 if (n + on == bsize || u.u_offset == ip->i_size) 347 bp->b_flags |= B_AGE; 348 brelse(bp); 349 } while (u.u_error == 0 && u.u_count != 0 && n != 0); 350 } 351 352 /* 353 * Write the file corresponding to 354 * the inode pointed at by the argument. 355 * The actual write arguments are found 356 * in the variables: 357 * u_base core address for source 358 * u_offset byte offset in file 359 * u_count number of bytes to write 360 * u_segflg write to kernel/user/user I 361 */ 362 writei(ip) 363 register struct inode *ip; 364 { 365 struct buf *bp; 366 register struct fs *fs; 367 dev_t dev; 368 daddr_t lbn, bn; 369 register int on, type; 370 register unsigned n; 371 long bsize; 372 int size, i, count; 373 extern int mem_no; 374 375 dev = (dev_t)ip->i_rdev; 376 if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR || 377 mem_no != major(dev)) ) { 378 u.u_error = EINVAL; 379 return; 380 } 381 type = ip->i_mode & IFMT; 382 if (type == IFCHR) { 383 ip->i_flag |= IUPD|ICHG; 384 CHARGE(sc_tio * u.u_count); 385 (*cdevsw[major(dev)].d_write)(dev); 386 return; 387 } 388 if (u.u_count == 0) 389 return; 390 if ((ip->i_mode & IFMT) == IFREG && 391 u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) { 392 psignal(u.u_procp, SIGXFSZ); 393 u.u_error = EMFILE; 394 return; 395 } 396 if (type!=IFBLK) { 397 dev = ip->i_dev; 398 fs = ip->i_fs; 399 bsize = fs->fs_bsize; 400 } else 401 bsize = BLKDEV_IOSIZE; 402 do { 403 lbn = u.u_offset / bsize; 404 on = u.u_offset % bsize; 405 n = MIN((unsigned)(bsize - on), u.u_count); 406 if (type != IFBLK) { 407 bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n))); 408 if (u.u_error || (long)bn<0) 409 return; 410 if(u.u_offset + n > ip->i_size && 411 (type == IFDIR || type == IFREG || type == IFLNK)) 412 ip->i_size = u.u_offset + n; 413 size = blksize(fs, ip, lbn); 414 } else { 415 size = bsize; 416 bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE); 417 } 418 count = howmany(size, DEV_BSIZE); 419 for (i = 0; i < count; i += CLSIZE) 420 if (mfind(dev, bn + i)) 421 munhash(dev, bn + i); 422 if (n == bsize) 423 bp = getblk(dev, bn, size); 424 else 425 bp = bread(dev, bn, size); 426 #ifdef UNFAST 427 iomove(bp->b_un.b_addr + on, n, B_WRITE); 428 #else 429 if (u.u_segflg != 1) { 430 if (copyin(u.u_base, bp->b_un.b_addr + on, n)) { 431 u.u_error = EFAULT; 432 goto bad; 433 } 434 } else 435 bcopy(u.u_base, bp->b_un.b_addr + on, n); 436 u.u_base += n; 437 u.u_offset += n; 438 u.u_count -= n; 439 bad: 440 ; 441 #endif 442 if (u.u_error != 0) 443 brelse(bp); 444 else { 445 if ((ip->i_mode&IFMT) == IFDIR) 446 /* 447 * Writing to clear a directory entry. 448 * Must insure the write occurs before 449 * the inode is freed, or may end up 450 * pointing at a new (different) file 451 * if inode is quickly allocated again 452 * and system crashes. 453 */ 454 bwrite(bp); 455 else if (n + on == bsize) { 456 bp->b_flags |= B_AGE; 457 bawrite(bp); 458 } else 459 bdwrite(bp); 460 } 461 ip->i_flag |= IUPD|ICHG; 462 if (u.u_ruid != 0) 463 ip->i_mode &= ~(ISUID|ISGID); 464 } while (u.u_error == 0 && u.u_count != 0); 465 } 466 467 /* 468 * Move n bytes at byte location 469 * &bp->b_un.b_addr[o] to/from (flag) the 470 * user/kernel (u.segflg) area starting at u.base. 471 * Update all the arguments by the number 472 * of bytes moved. 473 */ 474 iomove(cp, n, flag) 475 register caddr_t cp; 476 register unsigned n; 477 { 478 register int t; 479 480 if (n==0) 481 return; 482 if (u.u_segflg != 1) { 483 if (flag==B_WRITE) 484 t = copyin(u.u_base, (caddr_t)cp, n); 485 else 486 t = copyout((caddr_t)cp, u.u_base, n); 487 if (t) { 488 u.u_error = EFAULT; 489 return; 490 } 491 } else 492 if (flag == B_WRITE) 493 bcopy(u.u_base, (caddr_t)cp, n); 494 else 495 bcopy((caddr_t)cp, u.u_base, n); 496 u.u_base += n; 497 u.u_offset += n; 498 u.u_count -= n; 499 } 500