-/*
- * Write the file corresponding to
- * the inode pointed at by the argument.
- * The actual write arguments are found
- * in the variables:
- * u_base core address for source
- * u_offset byte offset in file
- * u_count number of bytes to write
- * u_segflg write to kernel/user/user I
- */
-writei(ip)
- register struct inode *ip;
-{
- struct buf *bp;
- register struct fs *fs;
- dev_t dev;
- daddr_t lbn, bn;
- register int on, type;
- register unsigned n;
- long bsize;
- int size, i, count;
- extern int mem_no;
-
- dev = (dev_t)ip->i_rdev;
- if (u.u_offset < 0 && ((ip->i_mode&IFMT) != IFCHR ||
- mem_no != major(dev)) ) {
- u.u_error = EINVAL;
- return;
- }
- type = ip->i_mode & IFMT;
- if (type == IFCHR) {
- ip->i_flag |= IUPD|ICHG;
- CHARGE(sc_tio * u.u_count);
- (*cdevsw[major(dev)].d_write)(dev);
- return;
- }
- if (u.u_count == 0)
- return;
- if ((ip->i_mode & IFMT) == IFREG &&
- u.u_offset + u.u_count > u.u_limit[LIM_FSIZE]) {
- psignal(u.u_procp, SIGXFSZ);
- u.u_error = EMFILE;
- return;
- }
- if (type!=IFBLK) {
- dev = ip->i_dev;
- fs = ip->i_fs;
- bsize = fs->fs_bsize;
- } else
- bsize = BLKDEV_IOSIZE;
- do {
- lbn = u.u_offset / bsize;
- on = u.u_offset % bsize;
- n = MIN((unsigned)(bsize - on), u.u_count);
- if (type != IFBLK) {
- bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, (int)(on + n)));
- if (u.u_error || (long)bn<0)
- return;
- if(u.u_offset + n > ip->i_size &&
- (type == IFDIR || type == IFREG || type == IFLNK))
- ip->i_size = u.u_offset + n;
- size = blksize(fs, ip, lbn);
- } else {
- size = bsize;
- bn = lbn * (BLKDEV_IOSIZE/DEV_BSIZE);
- }
- count = howmany(size, DEV_BSIZE);
- for (i = 0; i < count; i += CLSIZE)
- if (mfind(dev, bn + i))
- munhash(dev, bn + i);
- if (n == bsize)
- bp = getblk(dev, bn, size);
- else
- bp = bread(dev, bn, size);
- if (u.u_segflg != 1) {
- if (copyin(u.u_base, bp->b_un.b_addr + on, n)) {
- u.u_error = EFAULT;
- goto bad;
- }
- } else
- bcopy(u.u_base, bp->b_un.b_addr + on, n);
- u.u_base += n;
- u.u_offset += n;
- u.u_count -= n;
-bad:
- ;
- if (u.u_error != 0)
- brelse(bp);
- else {
- if ((ip->i_mode&IFMT) == IFDIR)
- /*
- * Writing to clear a directory entry.
- * Must insure the write occurs before
- * the inode is freed, or may end up
- * pointing at a new (different) file
- * if inode is quickly allocated again
- * and system crashes.
- */
- bwrite(bp);
- else if (n + on == bsize) {
- bp->b_flags |= B_AGE;
- bawrite(bp);
- } else
- bdwrite(bp);
- }
- ip->i_flag |= IUPD|ICHG;
- if (u.u_ruid != 0)
- ip->i_mode &= ~(ISUID|ISGID);
- } while (u.u_error == 0 && u.u_count != 0);
-}
-
-/*
- * Move n bytes at byte location
- * &bp->b_un.b_addr[o] to/from (flag) the
- * user/kernel (u.segflg) area starting at u.base.
- * Update all the arguments by the number
- * of bytes moved.
- */
-iomove(cp, n, flag)
- register caddr_t cp;
- register unsigned n;