Wordsmithing.
[pintos-anon] / solutions / p4.patch
index febbcaa829770c840e137b60ba96c589fc913659..61ef9e8ab541aae4cd490003585a50b318db4c91 100644 (file)
@@ -1,11 +1,12 @@
+Index: src/Makefile.build
 diff -u src/Makefile.build~ src/Makefile.build
---- src/Makefile.build~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/Makefile.build 2005-06-16 15:09:31.000000000 -0700
+--- src/Makefile.build 2005-06-18 20:20:47.000000000 -0700
++++ src/Makefile.build 2006-05-18 21:26:51.000000000 -0700
 @@ -53,7 +53,9 @@ userprog_SRC += userprog/gdt.c               # GDT in
  userprog_SRC += userprog/tss.c                # TSS management.
  
  # No virtual memory code yet.
--#vm_SRC = vm/filename.c                       # Some file.
+-#vm_SRC = vm/file.c                   # Some file.
 +vm_SRC = vm/page.c
 +vm_SRC += vm/frame.c
 +vm_SRC += vm/swap.c
@@ -20,9 +21,10 @@ diff -u src/Makefile.build~ src/Makefile.build
  
  SOURCES = $(foreach dir,$(KERNEL_SUBDIRS),$($(dir)_SRC))
  OBJECTS = $(patsubst %.c,%.o,$(patsubst %.S,%.o,$(SOURCES)))
+Index: src/devices/timer.c
 diff -u src/devices/timer.c~ src/devices/timer.c
---- src/devices/timer.c~ 2005-06-15 15:21:01.000000000 -0700
-+++ src/devices/timer.c 2005-06-16 15:09:31.000000000 -0700
+--- src/devices/timer.c        2005-07-06 13:45:36.000000000 -0700
++++ src/devices/timer.c        2006-05-18 21:26:51.000000000 -0700
 @@ -23,6 +23,9 @@ static volatile int64_t ticks;
     Initialized by timer_calibrate(). */
  static unsigned loops_per_tick;
@@ -99,10 +101,11 @@ diff -u src/devices/timer.c~ src/devices/timer.c
  }
  
  /* Returns true if LOOPS iterations waits for more than one timer
+Index: src/filesys/Make.vars
 diff -u src/filesys/Make.vars~ src/filesys/Make.vars
---- src/filesys/Make.vars~ 2005-05-24 14:46:45.000000000 -0700
-+++ src/filesys/Make.vars 2005-06-16 15:09:31.000000000 -0700
-@@ -6,7 +6,7 @@ KERNEL_SUBDIRS = threads devices lib lib
+--- src/filesys/Make.vars      2005-06-20 13:24:21.000000000 -0700
++++ src/filesys/Make.vars      2006-05-18 21:26:51.000000000 -0700
+@@ -6,7 +6,7 @@ TEST_SUBDIRS = tests/userprog tests/file
  GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.no-vm
  
  # Uncomment the lines below to enable VM.
@@ -114,9 +117,10 @@ diff -u src/filesys/Make.vars~ src/filesys/Make.vars
 +KERNEL_SUBDIRS += vm
 +TEST_SUBDIRS += tests/vm
 +GRADING_FILE = $(SRCDIR)/tests/filesys/Grading.with-vm
+Index: src/filesys/cache.c
 diff -u src/filesys/cache.c~ src/filesys/cache.c
---- src/filesys/cache.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/filesys/cache.c 2005-06-16 15:09:31.000000000 -0700
+--- src/filesys/cache.c        1969-12-31 16:00:00.000000000 -0800
++++ src/filesys/cache.c        2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,473 @@
 +#include "filesys/cache.h"
 +#include <debug.h>
@@ -591,9 +595,10 @@ diff -u src/filesys/cache.c~ src/filesys/cache.c
 +      free (ra_block);
 +    }
 +}
+Index: src/filesys/cache.h
 diff -u src/filesys/cache.h~ src/filesys/cache.h
---- src/filesys/cache.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/filesys/cache.h 2005-06-16 15:09:31.000000000 -0700
+--- src/filesys/cache.h        1969-12-31 16:00:00.000000000 -0800
++++ src/filesys/cache.h        2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,23 @@
 +#ifndef FILESYS_CACHE_H
 +#define FILESYS_CACHE_H
@@ -618,28 +623,11 @@ diff -u src/filesys/cache.h~ src/filesys/cache.h
 +void cache_readahead (disk_sector_t);
 +
 +#endif /* filesys/cache.h */
+Index: src/filesys/directory.c
 diff -u src/filesys/directory.c~ src/filesys/directory.c
---- src/filesys/directory.c~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/directory.c 2005-06-16 21:09:01.000000000 -0700
-@@ -3,12 +3,17 @@
- #include <string.h>
- #include <list.h>
- #include "filesys/filesys.h"
-+#include "filesys/fsutil.h"
- #include "filesys/inode.h"
- #include "threads/malloc.h"
-+#include "threads/synch.h"
- /* A directory. */
- struct dir 
-   {
-+    struct list_elem list_elem;         /* open_dirs list element. */
-+    struct lock dir_lock;               /* Protects inode. */
-+    int open_cnt;                       /* Number of openers. */
-     struct inode *inode;                /* Backing store. */
-   };
-@@ -20,15 +25,21 @@ struct dir_entry 
+--- src/filesys/directory.c    2006-05-18 22:26:21.000000000 -0700
++++ src/filesys/directory.c    2006-05-18 22:18:19.000000000 -0700
+@@ -20,21 +20,13 @@ struct dir_entry 
      bool in_use;                        /* In use or free? */
    };
  
@@ -647,107 +635,22 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
 -   given SECTOR.  Returns true if successful, false on failure. */
 -bool
 -dir_create (disk_sector_t sector, size_t entry_cnt) 
-+/* List of all open directories. */
-+static struct list open_dirs;
-+
-+/* Protects open_dirs additions or removals. */
-+static struct lock open_dirs_lock;
-+
-+/* Initializes directory modules. */
-+void
-+dir_init (void) 
- {
+-{
 -  return inode_create (sector, entry_cnt * sizeof (struct dir_entry));
-+  list_init (&open_dirs);
-+  lock_init (&open_dirs_lock);
- }
--/* Opens the directory in the given INODE, of which it takes
-+/* Opens the directory for the given INODE, of which it takes
-    ownership, and sets *DIRP to the new directory or a null
-    pointer on failure.  Return true if successful, false on
-    failure. */
-@@ -36,19 +47,46 @@ bool
- dir_open (struct inode *inode, struct dir **dirp) 
- {
-   struct dir *dir = NULL;
-+  struct list_elem *e;
-   
-   ASSERT (dirp != NULL);
--  if (inode != NULL) 
-+  lock_acquire (&open_dirs_lock);
-+
-+  if (inode == NULL)
-+    goto done;
-+
-+  /* Inode must refer to directory. */
-+  if (inode_get_type (inode) != DIR_INODE)
-+    goto done;
-+
-+  /* Check whether this directory is already open. */
-+  for (e = list_begin (&open_dirs); e != list_end (&open_dirs);
-+       e = list_next (e)) 
-     {
--      dir = malloc (sizeof *dir);
--      if (dir != NULL) 
--        dir->inode = inode;
-+      dir = list_entry (e, struct dir, list_elem);
-+      if (dir->inode == inode) 
-+        {
-+          dir->open_cnt++;
-+          goto done;
-+        }
-+    }
-+
-+  /* Create new directory. */
-+  dir = calloc (1, sizeof *dir);
-+  if (dir != NULL)
-+    {
-+      list_push_front (&open_dirs, &dir->list_elem);
-+      lock_init (&dir->dir_lock);
-+      dir->open_cnt = 1;
-+      dir->inode = inode;
-+      inode_reopen (dir->inode);
-     }
-   
-+ done:
-   *dirp = dir;
--  if (dir == NULL)
--    inode_close (inode);
-+  inode_close (inode);
-+  lock_release (&open_dirs_lock);
-   return dir != NULL;
- }
-@@ -61,22 +99,34 @@ dir_open_root (struct dir **dirp)
-   return dir_open (inode_open (ROOT_DIR_SECTOR), dirp);
- }
-+/* Re-opens DIR and returns true. */
-+bool
-+dir_reopen (struct dir *dir)
-+{
-+  dir->open_cnt++;
-+  return true;
-+}
-+
- /* Destroys DIR and frees associated resources. */
- void
- dir_close (struct dir *dir) 
+-}
+-
+ /* Opens and returns the directory for the given INODE, of which
+    it takes ownership.  Returns a null pointer on failure. */
+ struct dir *
+ dir_open (struct inode *inode) 
  {
--  if (dir != NULL)
-+  if (dir == NULL)
-+    return;
-+
-+  lock_acquire (&open_dirs_lock);
-+  if (--dir->open_cnt == 0) 
+   struct dir *dir = calloc (1, sizeof *dir);
+-  if (inode != NULL && dir != NULL)
++  if (inode != NULL && dir != NULL && inode_get_type (inode) == DIR_INODE)
      {
-+      list_remove (&dir->list_elem);
-       inode_close (dir->inode);
-       free (dir);
-     }
-+  lock_release (&open_dirs_lock);
+       dir->inode = inode;
+       return dir;
+@@ -67,10 +67,8 @@ dir_close (struct dir *dir) 
  }
  
  /* Searches DIR for a file with the given NAME.
@@ -760,20 +663,20 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
  static bool
  lookup (const struct dir *dir, const char *name,
          struct dir_entry *ep, off_t *ofsp) 
-@@ -113,10 +163,12 @@ dir_lookup (const struct dir *dir, const
+@@ -107,10 +105,12 @@ dir_lookup (const struct dir *dir, const
    ASSERT (dir != NULL);
    ASSERT (name != NULL);
  
-+  lock_acquire ((struct lock *) &dir->dir_lock);
++  inode_lock (dir->inode);
    if (lookup (dir, name, &e, NULL))
      *inode = inode_open (e.inode_sector);
    else
      *inode = NULL;
-+  lock_release ((struct lock *)&dir->dir_lock);
++  inode_unlock (dir->inode);
  
    return *inode != NULL;
  }
-@@ -138,10 +190,11 @@ dir_add (struct dir *dir, const char *na
+@@ -132,10 +132,11 @@ dir_add (struct dir *dir, const char *na
    ASSERT (name != NULL);
  
    /* Check NAME for validity. */
