/* sys_directory.c 5.8 83/01/01 */ #include "../machine/reg.h" #include "../h/param.h" #include "../h/systm.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/inode.h" #include "../h/proc.h" #include "../h/timeb.h" #include "../h/times.h" #include "../h/reboot.h" #include "../h/fs.h" #include "../h/conf.h" #include "../h/buf.h" #include "../h/mount.h" #include "../h/quota.h" #include "../h/nami.h" #include "../h/kernel.h" #include "../h/uio.h" /* * A virgin directory (no blushing please). */ struct dirtemplate dirtemplate = { 0, 12, 1, ".", 0, DIRBLKSIZ - 12, 2, ".." }; /* * Mkdir system call */ mkdir() { struct a { char *name; int dmode; } *uap; register struct inode *ip, *dp; uap = (struct a *)u.u_ap; ip = namei(uchar, CREATE, 0); if (u.u_error) return; if (ip != NULL) { iput(ip); u.u_error = EEXIST; return; } dp = u.u_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.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; } /* * Directory all set up, now * install the entry for it in * the parent directory. */ direnter(ip); dp = NULL; if (u.u_error) { u.u_dirp = uap->name; dp = namei(uchar, LOOKUP, 0); if (dp) { dp->i_nlink--; dp->i_flag |= ICHG; } } bad: /* * No need to do an explicit itrunc here, * irele will do this for us because we set * the link count to 0. */ if (u.u_error) { ip->i_nlink = 0; ip->i_flag |= ICHG; } if (dp) iput(dp); iput(ip); } /* * Rmdir system call. */ rmdir() { struct a { char *name; }; register struct inode *ip, *dp; ip = namei(uchar, DELETE | LOCKPARENT, 0); if (ip == NULL) return; dp = u.u_pdir; /* * No rmdir "." please. */ if (dp == ip) { irele(dp); iput(ip); u.u_error = EINVAL; return; } if ((ip->i_mode&IFMT) != IFDIR) { u.u_error = ENOTDIR; goto out; } /* * Don't remove a mounted on directory. */ if (ip->i_dev != dp->i_dev) { u.u_error = EBUSY; goto out; } /* * Verify the directory is empty. * (Rmdir ".." won't be valid since * ".." will contain a reference to * the current directory and thus be * non-empty.) */ if (!dirempty(ip)) { u.u_error = ENOTEMPTY; goto out; } /* * Delete reference to directory before purging * inode. If we crash in between, the directory * will be reattached to lost+found, */ if (dirremove() == 0) goto out; dp->i_nlink--; dp->i_flag |= ICHG; iput(dp); dp = NULL; /* * Truncate inode. The only stuff left * in the directory is "." and "..". The * "." reference is inconsequential since * we're quashing it. The ".." reference * has already been adjusted above. */ ip->i_nlink = 0; itrunc(ip, (u_long)0); out: if (dp) iput(dp); iput(ip); }