diff --git a/fs.c b/fs.c
index cf717a2061db24cc6fe0e22e4a8266a752e1430c..2370e0ecd4255723105b3df23840e0716a67d571 100644
--- a/fs.c
+++ b/fs.c
@@ -355,7 +355,8 @@ writei(struct inode *ip, char *addr, uint off, uint n)
     }
     if (r > 0) {
       if (off > ip->size) {
-	ip->size = off;
+	if (ip->type == T_DIR) ip->size = ((off / BSIZE) + 1) * BSIZE;
+	else ip->size = off;
       }
       iupdate(ip);
     }
diff --git a/ls.c b/ls.c
index ada61ec0fb238030eb433e863cce573576ab5d34..9731f6f13554da544cb55cf2714515f676d5b395 100644
--- a/ls.c
+++ b/ls.c
@@ -12,6 +12,7 @@ main(int argc, char *argv[])
 {
   int fd;
   uint off;
+  uint sz;
 
   if(argc > 1){
     puts("Usage: ls\n");
@@ -30,18 +31,19 @@ main(int argc, char *argv[])
   if (st.st_type != T_DIR) {
     printf(2, "ls: . is not a dir\n");
   }
-  cprintf("size %d\n", st.st_size);
-  for(off = 0; off < st.st_size; off += sizeof(struct dirent)) {
+  sz = st.st_size;
+  for(off = 0; off < sz; off += sizeof(struct dirent)) {
     if (read(fd, &dirent, sizeof(struct dirent)) != sizeof(struct dirent)) {
-      printf(2, "ls: read error\n");
-      exit();
+      printf(1, "ls: read error\n");
+      break;
     }
     if (dirent.inum != 0) {
-
-      if (stat (dirent.name, &st) < 0) 
-	printf(2, "stat: failed\n");
-
-      printf(1, "%s t %d\n", dirent.name, st.st_type);
+      if (stat (dirent.name, &st) < 0)  {
+	printf(1, "stat: failed\n");
+	break;
+      }
+      printf(1, "%s t %d ino %d sz %d\n", dirent.name, st.st_type, 
+	     dirent.inum, st.st_size);
     }
   }
   close(fd);
diff --git a/mkfs.c b/mkfs.c
index b048e10ab36b20a79d8316e8ef897651b2a0f313..15870d9e81541b0d70d857685d539ed8998f05da 100644
--- a/mkfs.c
+++ b/mkfs.c
@@ -23,6 +23,7 @@ uint freeinode = 1;
 void balloc(int);
 void wsect(uint, void *);
 void winode(uint, struct dinode *);
+void rinode(uint inum, struct dinode *ip);
 void rsect(uint sec, void *buf);
 uint ialloc(ushort type);
 void iappend(uint inum, void *p, int n);
@@ -53,9 +54,10 @@ xint(uint x)
 main(int argc, char *argv[])
 {
   int i, cc, fd;
-  uint bn, rootino, inum;
+  uint bn, rootino, inum, off;
   struct dirent de;
   char buf[512];
+  struct dinode din;
 
   if(argc < 2){
     fprintf(stderr, "Usage: mkfs fs.img files...\n");
@@ -122,6 +124,13 @@ main(int argc, char *argv[])
     close(fd);
   }
 
+  // fix size of root inode dir
+  rinode(rootino, &din);
+  off = xint(din.size);  
+  off = ((off/BSIZE) + 1) * BSIZE;
+  din.size = xint(off);
+  winode(rootino, &din);
+
   balloc(usedblocks);
 
   exit(0);
diff --git a/syscall.c b/syscall.c
index 0ef2670181a3caaab40fa8c8954ce091f895387f..0a017c76e77d204544656a4b0529266257cddc9b 100644
--- a/syscall.c
+++ b/syscall.c
@@ -294,8 +294,10 @@ sys_mkdir(void)
 {
   struct proc *cp = curproc[cpu()];
   struct inode *nip;
+  struct inode *pip;
   uint arg0;
   int l;
+  struct dirent de;
 
   if(fetcharg(0, &arg0) < 0) 
     return -1;
@@ -308,7 +310,15 @@ sys_mkdir(void)
 
   nip = mknod (cp->mem + arg0, T_DIR, 0, 0);
 
-  // XXX put . and .. in
+  de.name[0] = '.';
+  de.inum = nip->inum;
+  writei (nip, (char *) &de, 0, sizeof(de));
+
+  pip = namei(".", NAMEI_LOOKUP, 0);
+  de.inum = pip->inum;
+  de.name[1] = '.';
+  iput(pip);
+  writei (nip, (char *) &de, sizeof(de), sizeof(de));
 
   iput(nip);
   return (nip == 0) ? -1 : 0;
diff --git a/ulib.c b/ulib.c
index eaa33d386fe0e99e8aceac889ea4d589c0e1b9a9..004b934209fdb08a86b2e2257e21ab52be95197f 100644
--- a/ulib.c
+++ b/ulib.c
@@ -61,11 +61,11 @@ gets(char *buf, int max)
 int
 stat(char *n, struct stat *st)
 {
-  int fd = open(n, O_RDONLY);
+  int fd;
   int r;
 
+  fd = open(n, O_RDONLY);
   if (fd < 0) return -1;
-
   r = fstat(fd, st);
   close(fd);
   return r;