Research V7 development
authorKen Thompson <ken@research.uucp>
Mon, 7 May 1979 06:23:11 +0000 (01:23 -0500)
committerKen Thompson <ken@research.uucp>
Mon, 7 May 1979 06:23:11 +0000 (01:23 -0500)
Work on file usr/sys/sys/nami.c

Synthesized-from: v7

usr/sys/sys/nami.c [new file with mode: 0644]

diff --git a/usr/sys/sys/nami.c b/usr/sys/sys/nami.c
new file mode 100644 (file)
index 0000000..b310575
--- /dev/null
@@ -0,0 +1,224 @@
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/inode.h"
+#include "../h/mount.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/buf.h"
+
+/*
+ * Convert a pathname into a pointer to
+ * an inode. Note that the inode is locked.
+ *
+ * func = function called to get next char of name
+ *     &uchar if name is in user space
+ *     &schar if name is in system space
+ * flag = 0 if name is sought
+ *     1 if name is to be created
+ *     2 if name is to be deleted
+ */
+struct inode *
+namei(func, flag)
+int (*func)();
+{
+       register struct inode *dp;
+       register c;
+       register char *cp;
+       struct buf *bp;
+       int i;
+       dev_t d;
+       off_t eo;
+
+       /*
+        * If name starts with '/' start from
+        * root; otherwise start from current dir.
+        */
+
+       dp = u.u_cdir;
+       if((c=(*func)()) == '/')
+               if ((dp = u.u_rdir) == NULL)
+                       dp = rootdir;
+       iget(dp->i_dev, dp->i_number);
+       while(c == '/')
+               c = (*func)();
+       if(c == '\0' && flag != 0)
+               u.u_error = ENOENT;
+
+cloop:
+       /*
+        * Here dp contains pointer
+        * to last component matched.
+        */
+
+       if(u.u_error)
+               goto out;
+       if(c == '\0')
+               return(dp);
+
+       /*
+        * If there is another component,
+        * Gather up name into
+        * users' dir buffer.
+        */
+
+       cp = &u.u_dbuf[0];
+       while (c != '/' && c != '\0' && u.u_error == 0 ) {
+               if (mpxip!=NULL && c=='!')
+                       break;
+               if(cp < &u.u_dbuf[DIRSIZ])
+                       *cp++ = c;
+               c = (*func)();
+       }
+       while(cp < &u.u_dbuf[DIRSIZ])
+               *cp++ = '\0';
+       while(c == '/')
+               c = (*func)();
+       if (c == '!' && mpxip != NULL) {
+               iput(dp);
+               plock(mpxip);
+               mpxip->i_count++;
+               return(mpxip);
+       }
+
+seloop:
+       /*
+        * dp must be a directory and
+        * must have X permission.
+        */
+
+       if((dp->i_mode&IFMT) != IFDIR)
+               u.u_error = ENOTDIR;
+       access(dp, IEXEC);
+       if(u.u_error)
+               goto out;
+
+       /*
+        * set up to search a directory
+        */
+       u.u_offset = 0;
+       u.u_segflg = 1;
+       eo = 0;
+       bp = NULL;
+
+eloop:
+
+       /*
+        * If at the end of the directory,
+        * the search failed. Report what
+        * is appropriate as per flag.
+        */
+
+       if(u.u_offset >= dp->i_size) {
+               if(bp != NULL)
+                       brelse(bp);
+               if(flag==1 && c=='\0') {
+                       if(access(dp, IWRITE))
+                               goto out;
+                       u.u_pdir = dp;
+                       if(eo)
+                               u.u_offset = eo-sizeof(struct direct);
+                       else
+                               dp->i_flag |= IUPD|ICHG;
+                       return(NULL);
+               }
+               u.u_error = ENOENT;
+               goto out;
+       }
+
+       /*
+        * If offset is on a block boundary,
+        * read the next directory block.
+        * Release previous if it exists.
+        */
+
+       if((u.u_offset&BMASK) == 0) {
+               if(bp != NULL)
+                       brelse(bp);
+               bp = bread(dp->i_dev,
+                       bmap(dp, (daddr_t)(u.u_offset>>BSHIFT), B_READ));
+               if (bp->b_flags & B_ERROR) {
+                       brelse(bp);
+                       goto out;
+               }
+       }
+
+       /*
+        * Note first empty directory slot
+        * in eo for possible creat.
+        * String compare the directory entry
+        * and the current component.
+        * If they do not match, go back to eloop.
+        */
+
+       bcopy(bp->b_un.b_addr+(u.u_offset&BMASK), (caddr_t)&u.u_dent,
+               sizeof(struct direct));
+       u.u_offset += sizeof(struct direct);
+       if(u.u_dent.d_ino == 0) {
+               if(eo == 0)
+                       eo = u.u_offset;
+               goto eloop;
+       }
+       for(i=0; i<DIRSIZ; i++)
+               if(u.u_dbuf[i] != u.u_dent.d_name[i])
+                       goto eloop;
+
+       /*
+        * Here a component matched in a directory.
+        * If there is more pathname, go back to
+        * cloop, otherwise return.
+        */
+
+       if(bp != NULL)
+               brelse(bp);
+       if(flag==2 && c=='\0') {
+               if(access(dp, IWRITE))
+                       goto out;
+               return(dp);
+       }
+       d = dp->i_dev;
+       if(u.u_dent.d_ino == ROOTINO)
+       if(dp->i_number == ROOTINO)
+       if(u.u_dent.d_name[1] == '.')
+               for(i=1; i<NMOUNT; i++)
+                       if(mount[i].m_bufp != NULL)
+                       if(mount[i].m_dev == d) {
+                               iput(dp);
+                               dp = mount[i].m_inodp;
+                               dp->i_count++;
+                               plock(dp);
+                               goto seloop;
+                       }
+       iput(dp);
+       dp = iget(d, u.u_dent.d_ino);
+       if(dp == NULL)
+               return(NULL);
+       goto cloop;
+
+out:
+       iput(dp);
+       return(NULL);
+}
+
+/*
+ * Return the next character from the
+ * kernel string pointed at by dirp.
+ */
+schar()
+{
+
+       return(*u.u_dirp++ & 0377);
+}
+
+/*
+ * Return the next character from the
+ * user string pointed at by dirp.
+ */
+uchar()
+{
+       register c;
+
+       c = fubyte(u.u_dirp++);
+       if(c == -1)
+               u.u_error = EFAULT;
+       return(c);
+}