@@ -782,23 +685,23 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
      return false;
  
    /* Check that NAME is not in use. */
-+  lock_acquire (&dir->dir_lock);
++  inode_lock (dir->inode);
    if (lookup (dir, name, NULL, NULL))
      goto done;
  
-@@ -164,6 +217,7 @@ dir_add (struct dir *dir, const char *na
+@@ -158,6 +159,7 @@ dir_add (struct dir *dir, const char *na
    success = inode_write_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
  
   done:
-+  lock_release (&dir->dir_lock);
++  inode_unlock (dir->inode);
    return success;
  }
  
-@@ -182,12 +236,14 @@ dir_remove (struct dir *dir, const char 
+@@ -176,12 +178,14 @@ dir_remove (struct dir *dir, const char 
    ASSERT (name != NULL);
  
    /* Find directory entry. */
-+  lock_acquire (&dir->dir_lock);
++  inode_lock (dir->inode);
    if (!lookup (dir, name, &e, &ofs))
      goto done;
  
@@ -811,53 +714,48 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
      goto done;
  
    /* Erase directory entry. */
-@@ -201,6 +257,7 @@ dir_remove (struct dir *dir, const char 
+@@ -195,6 +199,7 @@ dir_remove (struct dir *dir, const char 
  
   done:
    inode_close (inode);
-+  lock_release (&dir->dir_lock);
++  inode_unlock (dir->inode);
    return success;
  }
  
-@@ -211,8 +268,10 @@ dir_list (const struct dir *dir)
+@@ -216,14 +216,17 @@
+ {
    struct dir_entry e;
-   size_t ofs;
-   
-+  lock_acquire ((struct lock *) &dir->dir_lock);
-   for (ofs = 0; inode_read_at (dir->inode, &e, sizeof e, ofs) == sizeof e;
-        ofs += sizeof e) 
-     if (e.in_use)
-       printf ("%s\n", e.name);
-+  lock_release ((struct lock *) &dir->dir_lock);
++  inode_lock (dir->inode);
+   while (inode_read_at (dir->inode, &e, sizeof e, dir->pos) == sizeof e) 
+     {
+       dir->pos += sizeof e;
+       if (e.in_use)
+         {
+           strlcpy (name, e.name, NAME_MAX + 1);
++          inode_unlock (dir->inode);
+           return true;
+         } 
+     }
++  inode_unlock (dir->inode);
+   return false;
  }
+Index: src/filesys/directory.h
 diff -u src/filesys/directory.h~ src/filesys/directory.h
---- src/filesys/directory.h~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/directory.h 2005-06-16 15:09:31.000000000 -0700
-@@ -13,9 +13,10 @@
+--- src/filesys/directory.h    2006-05-18 22:26:02.000000000 -0700
++++ src/filesys/directory.h    2006-05-18 22:05:40.000000000 -0700
+@@ -12,6 +11,5 @@
  struct inode;
- struct dir;
+ /* Opening and closing directories. */
 -bool dir_create (disk_sector_t sector, size_t entry_cnt);
-+void dir_init (void);
- bool dir_open (struct inode *, struct dir **);
- bool dir_open_root (struct dir **);
-+bool dir_reopen (struct dir *);
- void dir_close (struct dir *);
- bool dir_lookup (const struct dir *, const char *name, struct inode **);
- bool dir_add (struct dir *, const char *name, disk_sector_t);
+ struct dir *dir_open (struct inode *);
+ struct dir *dir_open_root (void);
+Index: src/filesys/file.c
 diff -u src/filesys/file.c~ src/filesys/file.c
---- src/filesys/file.c~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/file.c 2005-06-16 21:02:34.000000000 -0700
-@@ -1,6 +1,8 @@
- #include "filesys/file.h"
- #include <debug.h>
-+#include "filesys/directory.h"
- #include "filesys/inode.h"
-+#include "filesys/filesys.h"
- #include "threads/malloc.h"
- /* An open file. */
-@@ -18,7 +20,7 @@ struct file *
+--- src/filesys/file.c 2005-06-18 20:20:48.000000000 -0700
++++ src/filesys/file.c 2006-05-18 22:14:15.000000000 -0700
+@@ -18,7 +18,7 @@ struct file *
  file_open (struct inode *inode) 
  {
    struct file *file = calloc (1, sizeof *file);
@@ -866,9 +764,10 @@ diff -u src/filesys/file.c~ src/filesys/file.c
      {
        file->inode = inode;
        file->pos = 0;
+Index: src/filesys/filesys.c
 diff -u src/filesys/filesys.c~ src/filesys/filesys.c
---- src/filesys/filesys.c~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/filesys.c 2005-06-16 21:03:07.000000000 -0700
+--- src/filesys/filesys.c      2006-05-18 22:26:21.000000000 -0700
++++ src/filesys/filesys.c      2006-05-18 22:35:43.000000000 -0700
 @@ -2,11 +2,13 @@
  #include <debug.h>
  #include <stdio.h>
@@ -881,18 +780,17 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
  #include "devices/disk.h"
 +#include "threads/thread.h"
  
- /* The disk that contains the filesystem. */
+ /* The disk that contains the file system. */
  struct disk *filesys_disk;
-@@ -23,6 +24,8 @@ filesys_init (bool format) 
-     PANIC ("hd0:1 (hdb) not present, filesystem initialization failed");
+@@ -23,6 +25,7 @@ filesys_init (bool format) 
+     PANIC ("hd0:1 (hdb) not present, file system initialization failed");
  
    inode_init ();
-+  dir_init ();
 +  cache_init ();
    free_map_init ();
  
    if (format) 
-@@ -37,6 +40,103 @@ void
+@@ -37,6 +40,99 @@ void
  filesys_done (void) 
  {
    free_map_close ();
@@ -937,10 +835,10 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +/* Resolves relative or absolute file NAME.
 +   Returns true if successful, false on failure.
 +   Stores the directory corresponding to the name into *DIRP,
-+   and the file name part into BASENAME. */
++   and the file name part into BASE_NAME. */
 +static bool
 +resolve_name (const char *name,
-+              struct dir **dirp, char basename[NAME_MAX + 1]) 
++              struct dir **dirp, char base_name[NAME_MAX + 1]) 
 +{
 +  struct dir *dir = NULL;
 +  struct inode *inode;
@@ -949,17 +847,12 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +  int ok;
 +
 +  /* Find starting directory. */
-+  if (name[0] == '/' || thread_current ()->wd == NULL) 
-+    {
-+      if (!dir_open_root (&dir))
-+        goto error;
-+    }
-+  else 
-+    {
-+      if (!dir_reopen (thread_current ()->wd))
-+        goto error;
-+      dir = thread_current ()->wd;
-+    }
++  if (name[0] == '/' || thread_current ()->wd == NULL)
++    dir = dir_open_root ();
++  else
++    dir = dir_reopen (thread_current ()->wd);
++  if (dir == NULL)
++    goto error;
 +
 +  /* Get first name part. */
 +  cp = name;
@@ -974,7 +867,8 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +        goto error;
 +
 +      dir_close (dir);
-+      if (!dir_open (inode, &dir))
++      dir = dir_open (inode);
++      if (dir == NULL)
 +        goto error;
 +
 +      strlcpy (part, next_part, NAME_MAX + 1);
@@ -984,44 +878,44 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +
 +  /* Return our results. */
 +  *dirp = dir;
-+  strlcpy (basename, part, NAME_MAX + 1);
++  strlcpy (base_name, part, NAME_MAX + 1);
 +  return true;
 +
 + error:
 +  /* Return failure. */
 +  dir_close (dir);
 +  *dirp = NULL;
-+  basename[0] = '\0';
++  base_name[0] = '\0';
 +  return false;
  }
  \f
  /* Creates a file named NAME with the given INITIAL_SIZE.
-@@ -44,16 +144,17 @@ filesys_done (void) 
+@@ -44,16 +140,17 @@ filesys_done (void) 
     Fails if a file named NAME already exists,
     or if internal memory allocation fails. */
  bool
 -filesys_create (const char *name, off_t initial_size) 
 +filesys_create (const char *name, off_t initial_size, enum inode_type type) 
  {
-   struct dir *dir;
-+  char basename[NAME_MAX + 1];
++  struct dir *dir;
++  char base_name[NAME_MAX + 1];
    disk_sector_t inode_sector = 0;
--  bool success = (dir_open_root (&dir)
+-  struct dir *dir = dir_open_root ();
+-  bool success = (dir != NULL
 -                  && free_map_allocate (1, &inode_sector)
 -                  && inode_create (inode_sector, initial_size)
 -                  && dir_add (dir, name, inode_sector));
--  if (!success && inode_sector != 0) 
--    free_map_release (inode_sector, 1);
-+  bool success = (resolve_name (name, &dir, basename)
++  bool success = (resolve_name (name, &dir, base_name)
 +                  && free_map_allocate (&inode_sector)
 +                  && inode_create (inode_sector, initial_size, type)
-+                  && dir_add (dir, basename, inode_sector));
-+  if (!success && inode_sector) 
++                  && dir_add (dir, base_name, inode_sector));
+   if (!success && inode_sector != 0) 
+-    free_map_release (inode_sector, 1);
 +    free_map_release (inode_sector);
    dir_close (dir);
  
    return success;
-@@ -64,17 +165,18 @@ filesys_create (const char *name, off_t 
+@@ -64,17 +161,22 @@ filesys_create (const char *name, off_t 
     otherwise.
     Fails if no file named NAME exists,
     or if an internal memory allocation fails. */
@@ -1029,14 +923,19 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +struct inode *
  filesys_open (const char *name)
  {
-   struct dir *dir;
-+  char basename[NAME_MAX + 1];
+-  struct dir *dir = dir_open_root ();
++  struct dir *dir = NULL;
++  char base_name[NAME_MAX + 1];
    struct inode *inode = NULL;
  
--  if (dir_open_root (&dir))
+-  if (dir != NULL)
 -    dir_lookup (dir, name, &inode);
-+  if (resolve_name (name, &dir, basename))
-+    dir_lookup (dir, basename, &inode);
++  if (!strcmp (name, "/"))
++    inode = inode_open (ROOT_DIR_SECTOR);
++  else if (!strcmp (name, "."))
++    inode = inode_reopen (dir_get_inode (thread_current ()->wd));
++  else if (resolve_name (name, &dir, base_name))
++    dir_lookup (dir, base_name, &inode);
    dir_close (dir);
  
 -  return file_open (inode);
@@ -1044,22 +943,23 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
  }
  
  /* Deletes the file named NAME.
-@@ -85,13 +187,54 @@ bool
+@@ -84,7 +182,11 @@ filesys_open (const char *name)
+ bool
  filesys_remove (const char *name) 
  {
-   struct dir *dir = NULL;
--  bool success = (dir_open_root (&dir)
--                  && dir_remove (dir, name));
-+  char basename[NAME_MAX + 1];
+-  struct dir *dir = dir_open_root ();
+-  bool success = dir != NULL && dir_remove (dir, name);
++  struct dir *dir = NULL;
++  char base_name[NAME_MAX + 1];
 +  bool success = false;
 +
-+  if (resolve_name (name, &dir, basename)) 
-+    success = dir_remove (dir, basename);
++  if (resolve_name (name, &dir, base_name)) 
++    success = dir_remove (dir, base_name);
    dir_close (dir); 
  
+@@ -91,5 +193,44 @@
    return success;
  }
 +/* Change current directory to NAME.
 +   Return true if successful, false on failure. */
 +bool
@@ -1072,17 +972,18 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +    return false;
 +  else if (name[strspn (name, "/")] == '\0')
 +    {
-+      if (!dir_open_root (&dir))
++      dir = dir_open_root ();
++      if (dir == NULL)
 +        return false; 
 +    }
 +  else 
 +    {
-+      char basename[NAME_MAX + 1];
++      char base_name[NAME_MAX + 1];
 +      struct inode *base_inode;
 +      struct dir *base_dir;
-+      if (!resolve_name (name, &dir, basename)
-+          || !dir_lookup (dir, basename, &base_inode)
-+          || !dir_open (base_inode, &base_dir))
++      if (!resolve_name (name, &dir, base_name)
++          || !dir_lookup (dir, base_name, &base_inode)
++          || (base_dir = dir_open (base_inode)) == NULL)
 +        {
 +          dir_close (dir);
 +          return false;
@@ -1098,26 +999,10 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +  return true;
 +}
 +
- /* Prints a list of files in the filesystem to the system
-    console.
-    Returns true if successful, false on failure,
-@@ -99,13 +242,9 @@ filesys_remove (const char *name) 
- bool
- filesys_list (void) 
- {
--  struct dir *dir = NULL;
--  bool success = dir_open_root (&dir);
--  if (success)
--    dir_list (dir);
--  dir_close (dir);
-+  dir_list (thread_current ()->wd);
--  return success;
-+  return true;
- }
  \f
  static void must_succeed_function (int, bool) NO_INLINE;
-@@ -128,8 +267,8 @@ filesys_self_test (void)
+ #define MUST_SUCCEED(EXPR) must_succeed_function (__LINE__, EXPR)
+@@ -129,8 +264,8 @@ filesys_self_test (void)
      {
        /* Create file and check that it contains zeros
           throughout the created length. */
@@ -1128,7 +1013,7 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
        MUST_SUCCEED (file_read (file, s2, sizeof s2) == sizeof s2);
        MUST_SUCCEED (memcmp (s2, zeros, sizeof s) == 0);
        MUST_SUCCEED (file_tell (file) == sizeof s);
-@@ -137,7 +276,7 @@ filesys_self_test (void)
+@@ -138,7 +273,7 @@ filesys_self_test (void)
        file_close (file);
  
        /* Reopen file and write to it. */
@@ -1137,7 +1022,7 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
        MUST_SUCCEED (file_write (file, s, sizeof s) == sizeof s);
        MUST_SUCCEED (file_tell (file) == sizeof s);
        MUST_SUCCEED (file_length (file) == sizeof s);
-@@ -145,7 +284,7 @@ filesys_self_test (void)
+@@ -146,7 +281,7 @@ filesys_self_test (void)
  
        /* Reopen file and verify that it reads back correctly.
           Delete file while open to check proper semantics. */
@@ -1146,10 +1031,10 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
        MUST_SUCCEED (filesys_remove ("foo"));
        MUST_SUCCEED (filesys_open ("foo") == NULL);
        MUST_SUCCEED (file_read (file, s2, sizeof s) == sizeof s);
-@@ -172,9 +311,13 @@ static void
+@@ -173,9 +308,13 @@ static void
  do_format (void)
  {
-   printf ("Formatting filesystem...");
+   printf ("Formatting file system...");
 +
 +  /* Set up free map. */
    free_map_create ();
@@ -1162,9 +1047,10 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +
    printf ("done.\n");
  }
+Index: src/filesys/filesys.h
 diff -u src/filesys/filesys.h~ src/filesys/filesys.h
---- src/filesys/filesys.h~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/filesys.h 2005-06-16 20:55:14.000000000 -0700
+--- src/filesys/filesys.h      2005-06-18 20:20:48.000000000 -0700
++++ src/filesys/filesys.h      2006-05-18 21:26:51.000000000 -0700
 @@ -3,6 +3,7 @@
  
  #include <stdbool.h>
@@ -1173,7 +1059,7 @@ diff -u src/filesys/filesys.h~ src/filesys/filesys.h
  
  /* Sectors of system file inodes. */
  #define FREE_MAP_SECTOR 0       /* Free map file inode sector. */
-@@ -13,8 +14,8 @@ extern struct disk *filesys_disk;
+@@ -13,9 +14,10 @@ extern struct disk *filesys_disk;
  
  void filesys_init (bool format);
  void filesys_done (void);
@@ -1182,11 +1068,14 @@ diff -u src/filesys/filesys.h~ src/filesys/filesys.h
 +bool filesys_create (const char *name, off_t initial_size, enum inode_type);
 +struct inode *filesys_open (const char *name);
  bool filesys_remove (const char *name);
- bool filesys_chdir (const char *name);
- bool filesys_list (void);
++bool filesys_chdir (const char *name);
+ void filesys_self_test (void);
+Index: src/filesys/free-map.c
 diff -u src/filesys/free-map.c~ src/filesys/free-map.c
---- src/filesys/free-map.c~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/free-map.c 2005-06-16 20:57:13.000000000 -0700
+--- src/filesys/free-map.c     2005-06-18 20:20:48.000000000 -0700
++++ src/filesys/free-map.c     2006-05-18 21:26:51.000000000 -0700
 @@ -3,15 +3,18 @@
  #include <debug.h>
  #include "filesys/file.h"
@@ -1282,9 +1171,10 @@ diff -u src/filesys/free-map.c~ src/filesys/free-map.c
      PANIC ("can't write free map");
 +  file_close (free_map_file);
  }
+Index: src/filesys/free-map.h
 diff -u src/filesys/free-map.h~ src/filesys/free-map.h
---- src/filesys/free-map.h~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/free-map.h 2005-06-16 20:48:04.000000000 -0700
+--- src/filesys/free-map.h     2005-06-18 20:20:48.000000000 -0700
++++ src/filesys/free-map.h     2006-05-18 21:26:51.000000000 -0700
 @@ -11,7 +11,7 @@ void free_map_create (void);
  void free_map_open (void);
  void free_map_close (void);
@@ -1295,43 +1185,45 @@ diff -u src/filesys/free-map.h~ src/filesys/free-map.h
 +void free_map_release (disk_sector_t);
  
  #endif /* filesys/free-map.h */
+Index: src/filesys/fsutil.c
 diff -u src/filesys/fsutil.c~ src/filesys/fsutil.c
---- src/filesys/fsutil.c~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/fsutil.c 2005-06-16 20:55:13.000000000 -0700
+--- src/filesys/fsutil.c       2006-04-22 22:25:13.000000000 -0700
++++ src/filesys/fsutil.c       2006-05-18 21:26:51.000000000 -0700
 @@ -30,7 +30,7 @@ fsutil_cat (char **argv)
    char *buffer;
  
-   printf ("Printing '%s' to the console...\n", filename);
--  file = filesys_open (filename);
-+  file = file_open (filesys_open (filename));
+   printf ("Printing '%s' to the console...\n", file_name);
+-  file = filesys_open (file_name);
++  file = file_open (filesys_open (file_name));
    if (file == NULL)
-     PANIC ("%s: open failed", filename);
+     PANIC ("%s: open failed", file_name);
    buffer = palloc_get_page (PAL_ASSERT);
 @@ -102,9 +102,9 @@ fsutil_put (char **argv) 
-     PANIC ("%s: invalid file size %d", filename, size);
+     PANIC ("%s: invalid file size %d", file_name, size);
    
    /* Create destination file. */
--  if (!filesys_create (filename, size))
-+  if (!filesys_create (filename, size, FILE_INODE))
-     PANIC ("%s: create failed", filename);
--  dst = filesys_open (filename);
-+  dst = file_open (filesys_open (filename));
+-  if (!filesys_create (file_name, size))
++  if (!filesys_create (file_name, size, FILE_INODE))
+     PANIC ("%s: create failed", file_name);
+-  dst = filesys_open (file_name);
++  dst = file_open (filesys_open (file_name));
    if (dst == NULL)
-     PANIC ("%s: open failed", filename);
+     PANIC ("%s: open failed", file_name);
  
 @@ -154,7 +154,7 @@ fsutil_get (char **argv)
      PANIC ("couldn't allocate buffer");
  
    /* Open source file. */
--  src = filesys_open (filename);
-+  src = file_open (filesys_open (filename));
+-  src = filesys_open (file_name);
++  src = file_open (filesys_open (file_name));
    if (src == NULL)
-     PANIC ("%s: open failed", filename);
+     PANIC ("%s: open failed", file_name);
    size = file_length (src);
+Index: src/filesys/inode.c
 diff -u src/filesys/inode.c~ src/filesys/inode.c
---- src/filesys/inode.c~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/inode.c 2005-06-16 21:11:24.000000000 -0700
-@@ -1,26 +1,41 @@
+--- src/filesys/inode.c        2006-04-08 12:09:33.000000000 -0700
++++ src/filesys/inode.c        2006-05-18 22:18:19.000000000 -0700
+@@ -1,23 +1,38 @@
  #include "filesys/inode.h"
 +#include <bitmap.h>
  #include <list.h>
@@ -1371,15 +1263,12 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 -    uint32_t unused[125];               /* Not used. */
    };
  
--/* Returns the number of sectors to allocate for an inode SIZE
-+/* Returns the number of sectors to allocate for an indoe SIZE
-    bytes long. */
- static inline size_t
- bytes_to_sectors (off_t size)
-@@ -35,33 +49,29 @@ struct inode 
+ /* Returns the number of sectors to allocate for an inode SIZE
+@@ -35,33 +50,30 @@ struct inode 
      disk_sector_t sector;               /* Sector number of disk location. */
      int open_cnt;                       /* Number of openers. */
      bool removed;                       /* True if deleted, false otherwise. */
++    struct lock lock;                   /* Protects the inode. */
 +
 +    /* Denying writes. */
 +    struct lock deny_write_lock;        /* Protects members below. */
@@ -1421,7 +1310,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  }
  
  /* Initializes an inode with LENGTH bytes of data and
-@@ -70,35 +80,32 @@ inode_init (void) 
+@@ -70,38 +82,35 @@ inode_init (void) 
     Returns true if successful.
     Returns false if memory or disk allocation fails. */
  bool
@@ -1435,8 +1324,11 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +  bool success;
  
    ASSERT (length >= 0);
-+
 +  block = cache_lock (sector, EXCLUSIVE);
++
+   /* If this assertion fails, the inode structure is not exactly
+      one sector in size, and you should fix that. */
    ASSERT (sizeof *disk_inode == DISK_SECTOR_SIZE);
 +  disk_inode = cache_zero (block);
 +  disk_inode->type = type;
@@ -1476,7 +1368,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    return success;
  }
  
-@@ -112,6 +119,7 @@ inode_open (disk_sector_t sector) 
+@@ -115,6 +124,7 @@ inode_open (disk_sector_t sector) 
    struct inode *inode;
  
    /* Check whether this inode is already open. */
@@ -1484,7 +1376,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    for (e = list_begin (&open_inodes); e != list_end (&open_inodes);
         e = list_next (e)) 
      {
-@@ -119,22 +127,26 @@ inode_open (disk_sector_t sector) 
+@@ -122,22 +132,27 @@ inode_open (disk_sector_t sector) 
        if (inode->sector == sector) 
          {
            inode_reopen (inode);
@@ -1503,6 +1395,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    list_push_front (&open_inodes, &inode->elem);
    inode->sector = sector;
    inode->open_cnt = 1;
++  lock_init (&inode->lock);
    inode->deny_write_cnt = 0;
 +  lock_init (&inode->deny_write_lock);
 +  cond_init (&inode->no_writers_cond);
@@ -1514,7 +1407,16 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    return inode;
  }
  
-@@ -147,6 +159,17 @@ inode_reopen (struct inode *inode) 
+@@ -146,10 +161,25 @@ struct inode *
+ inode_reopen (struct inode *inode) 
+ {
+   if (inode != NULL) 
+-    inode->open_cnt++;
++    {
++      inode_lock (inode);
++      inode->open_cnt++;
++      inode_unlock (inode); 
++    }
    return inode;
  }
  
@@ -1532,7 +1434,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  /* Closes INODE and writes it to disk.
     If this was the last reference to INODE, frees its memory.
     If INODE was also a removed inode, frees its blocks. */
-@@ -158,21 +181,60 @@ inode_close (struct inode *inode) 
+@@ -161,21 +191,60 @@ inode_close (struct inode *inode) 
      return;
  
    /* Release resources if this was the last opener. */
@@ -1598,7 +1500,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  }
  
  /* Marks INODE to be deleted when it is closed by the last caller who
-@@ -181,6 +245,156 @@ inode_remove (struct inode *inode) 
+@@ -187,6 +256,156 @@ inode_remove (struct inode *inode) 
    inode->removed = true;
  }
  
@@ -1755,7 +1657,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  /* Reads SIZE bytes from INODE into BUFFER, starting at position OFFSET.
     Returns the number of bytes actually read, which may be less
     than SIZE if an error occurs or end of file is reached. */
-@@ -189,13 +403,12 @@ inode_read_at (struct inode *inode, void
+@@ -195,13 +414,12 @@ inode_read_at (struct inode *inode, void
  {
    uint8_t *buffer = buffer_;
    off_t bytes_read = 0;
@@ -1771,7 +1673,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  
        /* Bytes left in inode, bytes left in sector, lesser of the two. */
        off_t inode_left = inode_length (inode) - offset;
-@@ -204,26 +417,16 @@ inode_read_at (struct inode *inode, void
+@@ -210,26 +428,16 @@ inode_read_at (struct inode *inode, void
  
        /* Number of bytes to actually copy out of this sector. */
        int chunk_size = size < min_left ? size : min_left;
@@ -1804,7 +1706,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
          }
        
        /* Advance. */
-@@ -231,75 +434,84 @@ inode_read_at (struct inode *inode, void
+@@ -237,75 +445,84 @@ inode_read_at (struct inode *inode, void
        offset += chunk_size;
        bytes_read += chunk_size;
      }
@@ -1860,7 +1762,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
    while (size > 0) 
      {
 -      /* Sector to write, starting byte offset within sector. */
--      off_t sector_idx = byte_to_sector (inode, offset);
+-      disk_sector_t sector_idx = byte_to_sector (inode, offset);
 +      /* Sector to write, starting byte offset within sector, sector data. */
        int sector_ofs = offset % DISK_SECTOR_SIZE;
 +      struct cache_block *block;
@@ -1926,7 +1828,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  
    return bytes_written;
  }
-@@ -309,8 +521,12 @@ inode_write_at (struct inode *inode, con
+@@ -315,8 +532,12 @@ inode_write_at (struct inode *inode, con
  void
  inode_deny_write (struct inode *inode) 
  {
@@ -1940,7 +1842,7 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
  }
  
  /* Re-enables writes to INODE.
-@@ -319,14 +535,33 @@ inode_deny_write (struct inode *inode) 
+@@ -325,14 +546,47 @@ inode_deny_write (struct inode *inode) 
  void
  inode_allow_write (struct inode *inode) 
  {
@@ -1974,10 +1876,25 @@ diff -u src/filesys/inode.c~ src/filesys/inode.c
 +  lock_release (&open_inodes_lock);
 +
 +  return open_cnt;
++}
++
++/* Locks INODE. */
++void
++inode_lock (struct inode *inode) 
++{
++  lock_acquire (&inode->lock);
++}
++
++/* Releases INODE's lock. */
++void
++inode_unlock (struct inode *inode) 
++{
++  lock_release (&inode->lock);
  }
+Index: src/filesys/inode.h
 diff -u src/filesys/inode.h~ src/filesys/inode.h
---- src/filesys/inode.h~ 2005-06-16 21:50:20.000000000 -0700
-+++ src/filesys/inode.h 2005-06-16 20:53:47.000000000 -0700
+--- src/filesys/inode.h        2005-06-18 20:20:48.000000000 -0700
++++ src/filesys/inode.h        2006-05-18 21:46:41.000000000 -0700
 @@ -7,10 +7,18 @@
  
  struct bitmap;
@@ -1998,17 +1915,19 @@ diff -u src/filesys/inode.h~ src/filesys/inode.h
  void inode_close (struct inode *);
  void inode_remove (struct inode *);
  off_t inode_read_at (struct inode *, void *, off_t size, off_t offset);
-@@ -18,5 +26,6 @@ off_t inode_write_at (struct inode *, co
+@@ -18,5 +26,8 @@ off_t inode_write_at (struct inode *, co
  void inode_deny_write (struct inode *);
  void inode_allow_write (struct inode *);
  off_t inode_length (const struct inode *);
 +int inode_open_cnt (const struct inode *);
++void inode_lock (struct inode *);
++void inode_unlock (struct inode *);
  
  #endif /* filesys/inode.h */
-diff -u src/lib/kernel/bitmap.h~ src/lib/kernel/bitmap.h
+Index: src/threads/init.c
 diff -u src/threads/init.c~ src/threads/init.c
---- src/threads/init.c~ 2005-06-14 14:04:06.000000000 -0700
-+++ src/threads/init.c 2005-06-16 15:09:31.000000000 -0700
+--- src/threads/init.c 2006-05-18 17:35:54.000000000 -0700
++++ src/threads/init.c 2006-05-18 21:26:51.000000000 -0700
 @@ -33,6 +33,8 @@
  #include "filesys/filesys.h"
  #include "filesys/fsutil.h"
@@ -2018,7 +1937,7 @@ diff -u src/threads/init.c~ src/threads/init.c
  
  /* Amount of physical memory, in 4 kB pages. */
  size_t ram_pages;
-@@ -131,6 +133,9 @@ main (void)
+@@ -124,6 +126,9 @@ main (void)
    filesys_init (format_filesys);
  #endif
  
@@ -2028,10 +1947,11 @@ diff -u src/threads/init.c~ src/threads/init.c
    printf ("Boot complete.\n");
    
    /* Run actions specified on kernel command line. */
+Index: src/threads/interrupt.c
 diff -u src/threads/interrupt.c~ src/threads/interrupt.c
---- src/threads/interrupt.c~ 2005-06-15 15:22:43.000000000 -0700
-+++ src/threads/interrupt.c 2005-06-16 15:09:31.000000000 -0700
-@@ -343,6 +343,8 @@ intr_handler (struct intr_frame *frame) 
+--- src/threads/interrupt.c    2006-04-22 22:25:21.000000000 -0700
++++ src/threads/interrupt.c    2006-05-18 21:26:51.000000000 -0700
+@@ -354,6 +354,8 @@ intr_handler (struct intr_frame *frame) 
        in_external_intr = true;
        yield_on_return = false;
      }
@@ -2040,11 +1960,12 @@ diff -u src/threads/interrupt.c~ src/threads/interrupt.c
  
    /* Invoke the interrupt's handler.
       If there is no handler, invoke the unexpected interrupt
+Index: src/threads/thread.c
 diff -u src/threads/thread.c~ src/threads/thread.c
---- src/threads/thread.c~ 2005-06-15 14:41:47.000000000 -0700
-+++ src/threads/thread.c 2005-06-16 15:09:31.000000000 -0700
+--- src/threads/thread.c       2006-04-22 22:25:22.000000000 -0700
++++ src/threads/thread.c       2006-05-18 21:26:51.000000000 -0700
 @@ -13,6 +13,7 @@
- #include "threads/synch.h"
+ #include "threads/vaddr.h"
  #ifdef USERPROG
  #include "userprog/process.h"
 +#include "userprog/syscall.h"
@@ -2072,7 +1993,7 @@ diff -u src/threads/thread.c~ src/threads/thread.c
  }
  
  /* Starts preemptive thread scheduling by enabling interrupts.
-@@ -158,8 +159,8 @@ thread_create (const char *name, int pri
+@@ -159,8 +160,8 @@ thread_create (const char *name, int pri
      return TID_ERROR;
  
    /* Initialize thread. */
@@ -2083,7 +2004,7 @@ diff -u src/threads/thread.c~ src/threads/thread.c
  
    /* Stack frame for kernel_thread(). */
    kf = alloc_frame (t, sizeof *kf);
-@@ -252,16 +253,19 @@ thread_tid (void) 
+@@ -253,16 +254,19 @@ thread_tid (void) 
  void
  thread_exit (void) 
  {
@@ -2105,7 +2026,7 @@ diff -u src/threads/thread.c~ src/threads/thread.c
    schedule ();
    NOT_REACHED ();
  }
-@@ -390,17 +394,29 @@ is_thread (struct thread *t)
+@@ -406,17 +410,29 @@ is_thread (struct thread *t)
  /* Does basic initialization of T as a blocked thread named
     NAME. */
  static void
@@ -2136,9 +2057,10 @@ diff -u src/threads/thread.c~ src/threads/thread.c
    t->magic = THREAD_MAGIC;
  }
  
+Index: src/threads/thread.h
 diff -u src/threads/thread.h~ src/threads/thread.h
---- src/threads/thread.h~ 2005-06-15 14:49:06.000000000 -0700
-+++ src/threads/thread.h 2005-06-16 15:09:31.000000000 -0700
+--- src/threads/thread.h       2006-04-22 22:25:22.000000000 -0700
++++ src/threads/thread.h       2006-05-18 21:26:51.000000000 -0700
 @@ -2,8 +2,10 @@
  #define THREADS_THREAD_H
  
@@ -2203,9 +2125,10 @@ diff -u src/threads/thread.h~ src/threads/thread.h
  void thread_init (void);
  void thread_start (void);
  
+Index: src/userprog/exception.c
 diff -u src/userprog/exception.c~ src/userprog/exception.c
---- src/userprog/exception.c~ 2005-06-15 15:14:10.000000000 -0700
-+++ src/userprog/exception.c 2005-06-16 15:09:31.000000000 -0700
+--- src/userprog/exception.c   2006-01-29 13:32:56.000000000 -0800
++++ src/userprog/exception.c   2006-05-18 21:26:51.000000000 -0700
 @@ -4,6 +4,7 @@
  #include "userprog/gdt.h"
  #include "threads/interrupt.h"
@@ -2214,7 +2137,7 @@ diff -u src/userprog/exception.c~ src/userprog/exception.c
  
  /* Number of page faults processed. */
  static long long page_fault_cnt;
-@@ -153,9 +154,14 @@ page_fault (struct intr_frame *f) 
+@@ -148,9 +149,14 @@ page_fault (struct intr_frame *f) 
    write = (f->error_code & PF_W) != 0;
    user = (f->error_code & PF_U) != 0;
  
@@ -2232,19 +2155,20 @@ diff -u src/userprog/exception.c~ src/userprog/exception.c
    printf ("Page fault at %p: %s error %s page in %s context.\n",
            fault_addr,
            not_present ? "not present" : "rights violation",
+Index: src/userprog/pagedir.c
 diff -u src/userprog/pagedir.c~ src/userprog/pagedir.c
---- src/userprog/pagedir.c~ 2005-06-14 13:16:22.000000000 -0700
-+++ src/userprog/pagedir.c 2005-06-16 15:09:31.000000000 -0700
+--- src/userprog/pagedir.c     2006-04-22 22:25:23.000000000 -0700
++++ src/userprog/pagedir.c     2006-05-18 21:26:51.000000000 -0700
 @@ -35,15 +35,7 @@ pagedir_destroy (uint32_t *pd) 
    ASSERT (pd != base_page_dir);
    for (pde = pd; pde < pd + pd_no (PHYS_BASE); pde++)
-     if (*pde & PG_P) 
+     if (*pde & PTE_P) 
 -      {
 -        uint32_t *pt = pde_get_pt (*pde);
 -        uint32_t *pte;
 -        
 -        for (pte = pt; pte < pt + PGSIZE / sizeof *pte; pte++)
--          if (*pte & PG_P) 
+-          if (*pte & PTE_P) 
 -            palloc_free_page (pte_get_page (*pte));
 -        palloc_free_page (pt);
 -      }
@@ -2252,16 +2176,18 @@ diff -u src/userprog/pagedir.c~ src/userprog/pagedir.c
    palloc_free_page (pd);
  }
  
+Index: src/userprog/process.c
 diff -u src/userprog/process.c~ src/userprog/process.c
---- src/userprog/process.c~ 2005-06-14 13:09:39.000000000 -0700
-+++ src/userprog/process.c 2005-06-16 15:09:31.000000000 -0700
-@@ -14,11 +14,26 @@
+--- src/userprog/process.c     2006-05-18 17:35:55.000000000 -0700
++++ src/userprog/process.c     2006-05-18 22:12:19.000000000 -0700
+@@ -14,12 +14,27 @@
+ #include "threads/flags.h"
  #include "threads/init.h"
  #include "threads/interrupt.h"
- #include "threads/mmu.h"
 +#include "threads/malloc.h"
  #include "threads/palloc.h"
  #include "threads/thread.h"
+ #include "threads/vaddr.h"
 +#include "vm/page.h"
 +#include "vm/frame.h"
  
@@ -2274,7 +2200,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +   thread. */
 +struct exec_info 
 +  {
-+    const char *filename;               /* Program to load. */
++    const char *file_name;              /* Program to load. */
 +    struct semaphore load_done;         /* "Up"ed when loading complete. */
 +    struct wait_status *wait_status;    /* Child process. */
 +    struct dir *wd;                     /* Working directory. */
@@ -2282,10 +2208,10 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +  };
  
  /* Starts a new thread running a user program loaded from
-    FILENAME.  The new thread may be scheduled (and may even exit)
-@@ -27,41 +42,82 @@ static bool load (const char *cmdline, v
+    FILE_NAME.  The new thread may be scheduled (and may even exit)
+@@ -28,41 +43,78 @@ static bool load (const char *cmdline, v
  tid_t
- process_execute (const char *filename) 
+ process_execute (const char *file_name) 
  {
 -  char *fn_copy;
 +  struct dir *wd = thread_current ()->wd;
@@ -2294,27 +2220,23 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +  char *save_ptr;
    tid_t tid;
  
--  /* Make a copy of FILENAME.
+-  /* Make a copy of FILE_NAME.
 -     Otherwise there's a race between the caller and load(). */
 -  fn_copy = palloc_get_page (0);
 -  if (fn_copy == NULL)
 +  /* Initialize exec_info. */
-+  exec.filename = filename;
-+  if (wd) 
-+    {
-+      dir_reopen (wd);
-+      exec.wd = wd; 
-+    }
-+  else if (!dir_open_root (&exec.wd))
++  exec.file_name = file_name;
++  exec.wd = wd != NULL ? dir_reopen (wd) : dir_open_root ();
++  if (exec.wd == NULL)
      return TID_ERROR;
--  strlcpy (fn_copy, filename, PGSIZE);
+-  strlcpy (fn_copy, file_name, PGSIZE);
 +  sema_init (&exec.load_done, 0);
  
-   /* Create a new thread to execute FILENAME. */
--  tid = thread_create (filename, PRI_DEFAULT, execute_thread, fn_copy);
+   /* Create a new thread to execute FILE_NAME. */
+-  tid = thread_create (file_name, PRI_DEFAULT, execute_thread, fn_copy);
 -  if (tid == TID_ERROR)
 -    palloc_free_page (fn_copy); 
-+  strlcpy (thread_name, filename, sizeof thread_name);
++  strlcpy (thread_name, file_name, sizeof thread_name);
 +  strtok_r (thread_name, " ", &save_ptr);
 +  tid = thread_create (thread_name, PRI_DEFAULT, execute_thread, &exec);
 +  if (tid != TID_ERROR)
@@ -2337,10 +2259,10 @@ diff -u src/userprog/process.c~ src/userprog/process.c
  /* A thread function that loads a user process and starts it
     running. */
  static void
--execute_thread (void *filename_)
+-execute_thread (void *file_name_)
 +execute_thread (void *exec_)
  {
--  char *filename = filename_;
+-  char *file_name = file_name_;
 +  struct exec_info *exec = exec_;
    struct intr_frame if_;
    bool success;
@@ -2352,9 +2274,11 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    if_.gs = if_.fs = if_.es = if_.ds = if_.ss = SEL_UDSEG;
    if_.cs = SEL_UCSEG;
    if_.eflags = FLAG_IF | FLAG_MBS;
--  success = load (filename, &if_.eip, &if_.esp);
-+  success = load (exec->filename, &if_.eip, &if_.esp);
-+
+-  success = load (file_name, &if_.eip, &if_.esp);
++  success = load (exec->file_name, &if_.eip, &if_.esp);
+-  /* If load failed, quit. */
+-  palloc_free_page (file_name);
 +  /* Allocate wait_status. */
 +  if (success)
 +    {
@@ -2362,9 +2286,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +        = malloc (sizeof *exec->wait_status);
 +      success = exec->wait_status != NULL; 
 +    }
--  /* If load failed, quit. */
--  palloc_free_page (filename);
++
 +  /* Initialize wait_status. */
 +  if (success) 
 +    {
@@ -2380,7 +2302,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    if (!success) 
      thread_exit ();
  
-@@ -75,18 +131,47 @@ execute_thread (void *filename_)
+@@ -76,18 +128,47 @@ execute_thread (void *file_name_)
    NOT_REACHED ();
  }
  
@@ -2433,7 +2355,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    return -1;
  }
  
-@@ -95,8 +180,35 @@ void
+@@ -96,8 +177,35 @@ void
  process_exit (void)
  {
    struct thread *cur = thread_current ();
@@ -2462,30 +2384,31 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +
 +  /* Destroy the page hash table. */
 +  page_exit ();
-+
++  
 +  /* Close executable (and allow writes). */
 +  file_close (cur->bin_file);
-+  
++
    /* Destroy the current process's page directory and switch back
       to the kernel-only page directory. */
    pd = cur->pagedir;
-@@ -194,20 +306,22 @@ struct Elf32_Phdr
+@@ -194,7 +302,7 @@ struct Elf32_Phdr
+ #define PF_W 2          /* Writable. */
  #define PF_R 4          /* Readable. */
  
- static bool load_segment (struct file *, const struct Elf32_Phdr *);
 -static bool setup_stack (void **esp);
 +static bool setup_stack (const char *cmd_line, void **esp);
- /* Loads an ELF executable from FILENAME into the current thread.
-    Stores the executable's entry point into *EIP
+ static bool validate_segment (const struct Elf32_Phdr *, struct file *);
+ static bool load_segment (struct file *file, off_t ofs, uint8_t *upage,
+                           uint32_t read_bytes, uint32_t zero_bytes,
+@@ -205,13 +313,15 @@ static bool load_segment (struct file *f
     and its initial stack pointer into *ESP.
     Returns true if successful, false otherwise. */
  bool
--load (const char *filename, void (**eip) (void), void **esp) 
+-load (const char *file_name, void (**eip) (void), void **esp) 
 +load (const char *cmd_line, void (**eip) (void), void **esp) 
  {
    struct thread *t = thread_current ();
-+  char filename[NAME_MAX + 2];
++  char file_name[NAME_MAX + 2];
    struct Elf32_Ehdr ehdr;
    struct file *file = NULL;
    off_t file_ofs;
@@ -2494,7 +2417,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    int i;
  
    /* Allocate and activate page directory. */
-@@ -216,13 +330,28 @@ load (const char *filename, void (**eip)
+@@ -220,13 +330,28 @@ load (const char *file_name, void (**eip)
      goto done;
    process_activate ();
  
@@ -2504,27 +2427,27 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +    goto done;
 +  hash_init (t->pages, page_hash, page_less, NULL);
 +
-+  /* Extract filename from command line. */
++  /* Extract file_name from command line. */
 +  while (*cmd_line == ' ')
 +    cmd_line++;
-+  strlcpy (filename, cmd_line, sizeof filename);
-+  cp = strchr (filename, ' ');
++  strlcpy (file_name, cmd_line, sizeof file_name);
++  cp = strchr (file_name, ' ');
 +  if (cp != NULL)
 +    *cp = '\0';
 +
    /* Open executable file. */
--  file = filesys_open (filename);
-+  t->bin_file = file = file_open (filesys_open (filename));
+-  file = filesys_open (file_name);
++  t->bin_file = file = file_open (filesys_open (file_name));
    if (file == NULL) 
      {
-       printf ("load: %s: open failed\n", filename);
+       printf ("load: %s: open failed\n", file_name);
        goto done; 
      }
 +  file_deny_write (file);
  
    /* Read and verify executable header. */
    if (file_read (file, &ehdr, sizeof ehdr) != sizeof ehdr
-@@ -271,7 +400,7 @@ load (const char *filename, void (**eip)
+@@ -301,7 +426,7 @@ load (const char *file_name, void (**eip)
      }
  
    /* Set up stack. */
@@ -2533,84 +2456,66 @@ diff -u src/userprog/process.c~ src/userprog/process.c
      goto done;
  
    /* Start address. */
-@@ -280,15 +409,11 @@ load (const char *filename, void (**eip)
-   success = true;
+@@ -311,14 +436,11 @@ load (const char *file_name, void (**eip)
  
   done:
--  /* We arrive here whether the load is successful or not. */
+   /* We arrive here whether the load is successful or not. */
 -  file_close (file);
    return success;
  }
  \f
  /* load() helpers. */
  
--static bool install_page (void *upage, void *kpage);
+-static bool install_page (void *upage, void *kpage, bool writable);
 -
- /* Loads the segment described by PHDR from FILE into user
-    address space.  Return true if successful, false otherwise. */
+ /* Checks whether PHDR describes a valid, loadable segment in
+    FILE and returns true if so, false otherwise. */
  static bool
-@@ -296,6 +421,7 @@ load_segment (struct file *file, const s
- {
-   void *start, *end;  /* Page-rounded segment start and end. */
-   uint8_t *upage;     /* Iterator from start to end. */
-+  off_t file_offset;  /* Offset into file. */
-   off_t filesz_left;  /* Bytes left of file data (as opposed to
-                          zero-initialized bytes). */
-@@ -303,7 +429,7 @@ load_segment (struct file *file, const s
-      commented out.  You'll want to use it when implementing VM
-      to decide whether to page the segment from its executable or
-      from swap. */
--  //bool read_only = (phdr->p_flags & PF_W) == 0;
-+  bool read_only = (phdr->p_flags & PF_W) == 0;
-   ASSERT (file != NULL);
-   ASSERT (phdr != NULL);
-@@ -332,69 +458,129 @@ load_segment (struct file *file, const s
-       || start == 0)
-     return false; 
--  /* Load the segment page-by-page into memory. */
-+  /* Add the segment page-by-page to the hash table. */
-   filesz_left = phdr->p_filesz + (phdr->p_vaddr & PGMASK);
--  file_seek (file, ROUND_DOWN (phdr->p_offset, PGSIZE));
-+  file_offset = ROUND_DOWN (phdr->p_offset, PGSIZE);
-   for (upage = start; upage < (uint8_t *) end; upage += PGSIZE) 
+@@ -386,79 +508,127 @@ load_segment (struct file *file, off_t o
+   ASSERT (pg_ofs (upage) == 0);
+   ASSERT (ofs % PGSIZE == 0);
+-  file_seek (file, ofs);
+   while (read_bytes > 0 || zero_bytes > 0) 
      {
--      /* We want to read min(PGSIZE, filesz_left) bytes from the
--         file into the page and zero the rest. */
--      size_t read_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
--      size_t zero_bytes = PGSIZE - read_bytes;
+-      /* Calculate how to fill this page.
+-         We will read PAGE_READ_BYTES bytes from FILE
+-         and zero the final PAGE_ZERO_BYTES bytes. */
+       size_t page_read_bytes = read_bytes < PGSIZE ? read_bytes : PGSIZE;
+       size_t page_zero_bytes = PGSIZE - page_read_bytes;
+-
+-      /* Get a page of memory. */
 -      uint8_t *kpage = palloc_get_page (PAL_USER);
 -      if (kpage == NULL)
-+      struct page *p = page_allocate (upage, read_only);
++      struct page *p = page_allocate (upage, !writable);
 +      if (p == NULL)
          return false;
--      /* Do the reading and zeroing. */
--      if (file_read (file, kpage, read_bytes) != (int) read_bytes) 
-+      if (filesz_left > 0) 
-         {
+-
+-      /* Load this page. */
+-      if (file_read (file, kpage, page_read_bytes) != (int) page_read_bytes)
+-        {
 -          palloc_free_page (kpage);
 -          return false; 
 -        }
--      memset (kpage + read_bytes, 0, zero_bytes);
--      filesz_left -= read_bytes;
+-      memset (kpage + page_read_bytes, 0, page_zero_bytes);
 -
 -      /* Add the page to the process's address space. */
--      if (!install_page (upage, kpage)) 
--        {
+-      if (!install_page (upage, kpage, writable)) 
++      if (page_read_bytes > 0) 
+         {
 -          palloc_free_page (kpage);
 -          return false; 
-+          size_t file_bytes = filesz_left >= PGSIZE ? PGSIZE : filesz_left;
 +          p->file = file;
-+          p->file_offset = file_offset;
-+          p->file_bytes = file_bytes;
-+          filesz_left -= file_bytes;
-+          file_offset += file_bytes;
++          p->file_offset = ofs;
++          p->file_bytes = page_read_bytes;
          }
+-
+-      /* Advance. */
+       read_bytes -= page_read_bytes;
+       zero_bytes -= page_zero_bytes;
++      ofs += page_read_bytes;
+       upage += PGSIZE;
      }
    return true;
  }
  
@@ -2669,24 +2574,24 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +  cmd_line_copy = push (kpage, &ofs, cmd_line, strlen (cmd_line) + 1);
 +  if (cmd_line_copy == NULL)
 +    return false;
-+
-+  if (push (kpage, &ofs, &null, sizeof null) == NULL)
-+    return false;
  
 -  kpage = palloc_get_page (PAL_USER | PAL_ZERO);
 -  if (kpage != NULL) 
++  if (push (kpage, &ofs, &null, sizeof null) == NULL)
++    return false;
++
 +  /* Parse command line into arguments
 +     and push them in reverse order. */
 +  argc = 0;
 +  for (karg = strtok_r (cmd_line_copy, " ", &saveptr); karg != NULL;
 +       karg = strtok_r (NULL, " ", &saveptr))
      {
--      success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage);
+-      success = install_page (((uint8_t *) PHYS_BASE) - PGSIZE, kpage, true);
 -      if (success)
 -        *esp = PHYS_BASE;
 -      else
 -        palloc_free_page (kpage);
-+      char *uarg = upage + (karg - (char *) kpage);
++      void *uarg = upage + (karg - (char *) kpage);
 +      if (push (kpage, &ofs, &uarg, sizeof uarg) == NULL)
 +        return false;
 +      argc++;
@@ -2709,13 +2614,19 @@ diff -u src/userprog/process.c~ src/userprog/process.c
  }
  
 -/* Adds a mapping from user virtual address UPAGE to kernel
--   virtual address KPAGE to the page table.  Fails if UPAGE is
--   already mapped or if memory allocation fails. */
+-   virtual address KPAGE to the page table.
+-   If WRITABLE is true, the user process may modify the page;
+-   otherwise, it is read-only.
+-   UPAGE must not already be mapped.
+-   KPAGE should probably be a page obtained from the user pool
+-   with palloc_get_page().
+-   Returns true on success, false if UPAGE is already mapped or
+-   if memory allocation fails. */
 +/* Create a minimal stack for T by mapping a page at the
 +   top of user virtual memory.  Fills in the page using CMD_LINE
 +   and sets *ESP to the stack pointer. */
  static bool
--install_page (void *upage, void *kpage)
+-install_page (void *upage, void *kpage, bool writable)
 +setup_stack (const char *cmd_line, void **esp) 
  {
 -  struct thread *t = thread_current ();
@@ -2723,7 +2634,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 -  /* Verify that there's not already a page at that virtual
 -     address, then map our page there. */
 -  return (pagedir_get_page (t->pagedir, upage) == NULL
--          && pagedir_set_page (t->pagedir, upage, kpage, true));
+-          && pagedir_set_page (t->pagedir, upage, kpage, writable));
 +  struct page *page = page_allocate (((uint8_t *) PHYS_BASE) - PGSIZE, false);
 +  if (page != NULL) 
 +    {
@@ -2740,10 +2651,11 @@ diff -u src/userprog/process.c~ src/userprog/process.c
 +    }
 +  return false;
  }
+Index: src/userprog/syscall.c
 diff -u src/userprog/syscall.c~ src/userprog/syscall.c
---- src/userprog/syscall.c~ 2005-06-16 14:56:52.000000000 -0700
-+++ src/userprog/syscall.c 2005-06-16 15:09:31.000000000 -0700
-@@ -1,20 +1,594 @@
+--- src/userprog/syscall.c     2005-06-18 20:21:21.000000000 -0700
++++ src/userprog/syscall.c     2006-05-18 21:26:51.000000000 -0700
+@@ -1,20 +1,671 @@
  #include "userprog/syscall.h"
  #include <stdio.h>
 +#include <string.h>
@@ -2757,10 +2669,10 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +#include "threads/init.h"
  #include "threads/interrupt.h"
 +#include "threads/malloc.h"
-+#include "threads/mmu.h"
 +#include "threads/palloc.h"
  #include "threads/thread.h"
 -
++#include "threads/vaddr.h"
 +#include "vm/page.h"
 + 
 + 
@@ -2781,7 +2693,8 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +static int sys_munmap (int mapping);
 +static int sys_chdir (const char *udir);
 +static int sys_mkdir (const char *udir);
-+static int sys_lsdir (void);
++static int sys_readdir (int handle, char *name);
++static int sys_isdir (int handle);
 + 
  static void syscall_handler (struct intr_frame *);
 -
@@ -2826,7 +2739,8 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +      {1, (syscall_function *) sys_munmap},
 +      {1, (syscall_function *) sys_chdir},
 +      {1, (syscall_function *) sys_mkdir},
-+      {0, (syscall_function *) sys_lsdir},
++      {2, (syscall_function *) sys_readdir},
++      {1, (syscall_function *) sys_isdir},
 +    };
  
 +  const struct syscall *sc;
@@ -2876,6 +2790,32 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +    }
 +}
 + 
++/* Copies SIZE bytes from kernel address SRC to user address
++   UDST.
++   Call thread_exit() if any of the user accesses are invalid. */
++static void
++copy_out (void *udst_, const void *src_, size_t size) 
++{
++  uint8_t *udst = udst_;
++  const uint8_t *src = src_;
++
++  while (size > 0) 
++    {
++      size_t chunk_size = PGSIZE - pg_ofs (udst);
++      if (chunk_size > size)
++        chunk_size = size;
++      
++      if (!page_lock (udst, false))
++        thread_exit ();
++      memcpy (udst, src, chunk_size);
++      page_unlock (udst);
++
++      udst += chunk_size;
++      src += chunk_size;
++      size -= chunk_size;
++    }
++}
++ 
 +/* Creates a copy of user string US in kernel memory
 +   and returns it as a page that must be freed with
 +   palloc_free_page().
@@ -2985,6 +2925,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +  {
 +    struct list_elem elem;      /* List element. */
 +    struct file *file;          /* File. */
++    struct dir *dir;            /* Directory. */
 +    int handle;                 /* File handle. */
 +  };
 + 
@@ -2996,18 +2937,28 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +  struct file_descriptor *fd;
 +  int handle = -1;
 + 
-+  fd = malloc (sizeof *fd);
++  fd = calloc (1, sizeof *fd);
 +  if (fd != NULL)
 +    {
-+      fd->file = file_open (filesys_open (kfile));
-+      if (fd->file != NULL)
++      struct inode *inode = filesys_open (kfile);
++      if (inode != NULL)
 +        {
-+          struct thread *cur = thread_current ();
-+          handle = fd->handle = cur->next_handle++;
-+          list_push_front (&cur->fds, &fd->elem);
++          if (inode_get_type (inode) == FILE_INODE)
++            fd->file = file_open (inode);
++          else
++            fd->dir = dir_open (inode);
++          if (fd->file != NULL || fd->dir != NULL)
++            {
++              struct thread *cur = thread_current ();
++              handle = fd->handle = cur->next_handle++;
++              list_push_front (&cur->fds, &fd->elem);
++            }
++          else 
++            {
++              free (fd);
++              inode_close (inode);
++            }
 +        }
-+      else 
-+        free (fd);
 +    }
 +  
 +  palloc_free_page (kfile);
@@ -3035,11 +2986,35 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +  thread_exit ();
 +}
 + 
++/* Returns the file descriptor associated with the given handle.
++   Terminates the process if HANDLE is not associated with an
++   open ordinary file. */
++static struct file_descriptor *
++lookup_file_fd (int handle) 
++{
++  struct file_descriptor *fd = lookup_fd (handle);
++  if (fd->file == NULL)
++    thread_exit ();
++  return fd;
++}
++ 
++/* Returns the file descriptor associated with the given handle.
++   Terminates the process if HANDLE is not associated with an
++   open directory. */
++static struct file_descriptor *
++lookup_dir_fd (int handle) 
++{
++  struct file_descriptor *fd = lookup_fd (handle);
++  if (fd->dir == NULL)
++    thread_exit ();
++  return fd;
++}
++
 +/* Filesize system call. */
 +static int
 +sys_filesize (int handle) 
 +{
-+  struct file_descriptor *fd = lookup_fd (handle);
++  struct file_descriptor *fd = lookup_file_fd (handle);
 +  int size;
 + 
 +  size = file_length (fd->file);
@@ -3057,7 +3032,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +
 +  /* Look up file descriptor. */
 +  if (handle != STDIN_FILENO)
-+    fd = lookup_fd (handle);
++    fd = lookup_file_fd (handle);
 +
 +  while (size > 0) 
 +    {
@@ -3117,7 +3092,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +
 +  /* Lookup up file descriptor. */
 +  if (handle != STDOUT_FILENO)
-+    fd = lookup_fd (handle);
++    fd = lookup_file_fd (handle);
 +
 +  while (size > 0) 
 +    {
@@ -3133,7 +3108,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +      /* Do the write. */
 +      if (handle == STDOUT_FILENO)
 +        {
-+          putbuf (usrc, write_amt);
++          putbuf ((char *) usrc, write_amt);
 +          retval = write_amt;
 +        }
 +      else
@@ -3168,7 +3143,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +sys_seek (int handle, unsigned position) 
 +{
 +  if ((off_t) position >= 0)
-+    file_seek (lookup_fd (handle)->file, position);
++    file_seek (lookup_file_fd (handle)->file, position);
 +  return 0;
 +}
 + 
@@ -3176,7 +3151,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +static int
 +sys_tell (int handle) 
 +{
-+  return file_tell (lookup_fd (handle)->file);
++  return file_tell (lookup_file_fd (handle)->file);
 +}
 + 
 +/* Close system call. */
@@ -3185,6 +3160,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +{
 +  struct file_descriptor *fd = lookup_fd (handle);
 +  file_close (fd->file);
++  dir_close (fd->dir);
 +  list_remove (&fd->elem);
 +  free (fd);
 +  return 0;
@@ -3239,7 +3215,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +static int
 +sys_mmap (int handle, void *addr)
 +{
-+  struct file_descriptor *fd = lookup_fd (handle);
++  struct file_descriptor *fd = lookup_file_fd (handle);
 +  struct mapping *m = malloc (sizeof *m);
 +  size_t offset;
 +  off_t length;
@@ -3309,12 +3285,24 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +  return ok;
 +}
 +
-+/* Lsdir system call. */
++/* Readdir system call. */
 +static int
-+sys_lsdir (void) 
++sys_readdir (int handle, char *uname)
 +{
-+  dir_list (thread_current ()->wd);
-+  return 0;
++  struct file_descriptor *fd = lookup_dir_fd (handle);
++  char name[NAME_MAX + 1];
++  bool ok = dir_readdir (fd->dir, name);
++  if (ok)
++    copy_out (uname, name, strlen (name) + 1);
++  return ok;
++}
++
++/* Isdir system call. */
++static int
++sys_isdir (int handle)
++{
++  struct file_descriptor *fd = lookup_fd (handle);
++  return fd->dir != NULL;
 +}
 +\f 
 +/* On thread exit, close all open files and unmap all mappings. */
@@ -3329,6 +3317,7 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +      struct file_descriptor *fd = list_entry (e, struct file_descriptor, elem);
 +      next = list_next (e);
 +      file_close (fd->file);
++      dir_close (fd->dir);
 +      free (fd);
 +    }
 +   
@@ -3342,9 +3331,10 @@ diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 +
 +  dir_close (cur->wd);
 +}
+Index: src/userprog/syscall.h
 diff -u src/userprog/syscall.h~ src/userprog/syscall.h
---- src/userprog/syscall.h~ 2004-09-05 22:38:45.000000000 -0700
-+++ src/userprog/syscall.h 2005-06-16 15:09:31.000000000 -0700
+--- src/userprog/syscall.h     2004-09-05 22:38:45.000000000 -0700
++++ src/userprog/syscall.h     2006-05-18 21:26:51.000000000 -0700
 @@ -2,5 +2,6 @@
  #define USERPROG_SYSCALL_H
  
@@ -3352,9 +3342,10 @@ diff -u src/userprog/syscall.h~ src/userprog/syscall.h
 +void syscall_exit (void);
  
  #endif /* userprog/syscall.h */
+Index: src/vm/frame.c
 diff -u src/vm/frame.c~ src/vm/frame.c
---- src/vm/frame.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/frame.c 2005-06-16 15:09:31.000000000 -0700
+--- src/vm/frame.c     1969-12-31 16:00:00.000000000 -0800
++++ src/vm/frame.c     2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,161 @@
 +#include "vm/frame.h"
 +#include <stdio.h>
@@ -3362,9 +3353,9 @@ diff -u src/vm/frame.c~ src/vm/frame.c
 +#include "devices/timer.h"
 +#include "threads/init.h"
 +#include "threads/malloc.h"
-+#include "threads/mmu.h"
 +#include "threads/palloc.h"
 +#include "threads/synch.h"
++#include "threads/vaddr.h"
 +
 +static struct frame *frames;
 +static size_t frame_cnt;
@@ -3517,9 +3508,10 @@ diff -u src/vm/frame.c~ src/vm/frame.c
 +  ASSERT (lock_held_by_current_thread (&f->lock));
 +  lock_release (&f->lock);
 +}
+Index: src/vm/frame.h
 diff -u src/vm/frame.h~ src/vm/frame.h
---- src/vm/frame.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/frame.h 2005-06-16 15:09:31.000000000 -0700
+--- src/vm/frame.h     1969-12-31 16:00:00.000000000 -0800
++++ src/vm/frame.h     2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,23 @@
 +#ifndef VM_FRAME_H
 +#define VM_FRAME_H
@@ -3544,9 +3536,10 @@ diff -u src/vm/frame.h~ src/vm/frame.h
 +void frame_unlock (struct frame *);
 +
 +#endif /* vm/frame.h */
+Index: src/vm/page.c
 diff -u src/vm/page.c~ src/vm/page.c
---- src/vm/page.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/page.c 2005-06-16 15:09:31.000000000 -0700
+--- src/vm/page.c      1969-12-31 16:00:00.000000000 -0800
++++ src/vm/page.c      2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,294 @@
 +#include "vm/page.h"
 +#include <stdio.h>
@@ -3555,9 +3548,9 @@ diff -u src/vm/page.c~ src/vm/page.c
 +#include "vm/swap.h"
 +#include "filesys/file.h"
 +#include "threads/malloc.h"
-+#include "threads/mmu.h"
 +#include "threads/thread.h"
 +#include "userprog/pagedir.h"
++#include "threads/vaddr.h"
 +
 +/* Maximum size of process stack, in bytes. */
 +#define STACK_MAX (1024 * 1024)
@@ -3842,9 +3835,10 @@ diff -u src/vm/page.c~ src/vm/page.c
 +  ASSERT (p != NULL);
 +  frame_unlock (p->frame);
 +}
+Index: src/vm/page.h
 diff -u src/vm/page.h~ src/vm/page.h
---- src/vm/page.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/page.h 2005-06-16 15:09:31.000000000 -0700
+--- src/vm/page.h      1969-12-31 16:00:00.000000000 -0800
++++ src/vm/page.h      2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,50 @@
 +#ifndef VM_PAGE_H
 +#define VM_PAGE_H
@@ -3896,9 +3890,10 @@ diff -u src/vm/page.h~ src/vm/page.h
 +hash_less_func page_less;
 +
 +#endif /* vm/page.h */
+Index: src/vm/swap.c
 diff -u src/vm/swap.c~ src/vm/swap.c
---- src/vm/swap.c~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/swap.c 2005-06-16 15:09:31.000000000 -0700
+--- src/vm/swap.c      1969-12-31 16:00:00.000000000 -0800
++++ src/vm/swap.c      2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,85 @@
 +#include "vm/swap.h"
 +#include <bitmap.h>
@@ -3907,8 +3902,8 @@ diff -u src/vm/swap.c~ src/vm/swap.c
 +#include "vm/frame.h"
 +#include "vm/page.h"
 +#include "devices/disk.h"
-+#include "threads/mmu.h"
 +#include "threads/synch.h"
++#include "threads/vaddr.h"
 +
 +/* The swap disk. */
 +static struct disk *swap_disk;
@@ -3985,9 +3980,10 @@ diff -u src/vm/swap.c~ src/vm/swap.c
 +
 +  return true;
 +}
+Index: src/vm/swap.h
 diff -u src/vm/swap.h~ src/vm/swap.h
---- src/vm/swap.h~ 1969-12-31 16:00:00.000000000 -0800
-+++ src/vm/swap.h 2005-06-16 15:09:31.000000000 -0700
+--- src/vm/swap.h      1969-12-31 16:00:00.000000000 -0800
++++ src/vm/swap.h      2006-05-18 21:26:51.000000000 -0700
 @@ -0,0 +1,11 @@
 +#ifndef VM_SWAP_H
 +#define VM_SWAP_H 1