- if (ep->d_ino == 0) {
- if (spacefree + dsize < newentrysize)
- panic("wdir: compact1");
- ndp->ni_dent.d_reclen = spacefree + dsize;
- } else {
- if (spacefree < newentrysize)
- panic("wdir: compact2");
- ndp->ni_dent.d_reclen = spacefree;
- ep->d_reclen = dsize;
- ep = (struct direct *)((char *)ep + dsize);
- }
- bcopy((caddr_t)&ndp->ni_dent, (caddr_t)ep, (u_int)newentrysize);
- bwrite(bp);
- ndp->ni_pdir->i_flag |= IUPD|ICHG;
- iput(ndp->ni_pdir);
- return (error);
-}
-
-/*
- * Remove a directory entry after a call to namei, using the
- * parameters which it left in the u. area. The u. entry
- * ni_offset contains the offset into the directory of the
- * entry to be eliminated. The ni_count field contains the
- * size of the previous record in the directory. If this
- * is 0, the first entry is being deleted, so we need only
- * zero the inode number to mark the entry as free. If the
- * entry isn't the first in the directory, we must reclaim
- * the space of the now empty record by adding the record size
- * to the size of the previous entry.
- */
-dirremove(ndp)
- register struct nameidata *ndp;
-{
- register struct inode *dp = ndp->ni_pdir;
- register struct buf *bp;
- struct direct *ep;
-
- if (ndp->ni_count == 0) {
- /*
- * First entry in block: set d_ino to zero.
- */
- ndp->ni_dent.d_ino = 0;
- (void) rdwri(UIO_WRITE, dp, (caddr_t)&ndp->ni_dent,
- (int)DIRSIZ(&ndp->ni_dent), ndp->ni_offset, 1, (int *)0);
- } else {
- /*
- * Collapse new free space into previous entry.
- */
- bp = blkatoff(dp, (int)(ndp->ni_offset - ndp->ni_count),
- (char **)&ep);
- if (bp == 0)
- return (0);
- ep->d_reclen += ndp->ni_dent.d_reclen;
- bwrite(bp);
- dp->i_flag |= IUPD|ICHG;
- }
- return (1);
-}
-
-/*
- * Rewrite an existing directory entry to point at the inode
- * supplied. The parameters describing the directory entry are
- * set up by a call to namei.
- */
-dirrewrite(dp, ip, ndp)
- struct inode *dp, *ip;
- struct nameidata *ndp;
-{
-
- ndp->ni_dent.d_ino = ip->i_number;
- u.u_error = rdwri(UIO_WRITE, dp, (caddr_t)&ndp->ni_dent,
- (int)DIRSIZ(&ndp->ni_dent), ndp->ni_offset, 1, (int *)0);
- iput(dp);
-}
-
-/*
- * Return buffer with contents of block "offset"
- * from the beginning of directory "ip". If "res"
- * is non-zero, fill it in with a pointer to the
- * remaining space in the directory.
- */
-struct buf *
-blkatoff(ip, offset, res)
- struct inode *ip;
- off_t offset;
- char **res;
-{
- register struct fs *fs = ip->i_fs;
- daddr_t lbn = lblkno(fs, offset);
- int base = blkoff(fs, offset);
- int bsize = blksize(fs, ip, lbn);
- daddr_t bn = fsbtodb(fs, bmap(ip, lbn, B_WRITE, base, bsize));
- register struct buf *bp;
-
- if (u.u_error)
- return (0);
- bp = bread(ip->i_dev, bn, bsize);
- if (bp->b_flags & B_ERROR) {
- brelse(bp);
- return (0);
- }
- if (res)
- *res = bp->b_un.b_addr + base;
- return (bp);
-}
-
-/*
- * Check if a directory is empty or not.
- * Inode supplied must be locked.
- *
- * Using a struct dirtemplate here is not precisely
- * what we want, but better than using a struct direct.
- *
- * NB: does not handle corrupted directories.
- */
-dirempty(ip, parentino)
- register struct inode *ip;
- ino_t parentino;
-{
- register off_t off;
- struct dirtemplate dbuf;
- register struct direct *dp = (struct direct *)&dbuf;
- int error, count;
-#define MINDIRSIZ (sizeof (struct dirtemplate) / 2)
-
- for (off = 0; off < ip->i_size; off += dp->d_reclen) {
- error = rdwri(UIO_READ, ip, (caddr_t)dp, MINDIRSIZ,
- off, 1, &count);
- /*
- * Since we read MINDIRSIZ, residual must
- * be 0 unless we're at end of file.
- */
- if (error || count != 0)
- return (0);
- /* skip empty entries */
- if (dp->d_ino == 0)
- continue;
- /* accept only "." and ".." */
- if (dp->d_namlen > 2)
- return (0);
- if (dp->d_name[0] != '.')
- return (0);