+ ip->i_flag |= IACC|IUPD|ICHG;
+ if ((mode & IFMT) == 0)
+ mode |= IFREG;
+ ip->i_mode = mode & ~u.u_cmask;
+ ip->i_nlink = 1;
+ ip->i_uid = u.u_uid;
+ ip->i_gid = pdir->i_gid;
+ if (ip->i_mode & ISGID && !groupmember(ip->i_gid))
+ ip->i_mode &= ~ISGID;
+#ifdef QUOTA
+ ip->i_dquot = inoquota(ip);
+#endif
+
+ /*
+ * Make sure inode goes to disk before directory entry.
+ */
+ iupdat(ip, &time, &time, 1);
+ u.u_error = direnter(ip, ndp);
+ if (u.u_error) {
+ /*
+ * Write error occurred trying to update directory
+ * so must deallocate the inode.
+ */
+ ip->i_nlink = 0;
+ ip->i_flag |= ICHG;
+ iput(ip);
+ return (NULL);
+ }
+ return (ip);
+}
+
+/*
+ * A virgin directory (no blushing please).
+ */
+struct dirtemplate mastertemplate = {
+ 0, 12, 1, ".",
+ 0, DIRBLKSIZ - 12, 2, ".."
+};
+
+/*
+ * Mkdir system call
+ */
+mkdir()
+{
+ struct a {
+ char *name;
+ int dmode;
+ } *uap = (struct a *)u.u_ap;
+ register struct inode *ip, *dp;
+ struct dirtemplate dirtemplate;
+ register struct nameidata *ndp = &u.u_nd;
+
+ ndp->ni_nameiop = CREATE;
+ ndp->ni_segflg = UIO_USERSPACE;
+ ndp->ni_dirp = uap->name;
+ ip = namei(ndp);
+ if (u.u_error)
+ return;
+ if (ip != NULL) {
+ iput(ip);
+ u.u_error = EEXIST;
+ return;
+ }
+ dp = ndp->ni_pdir;
+ uap->dmode &= 0777;
+ uap->dmode |= IFDIR;
+ /*
+ * Must simulate part of maknode here
+ * in order to acquire the inode, but
+ * not have it entered in the parent
+ * directory. The entry is made later
+ * after writing "." and ".." entries out.
+ */
+ ip = ialloc(dp, dirpref(dp->i_fs), uap->dmode);
+ if (ip == NULL) {
+ iput(dp);
+ return;
+ }
+#ifdef QUOTA
+ if (ip->i_dquot != NODQUOT)
+ panic("mkdir: dquot");
+#endif
+ ip->i_flag |= IACC|IUPD|ICHG;
+ ip->i_mode = uap->dmode & ~u.u_cmask;
+ ip->i_nlink = 2;
+ ip->i_uid = u.u_uid;
+ ip->i_gid = dp->i_gid;
+#ifdef QUOTA
+ ip->i_dquot = inoquota(ip);
+#endif
+ iupdat(ip, &time, &time, 1);
+
+ /*
+ * Bump link count in parent directory
+ * to reflect work done below. Should
+ * be done before reference is created
+ * so reparation is possible if we crash.
+ */
+ dp->i_nlink++;
+ dp->i_flag |= ICHG;
+ iupdat(dp, &time, &time, 1);
+
+ /*
+ * Initialize directory with "."
+ * and ".." from static template.
+ */
+ dirtemplate = mastertemplate;
+ dirtemplate.dot_ino = ip->i_number;
+ dirtemplate.dotdot_ino = dp->i_number;
+ u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&dirtemplate,
+ sizeof (dirtemplate), (off_t)0, 1, (int *)0);
+ if (u.u_error) {
+ dp->i_nlink--;
+ dp->i_flag |= ICHG;
+ goto bad;