+/*
+ * Do consistency checking on a directory entry:
+ * record length must be multiple of 4
+ * 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
+ */
+int
+ufs_dirbadentry(ep, entryoffsetinblock)
+ register struct direct *ep;
+ int entryoffsetinblock;
+{
+ register int i;
+
+ if ((ep->d_reclen & 0x3) != 0 ||
+ ep->d_reclen > DIRBLKSIZ - (entryoffsetinblock & (DIRBLKSIZ - 1)) ||
+ ep->d_reclen < DIRSIZ(ep) || ep->d_namlen > MAXNAMLEN) {
+ /*return (1); */
+ printf("First bad\n");
+ goto bad;
+ }
+ for (i = 0; i < ep->d_namlen; i++)
+ if (ep->d_name[i] == '\0') {
+ /*return (1); */
+ printf("Second bad\n");
+ goto bad;
+ }
+ if (ep->d_name[i])
+ goto bad;
+ return (ep->d_name[i]);
+bad:
+printf("ufs_dirbadentry: jumping out: reclen: %d namlen %d ino %d name %s\n",
+ ep->d_reclen, ep->d_namlen, ep->d_ino, ep->d_name );
+ return(1);
+}
+
+/*
+ * Write a directory entry after a call to namei, using the parameters
+ * that it left in nameidata. The argument ip is the inode which the new
+ * directory entry will refer to. The nameidata field ndp->ni_dvp is a
+ * pointer to the directory to be written, which was left locked by namei.
+ * Remaining parameters (ndp->ni_ufs.ufs_offset, ndp->ni_ufs.ufs_count)
+ * indicate how the space for the new entry is to be obtained.
+ */
+int
+ufs_direnter(ip, ndp)
+ struct inode *ip;
+ register struct nameidata *ndp;
+{
+ register struct direct *ep, *nep;
+ register struct inode *dp;
+ register struct vnode *dvp;
+ struct buf *bp;
+ struct direct newdir;
+ struct iovec aiov;
+ struct uio auio;
+ u_int dsize;
+ int error, loc, newentrysize, spacefree;
+ char *dirbuf;
+
+#ifdef DIAGNOSTIC
+ if ((ndp->ni_nameiop & SAVENAME) == 0)
+ panic("direnter: missing name");
+#endif
+ dvp = ndp->ni_dvp;
+ dp = VTOI(dvp);
+ newdir.d_ino = ip->i_number;
+ newdir.d_namlen = ndp->ni_namelen;
+ bcopy(ndp->ni_ptr, newdir.d_name, (unsigned)ndp->ni_namelen + 1);
+ newentrysize = DIRSIZ(&newdir);
+ if (ndp->ni_ufs.ufs_count == 0) {
+ /*
+ * If ndp->ni_ufs.ufs_count is 0, then namei could find no
+ * space in the directory. Here, ndp->ni_ufs.ufs_offset will
+ * be on a directory block boundary and we will write the
+ * new entry into a fresh block.
+ */
+ if (ndp->ni_ufs.ufs_offset & (DIRBLKSIZ - 1))
+ panic("wdir: newblk");
+ auio.uio_offset = ndp->ni_ufs.ufs_offset;
+ newdir.d_reclen = DIRBLKSIZ;
+ auio.uio_resid = newentrysize;
+ aiov.iov_len = newentrysize;
+ aiov.iov_base = (caddr_t)&newdir;
+ auio.uio_iov = &aiov;
+ auio.uio_iovcnt = 1;
+ auio.uio_rw = UIO_WRITE;
+ auio.uio_segflg = UIO_SYSSPACE;
+ auio.uio_procp = (struct proc *)0;
+ error = VOP_WRITE(dvp, &auio, IO_SYNC, ndp->ni_cred);
+ if (DIRBLKSIZ >
+ VFSTOUFS(dvp->v_mount)->um_mountp->mnt_stat.f_bsize)
+ /* XXX should grow with balloc() */
+ panic("ufs_direnter: frag size");
+ else if (!error) {
+ dp->i_size = roundup(dp->i_size, DIRBLKSIZ);
+ dp->i_flag |= ICHG;