07300 #include "../h/param.h" 07301 #include "../h/systm.h" 07302 #include "../h/inode.h" 07303 #include "../h/dir.h" 07304 #include "../h/user.h" 07305 #include "../h/buf.h" 07306 #include "../h/conf.h" 07307 07308 /* 07309 * Read the file corresponding to 07310 * the inode pointed at by the argument. 07311 * The actual read arguments are found 07312 * in the variables: 07313 * u_base core address for destination 07314 * u_offset byte offset in file 07315 * u_count number of bytes to read 07316 * u_segflg read to kernel/user/user I 07317 */ 07318 readi(ip) 07319 register struct inode *ip; 07320 { 07321 struct buf *bp; 07322 dev_t dev; 07323 daddr_t lbn, bn; 07324 off_t diff; 07325 register on, n; 07326 register type; 07327 07328 if(u.u_count == 0) 07329 return; 07330 if(u.u_offset < 0) { 07331 u.u_error = EINVAL; 07332 return; 07333 } 07334 ip->i_flag |= IACC; 07335 dev = (dev_t)ip->i_un.i_rdev; 07336 type = ip->i_mode&IFMT; 07337 if (type==IFCHR || type==IFMPC) { 07338 return((*cdevsw[major(dev)].d_read)(dev)); 07339 } 07340 07341 do { 07342 lbn = bn = u.u_offset >> BSHIFT; 07343 on = u.u_offset & BMASK; 07344 n = min((unsigned)(BSIZE-on), u.u_count); 07345 if (type!=IFBLK && type!=IFMPB) { 07346 diff = ip->i_size - u.u_offset; 07347 if(diff <= 0) 07348 return; 07349 if(diff < n) 07350 n = diff; 07351 bn = bmap(ip, bn, B_READ); 07352 if(u.u_error) 07353 return; 07354 dev = ip->i_dev; 07355 } else 07356 rablock = bn+1; 07357 if ((long)bn<0) { 07358 bp = geteblk(); 07359 clrbuf(bp); 07360 } else if (ip->i_un.i_lastr+1==lbn) 07361 bp = breada(dev, bn, rablock); 07362 else 07363 bp = bread(dev, bn); 07364 ip->i_un.i_lastr = lbn; 07365 n = min((unsigned)n, BSIZE-bp->b_resid); 07366 if (n!=0) 07367 iomove(bp->b_un.b_addr+on, n, B_READ); 07368 brelse(bp); 07369 } while(u.u_error==0 && u.u_count!=0 && n>0); 07370 } 07371 07372 /* 07373 * Write the file corresponding to 07374 * the inode pointed at by the argument. 07375 * The actual write arguments are found 07376 * in the variables: 07377 * u_base core address for source 07378 * u_offset byte offset in file 07379 * u_count number of bytes to write 07380 * u_segflg write to kernel/user/user I 07381 */ 07382 writei(ip) 07383 register struct inode *ip; 07384 { 07385 struct buf *bp; 07386 dev_t dev; 07387 daddr_t bn; 07388 register n, on; 07389 register type; 07390 07391 if(u.u_offset < 0) { 07392 u.u_error = EINVAL; 07393 return; 07394 } 07395 dev = (dev_t)ip->i_un.i_rdev; 07396 type = ip->i_mode&IFMT; 07397 if (type==IFCHR || type==IFMPC) { 07398 ip->i_flag |= IUPD|ICHG; 07399 (*cdevsw[major(dev)].d_write)(dev); 07400 return; 07401 } 07402 if (u.u_count == 0) 07403 return; 07404 07405 do { 07406 bn = u.u_offset >> BSHIFT; 07407 on = u.u_offset & BMASK; 07408 n = min((unsigned)(BSIZE-on), u.u_count); 07409 if (type!=IFBLK && type!=IFMPB) { 07410 bn = bmap(ip, bn, B_WRITE); 07411 if((long)bn<0) 07412 return; 07413 dev = ip->i_dev; 07414 } 07415 if(n == BSIZE) 07416 bp = getblk(dev, bn); 07417 else 07418 bp = bread(dev, bn); 07419 iomove(bp->b_un.b_addr+on, n, B_WRITE); 07420 if(u.u_error != 0) 07421 brelse(bp); 07422 else 07423 bdwrite(bp); 07424 if(u.u_offset > ip->i_size && 07425 (type==IFDIR || type==IFREG)) 07426 ip->i_size = u.u_offset; 07427 ip->i_flag |= IUPD|ICHG; 07428 } while(u.u_error==0 && u.u_count!=0); 07429 } 07430 07431 /* 07432 * Return the logical maximum 07433 * of the 2 arguments. 07434 */ 07435 max(a, b) 07436 unsigned a, b; 07437 { 07438 07439 if(a > b) 07440 return(a); 07441 return(b); 07442 } 07443 07444 /* 07445 * Return the logical minimum 07446 * of the 2 arguments. 07447 */ 07448 min(a, b) 07449 unsigned a, b; 07450 { 07451 07452 if(a < b) 07453 return(a); 07454 return(b); 07455 } 07456 07457 /* 07458 * Move n bytes at byte location 07459 * &bp->b_un.b_addr[o] to/from (flag) the 07460 * user/kernel (u.segflg) area starting at u.base. 07461 * Update all the arguments by the number 07462 * of bytes moved. 07463 * 07464 * There are 2 algorithms, 07465 * if source address, dest address and count 07466 * are all even in a user copy, 07467 * then the machine language copyin/copyout 07468 * is called. 07469 * If not, its done byte-by-byte with 07470 * cpass and passc. 07471 */ 07472 iomove(cp, n, flag) 07473 register caddr_t cp; 07474 register n; 07475 { 07476 register t; 07477 07478 if (n==0) 07479 return; 07480 if(u.u_segflg != 1 && 07481 (n&(NBPW-1)) == 0 && 07482 ((int)cp&(NBPW-1)) == 0 && 07483 ((int)u.u_base&(NBPW-1)) == 0) { 07484 if (flag==B_WRITE) 07485 if (u.u_segflg==0) 07486 t = copyin(u.u_base, (caddr_t)cp, n); 07487 else 07488 t = copyiin(u.u_base, (caddr_t)cp, n); 07489 else 07490 if (u.u_segflg==0) 07491 t = copyout((caddr_t)cp, u.u_base, n); 07492 else 07493 t = copyiout((caddr_t)cp, u.u_base, n); 07494 if (t) { 07495 u.u_error = EFAULT; 07496 return; 07497 } 07498 u.u_base += n; 07499 u.u_offset += n; 07500 u.u_count -= n; 07501 return; 07502 } 07503 if (flag==B_WRITE) { 07504 do { 07505 if ((t = cpass()) < 0) 07506 return; 07507 *cp++ = t; 07508 } while (--n); 07509 } else 07510 do { 07511 if(passc(*cp++) < 0) 07512 return; 07513 } while (--n); 07514 } 07515 07516 07517 07518 07519 07520 07521 07522 07523 07524 07525 07526 07527 07528 07529 07530 07531 07532 07533 07534 07535 07536 07537 07538 07539 07540 07541 07542 07543 07544 07545 07546 07547 07548 07549