diff --git a/defs.h b/defs.h
index 24fd52b0631322668ca0dfbe249afe4b288bba2f..acf7b7c8a30522b293dafd8e449ebdc7c43361ea 100644
--- a/defs.h
+++ b/defs.h
@@ -121,24 +121,19 @@ void bwrite(struct buf*, uint);
 void brelse(struct buf*);
 
 // fs.c
+struct inode;
 void iinit(void);
-struct inode* iget(uint, uint);
 void ilock(struct inode*);
 void iunlock(struct inode*);
-void itrunc(struct inode*);
 void idecref(struct inode*);
 struct inode* iincref(struct inode*);
 void iput(struct inode*);
 struct inode* namei(char*);
-struct inode* nameiparent(char*, char**, int*);
 void stati(struct inode*, struct stat*);
 int readi(struct inode*, char*, uint, uint);
 int writei(struct inode*, char*, uint, uint);
 struct inode* mknod(char*, short, short, short);
-struct inode* dircreat(struct inode*, char*, int, short, short, short);
-struct inode* dirlookup(struct inode*, char*, int, uint*);
 int unlink(char*);
-void iupdate(struct inode*);
 int link(char*, char*);
 struct inode* igetroot(void);
 int mkdir(char *path);
diff --git a/fs.c b/fs.c
index 4731b5f0aaabc05fc6c2109082fc78fe3f85c61d..8c65f35208de934ec64e1a7611224bfa5d2cc9ff 100644
--- a/fs.c
+++ b/fs.c
@@ -24,6 +24,8 @@
 #include "dev.h"
 
 #define min(a, b) ((a) < (b) ? (a) : (b))
+static void itrunc(struct inode*);
+static void iupdate(struct inode*);
 
 // Blocks. 
 
@@ -278,7 +280,7 @@ ialloc(uint dev, short type)
 }
 
 // Copy inode, which has changed, from memory to disk.
-void
+static void
 iupdate(struct inode *ip)
 {
   struct buf *bp;
@@ -347,7 +349,7 @@ bmap(struct inode *ip, uint bn, int alloc)
 }
 
 // Truncate inode (discard contents).
