-
-/*
- * Remove a directory entry after a call to namei, using the
- * parameters which it left in the u. area. The u. entry
- * u_offset contains the offset into the directory of the
- * entry to be eliminated. The u_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()
-{
- register struct inode *dp = u.u_pdir;
- register struct buf *bp;
- struct direct *ep;
-
- if (u.u_count == 0) {
- /*
- * First entry in block: set d_ino to zero.
- */
- u.u_dent.d_ino = 0;
- (void) rdwri(UIO_WRITE, dp, (caddr_t)&u.u_dent,
- (int)DIRSIZ(&u.u_dent), u.u_offset, 1, (int *)0);
- } else {
- /*
- * Collapse new free space into previous entry.
- */
- bp = blkatoff(dp, (int)(u.u_offset - u.u_count), (char **)&ep);
- if (bp == 0)
- return (0);
- ep->d_reclen += u.u_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)
- struct inode *dp, *ip;
-{
-
- u.u_dent.d_ino = ip->i_number;
- u.u_error = rdwri(UIO_WRITE, dp, (caddr_t)&u.u_dent,
- (int)DIRSIZ(&u.u_dent), u.u_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.
- */
-dirempty(ip)
- register struct inode *ip;
-{
- register off_t off;
- struct direct dbuf;
- register struct direct *dp = &dbuf;
- int error, count;
-
- for (off = 0; off < ip->i_size; off += dp->d_reclen) {
- error = rdwri(UIO_READ, ip, (caddr_t)dp,
- sizeof (struct direct), off, 1, &count);
- count = sizeof (struct direct) - count;
-#define MINDIRSIZ (sizeof (struct direct) - (MAXNAMLEN + 1))
- if (error || count < MINDIRSIZ || count < DIRSIZ(dp))
- return (0);
- if (dp->d_ino == 0)
- continue;
- if (dp->d_name[0] != '.')
- return (0);
- if (dp->d_namlen == 1 ||
- (dp->d_namlen == 2 && dp->d_name[1] == '.'))
- continue;
- return (0);
- }
- return (1);
-}