- if (*cp == '/') {
- while (*cp == '/')
- cp++;
- irele(pdp);
- goto dirloop;
- }
- nbp->av_forw = freenamebuf;
- freenamebuf = nbp;
- if (lockparent)
- ndp->ni_pdir = pdp;
- else
- irele(pdp);
- return (dp);
-bad2:
- irele(pdp);
-bad:
- if (bp)
- brelse(bp);
- if (dp)
- iput(dp);
- nbp->av_forw = freenamebuf;
- freenamebuf = nbp;
- return (NULL);
-}
-
-
-dirbad(ip, offset, how)
- struct inode *ip;
- off_t offset;
- char *how;
-{
-
- printf("%s: bad dir ino %d at offset %d: %s\n",
- ip->i_fs->fs_fsmnt, ip->i_number, offset, how);
-}
-
-/*
- * Do consistency checking on a directory entry:
- * record length must be multiple of 4
- * record length must not be non-negative
- * entry must fit in rest of its DIRBLKSIZ block
- * record must be large enough to contain entry
- * name is not longer than MAXNAMLEN
- * name must be as long as advertised, and null terminated
- */
-dirbadentry(ep, entryoffsetinblock)
- register struct direct *ep;
- int entryoffsetinblock;
-{
- register int i;
-
- if ((ep->d_reclen & 0x3) != 0 || ep->d_reclen <= 0 ||
- ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
- ep->d_reclen < DIRSIZ(ep) || ep->d_namlen > MAXNAMLEN)
- return (1);
- for (i = 0; i < ep->d_namlen; i++)
- if (ep->d_name[i] == '\0')
- return (1);
- return (ep->d_name[i]);
-}
-
-/*
- * Write a directory entry after a call to namei, using the parameters
- * which it left in the u. area. The argument ip is the inode which
- * the new directory entry will refer to. The u. area field ndp->ni_pdir is
- * a pointer to the directory to be written, which was left locked by
- * namei. Remaining parameters (ndp->ni_offset, ndp->ni_count) indicate
- * how the space for the new entry is to be gotten.
- */
-direnter(ip, ndp)
- struct inode *ip;
- register struct nameidata *ndp;
-{
- register struct direct *ep, *nep;
- register struct inode *dp = ndp->ni_pdir;
- struct buf *bp;
- int loc, spacefree, error = 0;
- u_int dsize;
- int newentrysize;
- char *dirbuf;
-
- ndp->ni_dent.d_ino = ip->i_number;
- newentrysize = DIRSIZ(&ndp->ni_dent);
- if (ndp->ni_count == 0) {
- /*
- * If ndp->ni_count is 0, then namei could find no space in the
- * directory. In this case ndp->ni_offset will be on a directory
- * block boundary and we will write the new entry into a fresh
- * block.
- */
- if (ndp->ni_offset&(DIRBLKSIZ-1))
- panic("wdir: newblk");
- ndp->ni_dent.d_reclen = DIRBLKSIZ;
- error = rdwri(UIO_WRITE, dp, (caddr_t)&ndp->ni_dent,
- newentrysize, ndp->ni_offset, 1, (int *)0);
- if (DIRBLKSIZ > dp->i_fs->fs_fsize)
- panic("wdir: blksize"); /* XXX - should grow w/bmap() */
- else
- dp->i_size = roundup(dp->i_size, DIRBLKSIZ);
- iput(dp);
- return (error);
- }
-
- /*
- * If ndp->ni_count is non-zero, then namei found space for the new
- * entry in the range ndp->ni_offset to ndp->ni_offset + ndp->ni_count.
- * in the directory. To use this space, we may have to compact
- * the entries located there, by copying them together towards
- * the beginning of the block, leaving the free space in
- * one usable chunk at the end.
- */
-
- /*
- * Increase size of directory if entry eats into new space.
- * This should never push the size past a new multiple of
- * DIRBLKSIZE.
- *
- * N.B. - THIS IS AN ARTIFACT OF 4.2 AND SHOULD NEVER HAPPEN.
- */
- if (ndp->ni_offset + ndp->ni_count > dp->i_size)
- dp->i_size = ndp->ni_offset + ndp->ni_count;
-
- /*
- * Get the block containing the space for the new directory
- * entry. Should return error by result instead of u.u_error.
- */
- bp = blkatoff(dp, ndp->ni_offset, (char **)&dirbuf);
- if (bp == 0) {
- iput(dp);
- return (u.u_error);
- }
-
- /*
- * Find space for the new entry. In the simple case, the
- * entry at offset base will have the space. If it does
- * not, then namei arranged that compacting the region
- * ndp->ni_offset to ndp->ni_offset+ndp->ni_count would yield the space.
- */
- ep = (struct direct *)dirbuf;
- dsize = DIRSIZ(ep);
- spacefree = ep->d_reclen - dsize;
- for (loc = ep->d_reclen; loc < ndp->ni_count; ) {
- nep = (struct direct *)(dirbuf + loc);
- if (ep->d_ino) {
- /* trim the existing slot */
- ep->d_reclen = dsize;
- ep = (struct direct *)((char *)ep + dsize);
- } else {
- /* overwrite; nothing there; header is ours */
- spacefree += dsize;