-void
+static void
 itrunc(struct inode *ip)
 {
   int i, j;
@@ -451,14 +453,41 @@ writei(struct inode *ip, char *src, uint off, uint n)
 //
 // Directories are just inodes (files) filled with dirent structures.
 
+// Compare two names, which are strings with a max length of DIRSIZ.
+static int
+namecmp(const char *s, const char *t)
+{
+  int i;
+  
+  for(i=0; i<DIRSIZ; i++){
+    if(s[i] != t[i])
+      return s[i] - t[i];
+    if(s[i] == 0)
+      break;
+  }
+  return 0;
+}
+
+// Copy one name to another.
+static void
+namecpy(char *s, const char *t)
+{
+  int i;
+  
+  for(i=0; i<DIRSIZ && t[i]; i++)
+    s[i] = t[i];
+  for(; i<DIRSIZ; i++)
+    s[i] = 0;
+}
+
 // Look for a directory entry in a directory.
 // If not found, return -1.
 // If found:
 //   set *poff to the byte offset of the directory entry
 //   set *pinum to the inode number
 //   return 0.
-struct inode*
-dirlookup(struct inode *dp, char *name, int namelen, uint *poff)
+static struct inode*
+dirlookup(struct inode *dp, char *name, uint *poff)
 {
   uint off, inum;
   struct buf *bp;
@@ -474,8 +503,7 @@ dirlookup(struct inode *dp, char *name, int namelen, uint *poff)
         de++){
       if(de->inum == 0)
         continue;
-      if(memcmp(name, de->name, namelen) == 0 &&
-         (namelen == DIRSIZ || de->name[namelen]== 0)){
+      if(namecmp(name, de->name) == 0){
         // entry matches path element
         if(poff)
           *poff = off + (uchar*)de - bp->data;
@@ -491,15 +519,15 @@ dirlookup(struct inode *dp, char *name, int namelen, uint *poff)
 
 // Write a new directory entry (name, ino) into the directory dp.
 // Caller must have locked dp.
-int
-dirlink(struct inode *dp, char *name, int namelen, uint ino)
+static int
+dirlink(struct inode *dp, char *name, uint ino)
 {
   int off;
   struct dirent de;
   struct inode *ip;
 
   // Double-check that name is not present.
-  if((ip = dirlookup(dp, name, namelen, 0)) != 0){
+  if((ip = dirlookup(dp, name, 0)) != 0){
     idecref(ip);
     return -1;
   }
@@ -512,11 +540,8 @@ dirlink(struct inode *dp, char *name, int namelen, uint ino)
       break;
   }
 
+  namecpy(de.name, name);
   de.inum = ino;
-  if(namelen > DIRSIZ)
-    namelen = DIRSIZ;
-  memmove(de.name, name, namelen);
-  memset(de.name+namelen, 0, DIRSIZ-namelen);
   if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
     panic("dirwrite");
   
@@ -526,8 +551,8 @@ dirlink(struct inode *dp, char *name, int namelen, uint ino)
 // Create a new inode named name inside dp
 // and return its locked inode structure.
 // If name already exists, return 0.
-struct inode*
-dircreat(struct inode *dp, char *name, int namelen, short type, short major, short minor)
+static struct inode*
+dircreat(struct inode *dp, char *name, short type, short major, short minor)
 {
   struct inode *ip;
 
@@ -541,7 +566,7 @@ dircreat(struct inode *dp, char *name, int namelen, short type, short major, sho
   ip->nlink = 1;
   iupdate(ip);
   
-  if(dirlink(dp, name, namelen, ip->inum) < 0){
+  if(dirlink(dp, name, ip->inum) < 0){
     ip->nlink = 0;
     iupdate(ip);
     iput(ip);
@@ -568,16 +593,25 @@ dircreat(struct inode *dp, char *name, int namelen, short type, short major, sho
 //   skipelem("") = skipelem("////") = 0
 //
 static char*
-skipelem(char *path, char **name, int *len)
+skipelem(char *path, char *name)
 {
+  char *s;
+  int len;
+
   while(*path == '/')
     path++;
   if(*path == 0)
     return 0;
-  *name = path;
+  s = path;
   while(*path != '/' && *path != 0)
     path++;
-  *len = path - *name;
+  len = path - s;
+  if(len >= DIRSIZ)
+    memmove(name, s, DIRSIZ);
+  else{
+    memmove(name, s, len);
+    name[len] = 0;
+  }
   while(*path == '/')
     path++;
   return path;
@@ -593,11 +627,9 @@ skipelem(char *path, char **name, int *len)
 // NAMEI_DELETE: return locked parent inode, offset of dirent in *ret_off.
 //   return 0 if name doesn't exist.
 struct inode*
-_namei(char *path, int parent, char **pname, int *pnamelen)
+_namei(char *path, int parent, char *name)
 {
   struct inode *dp, *ip;
-  char *name;
-  int namelen;
   uint off;
 
   if(*path == '/')
@@ -606,22 +638,16 @@ _namei(char *path, int parent, char **pname, int *pnamelen)
     dp = iincref(cp->cwd);
   ilock(dp);
 
-  while((path = skipelem(path, &name, &namelen)) != 0){
-    // Truncate names in path to DIRSIZ chars.
-    if(namelen > DIRSIZ)
-      namelen = DIRSIZ;
-
+  while((path = skipelem(path, name)) != 0){
     if(dp->type != T_DIR)
       goto fail;
     
     if(parent && *path == '\0'){
       // Stop one level early.
-      *pname = name;
-      *pnamelen = namelen;
       return dp;
     }
 
-    if((ip = dirlookup(dp, name, namelen, &off)) == 0)
+    if((ip = dirlookup(dp, name, &off)) == 0)
       goto fail;
 
     iput(dp);
@@ -642,29 +668,27 @@ fail:
 struct inode*
 namei(char *path)
 {
-  return _namei(path, 0, 0, 0);
+  char name[DIRSIZ];
+  return _namei(path, 0, name);
 }
 
-struct inode*
-nameiparent(char *path, char **name, int *namelen)
+static struct inode*
+nameiparent(char *path, char *name)
 {
-  return _namei(path, 1, name, namelen);
+  return _namei(path, 1, name);
 }
 
-
-
 // Create the path and return its locked inode structure.
 // If cp already exists, return 0.
 struct inode*
 mknod(char *path, short type, short major, short minor)
 {
   struct inode *ip, *dp;
-  char *name;
-  int namelen;
+  char name[DIRSIZ];
 
-  if((dp = nameiparent(path, &name, &namelen)) == 0)
+  if((dp = nameiparent(path, name)) == 0)
     return 0;
-  ip = dircreat(dp, name, namelen, type, major, minor);
+  ip = dircreat(dp, name, type, major, minor);
   iput(dp);
   return ip;
 }
@@ -676,26 +700,21 @@ unlink(char *path)
   struct inode *ip, *dp;
   struct dirent de;
   uint off;
-  char *name;
-  int namelen;
+  char name[DIRSIZ];
 
-  if((dp = nameiparent(path, &name, &namelen)) == 0)
+  if((dp = nameiparent(path, name)) == 0)
     return -1;
-  if((ip = dirlookup(dp, name, namelen, &off)) == 0){
+
+  // Cannot unlink "." or "..".
+  if(namecmp(name, ".") == 0 || namecmp(name, "..") == 0){
     iput(dp);
     return -1;
   }
 
-  if(readi(dp, (char*)&de, off, sizeof(de)) != sizeof(de) || de.inum == 0)
-    panic("unlink no entry");
-  
-  // Cannot remove "." or ".." - the 2 and 3 count the trailing NUL.
-  if(memcmp(de.name, ".", 2) == 0 || memcmp(de.name, "..", 3) == 0){
-    idecref(ip);
+  if((ip = dirlookup(dp, name, &off)) == 0){
     iput(dp);
     return -1;
   }
-
   memset(&de, 0, sizeof(de));
   if(writei(dp, (char*)&de, off, sizeof(de)) != sizeof(de))
     panic("unlink dir write");
@@ -716,8 +735,7 @@ int
 link(char *old, char *new)
 {
   struct inode *ip, *dp;
-  char *name;
-  int namelen;
+  char name[DIRSIZ];
 
   if((ip = namei(old)) == 0)
     return -1;
@@ -727,11 +745,11 @@ link(char *old, char *new)
   }
   iunlock(ip);
 
-  if((dp = nameiparent(new, &name, &namelen)) == 0){
+  if((dp = nameiparent(new, name)) == 0){
     idecref(ip);
     return -1;
   }
-  if(dp->dev != ip->dev || dirlink(dp, name, namelen, ip->inum) < 0){
+  if(dp->dev != ip->dev || dirlink(dp, name, ip->inum) < 0){
     idecref(ip);
     iput(dp);
     return -1;
@@ -750,21 +768,20 @@ int
 mkdir(char *path)
 {
   struct inode *dp, *ip;
-  char *name;
-  int namelen;
+  char name[DIRSIZ];
   
   // XXX write ordering is screwy here- do we care?
-  if((dp = nameiparent(path, &name, &namelen)) == 0)
+  if((dp = nameiparent(path, name)) == 0)
     return -1;
   
-  if((ip = dircreat(dp, name, namelen, T_DIR, 0, 0)) == 0){
+  if((ip = dircreat(dp, name, T_DIR, 0, 0)) == 0){
     iput(dp);
     return -1;
   }
   dp->nlink++;
   iupdate(dp);
 
-  if(dirlink(ip, ".", 1, ip->inum) < 0 || dirlink(ip, "..", 2, dp->inum) < 0)
+  if(dirlink(ip, ".", ip->inum) < 0 || dirlink(ip, "..", dp->inum) < 0)
     panic("mkdir");
   iput(dp);
   iput(ip);
@@ -776,13 +793,12 @@ struct inode*
 create(char *path)
 {
   struct inode *dp, *ip;
-  char *name;
-  int namelen;
+  char name[DIRSIZ];
   
-  if((dp = nameiparent(path, &name, &namelen)) == 0)
+  if((dp = nameiparent(path, name)) == 0)
     return 0;
   
-  if((ip = dirlookup(dp, name, namelen, 0)) != 0){
+  if((ip = dirlookup(dp, name, 0)) != 0){
     iput(dp);
     ilock(ip);
     if(ip->type == T_DIR){
@@ -791,7 +807,7 @@ create(char *path)
     }
     return ip;
   }
-  if((ip = dircreat(dp, name, namelen, T_FILE, 0, 0)) == 0){
+  if((ip = dircreat(dp, name, T_FILE, 0, 0)) == 0){
     iput(dp);
     return 0;
   }