-}
-
-/*
- * Make a new file.
- */
-struct inode *
-maknode(mode)
- int mode;
-{
- register struct inode *ip;
- ino_t ipref;
-
- if ((mode & IFMT) == IFDIR)
- ipref = dirpref(u.u_pdir->i_fs);
- else
- ipref = u.u_pdir->i_number;
- ip = ialloc(u.u_pdir, ipref, mode);
- if (ip == NULL) {
- iput(u.u_pdir);
- return(NULL);
- }
- ip->i_flag |= IACC|IUPD|ICHG;
- if ((mode & IFMT) == 0)
- mode |= IFREG;
- ip->i_mode = mode & ~u.u_cmask;
- ip->i_nlink = 1;
- ip->i_uid = u.u_uid;
- ip->i_gid = u.u_pdir->i_gid;
-
- /*
- * Make sure inode goes to disk before directory entry.
- */
- iupdat(ip, &time, &time, 1);
- wdir(ip);
- if (u.u_error) {
- /*
- * write error occurred trying to update directory
- * so must deallocate the inode
- */
- ip->i_nlink = 0;
- ip->i_flag |= ICHG;
- iput(ip);
- return(NULL);
- }
- return(ip);
-}
-
-/*
- * Write a directory entry with
- * parameters left as side effects
- * to a call to namei.
- */
-wdir(ip)
- struct inode *ip;
-{
- register struct direct *dp, *ndp;
- struct fs *fs;
- struct buf *bp;
- int lbn, bn, base;
- int loc, dsize, spccnt, newsize;
- char *dirbuf;
-
- u.u_dent.d_ino = ip->i_number;
- u.u_segflg = 1;
- newsize = DIRSIZ(&u.u_dent);
- /*
- * if u.u_count == 0, a new directory block must be allocated.
- */
- if (u.u_count == 0) {
- u.u_dent.d_reclen = DIRBLKSIZ;
- u.u_count = newsize;
- u.u_base = (caddr_t)&u.u_dent;
- writei(u.u_pdir);
- iput(u.u_pdir);
- return;
- }
- /*
- * must read in an existing directory block
- * to prepare to place the new entry into it.
- */
- fs = u.u_pdir->i_fs;
- lbn = lblkno(fs, u.u_offset);
- base = blkoff(fs, u.u_offset);
- bn = fsbtodb(fs, bmap(u.u_pdir, lbn, B_WRITE, base + u.u_count));
- if (u.u_offset + u.u_count > u.u_pdir->i_size)
- u.u_pdir->i_size = u.u_offset + u.u_count;
- bp = bread(u.u_pdir->i_dev, bn, blksize(fs, u.u_pdir, lbn));
- if (bp->b_flags & B_ERROR) {
- brelse(bp);
- return;
- }
- dirbuf = bp->b_un.b_addr + base;
- dp = (struct direct *)dirbuf;
- dsize = DIRSIZ(dp);
- spccnt = dp->d_reclen - dsize;
- /*
- * if there is insufficient room to make an entry at this point
- * namei insures that compacting from u.u_offset for u.u_count
- * bytes will provide the necessary space.
- */
- for (loc = dp->d_reclen; loc < u.u_count; ) {
- ndp = (struct direct *)(dirbuf + loc);
- if (dp->d_ino == 0) {
- spccnt += dsize;
- } else {
- dp->d_reclen = dsize;
- dp = (struct direct *)((char *)dp + dsize);
- }
- dsize = DIRSIZ(ndp);
- spccnt += ndp->d_reclen - dsize;
- loc += ndp->d_reclen;
- bcopy(ndp, dp, dsize);
- }
- /*
- * Update the pointer fields in the previous entry (if any),
- * copy in the new entry, and write out the block.
- */
- if (dp->d_ino == 0) {
- if (spccnt + dsize < newsize)
- panic("wdir: compact failed");
- u.u_dent.d_reclen = spccnt + dsize;
- } else {
- if (spccnt < newsize)
- panic("wdir: compact failed");
- u.u_dent.d_reclen = spccnt;
- dp->d_reclen = dsize;
- dp = (struct direct *)((char *)dp + dsize);
- }
- bcopy(&u.u_dent, dp, newsize);
- bwrite(bp);
- u.u_pdir->i_flag |= IUPD|ICHG;
- iput(u.u_pdir);