BSD 4_1c_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Sat, 1 Jan 1983 10:13:33 +0000 (02:13 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Sat, 1 Jan 1983 10:13:33 +0000 (02:13 -0800)
Work on file a/sys/sys/sys_directory.c

Synthesized-from: CSRG/cd1/4.1c.2

a/sys/sys/sys_directory.c [new file with mode: 0644]

diff --git a/a/sys/sys/sys_directory.c b/a/sys/sys/sys_directory.c
new file mode 100644 (file)
index 0000000..b12585b
--- /dev/null
@@ -0,0 +1,202 @@
+/*     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);
+}