+direnter(ip)
+ struct inode *ip;
+{
+ register struct direct *ep, *nep;
+ struct buf *bp;
+ int loc, freespace;
+ u_int dsize, newentrysize;
+ char *dirbuf;
+
+ u.u_dent.d_ino = ip->i_number;
+ u.u_segflg = 1;
+ newentrysize = DIRSIZ(&u.u_dent);
+ if (u.u_count == 0) {
+ /*
+ * If u.u_count is 0, then namei could find no space in the
+ * directory. In this case u.u_offset will be on a directory
+ * block boundary and we will write the new entry into a fresh
+ * block.
+ */
+ if (u.u_offset&(DIRBLKSIZ-1))
+ panic("wdir: newblk");
+ u.u_dent.d_reclen = DIRBLKSIZ;
+ (void) rdwri(UIO_WRITE, u.u_pdir, (caddr_t)&u.u_dent, newentrysize,
+ u.u_offset, 1, (int *)0);
+ iput(u.u_pdir);
+ return;
+ }
+
+ /*
+ * If u.u_count is non-zero, then namei found space for the
+ * new entry in the range u.u_offset to u.u_offset+u.u_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.
+ */
+ if (u.u_offset+u.u_count > u.u_pdir->i_size) {
+/*ZZ*/ if (((u.u_offset+u.u_count-1)&~(DIRBLKSIZ-1)) !=
+/*ZZ*/ ((u.u_pdir->i_size-1)&~(DIRBLKSIZ-1))) {
+/*ZZ*/ panic("wdir: span");
+/*ZZ*/ }
+ u.u_pdir->i_size = u.u_offset + u.u_count;
+ }
+
+ /*
+ * Get the block containing the space for the new directory
+ * entry.
+ */
+ bp = blkatoff(u.u_pdir, u.u_offset, (char **)&dirbuf);
+ if (bp == 0)
+ return;
+
+ /*
+ * 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
+ * u.u_offset to u.u_offset+u.u_count would yield the space.
+ */
+ ep = (struct direct *)dirbuf;
+ dsize = DIRSIZ(ep);
+ freespace = ep->d_reclen - dsize;
+ for (loc = ep->d_reclen; loc < u.u_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 */
+ freespace += dsize;
+ }
+ dsize = DIRSIZ(nep);
+ freespace += nep->d_reclen - dsize;
+ loc += nep->d_reclen;
+/*ZZ*/if((loc&~0x1ff)!=(loc+nep->d_reclen-1&~0x1ff))
+/*ZZ*/printf("wdir: compact loc %d reclen %d (dir %s/%d)\n",loc,nep->d_reclen,
+/*ZZ*/u.u_pdir->i_fs->fs_fsmnt,u.u_pdir->i_number);
+ bcopy((caddr_t)nep, (caddr_t)ep, dsize);
+ }
+ /*
+ * Update the pointer fields in the previous entry (if any),
+ * copy in the new entry, and write out the block.
+ */
+ if (ep->d_ino == 0) {
+ if (freespace + dsize < newentrysize)
+ panic("wdir: compact1");
+/*ZZ*/if(freespace+dsize>512)panic("wdir: compact screwup");
+ u.u_dent.d_reclen = freespace + dsize;
+ } else {
+ if (freespace < newentrysize)
+ panic("wdir: compact2");
+ u.u_dent.d_reclen = freespace;
+/*ZZ*/if ((((char *)ep-bp->b_un.b_addr)&0x1ff)+dsize>512) panic("wdir: reclen");
+ ep->d_reclen = dsize;
+ ep = (struct direct *)((char *)ep + dsize);
+ }
+/*ZZ*/if((((char*)ep-bp->b_un.b_addr)&0x1ff)+u.u_dent.d_reclen>512)panic("wdir: botch");
+ bcopy(&u.u_dent, ep, newentrysize);
+ bwrite(bp);
+ u.u_pdir->i_flag |= IUPD|ICHG;
+ iput(u.u_pdir);
+}
+
+dirremove()