Wordsmithing.
[pintos-anon] / solutions / p4.patch
index 2342ca94417654e643b7e5b3fcdd5148647319d1..61ef9e8ab541aae4cd490003585a50b318db4c91 100644 (file)
@@ -6,7 +6,7 @@ diff -u src/Makefile.build~ src/Makefile.build
  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
@@ -722,25 +722,32 @@ diff -u src/filesys/directory.c~ src/filesys/directory.c
    return success;
  }
  
-@@ -205,8 +210,10 @@ dir_list (const struct dir *dir)
+@@ -216,14 +216,17 @@
+ {
    struct dir_entry e;
-   size_t ofs;
-   
 +  inode_lock (dir->inode);
-   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);
+   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    2006-05-18 22:26:02.000000000 -0700
 +++ src/filesys/directory.h    2006-05-18 22:05:40.000000000 -0700
 @@ -12,6 +11,5 @@
- #define NAME_MAX 14
  struct inode;
+ /* Opening and closing directories. */
 -bool dir_create (disk_sector_t sector, size_t entry_cnt);
  struct dir *dir_open (struct inode *);
  struct dir *dir_open_root (void);
@@ -773,10 +780,10 @@ 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 +25,7 @@ filesys_init (bool format) 
-     PANIC ("hd0:1 (hdb) not present, filesystem initialization failed");
+     PANIC ("hd0:1 (hdb) not present, file system initialization failed");
  
    inode_init ();
 +  cache_init ();
@@ -828,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;
@@ -871,14 +878,14 @@ 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
@@ -891,24 +898,24 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +filesys_create (const char *name, off_t initial_size, enum inode_type type) 
  {
 +  struct dir *dir;
-+  char basename[NAME_MAX + 1];
++  char base_name[NAME_MAX + 1];
    disk_sector_t inode_sector = 0;
 -  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));
-+  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));
++                  && 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 +161,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. */
@@ -917,14 +924,18 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
  filesys_open (const char *name)
  {
 -  struct dir *dir = dir_open_root ();
-+  struct dir *dir;
-+  char basename[NAME_MAX + 1];
++  struct dir *dir = NULL;
++  char base_name[NAME_MAX + 1];
    struct inode *inode = NULL;
  
 -  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);
@@ -932,23 +943,23 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
  }
  
  /* Deletes the file named NAME.
-@@ -84,13 +182,56 @@ filesys_open (const char *name)
+@@ -84,7 +182,11 @@ filesys_open (const char *name)
  bool
  filesys_remove (const char *name) 
  {
 -  struct dir *dir = dir_open_root ();
 -  bool success = dir != NULL && dir_remove (dir, name);
 +  struct dir *dir = NULL;
-+  char basename[NAME_MAX + 1];
++  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
@@ -967,11 +978,11 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 +    }
 +  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)
++      if (!resolve_name (name, &dir, base_name)
++          || !dir_lookup (dir, base_name, &base_inode)
 +          || (base_dir = dir_open (base_inode)) == NULL)
 +        {
 +          dir_close (dir);
@@ -988,28 +999,9 @@ 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,
-@@ -98,15 +239,9 @@ filesys_remove (const char *name) 
- bool
- filesys_list (void) 
- {
--  struct dir *dir = dir_open_root ();
--  if (dir != NULL) 
--    {
--      dir_list (dir);
--      dir_close (dir);
--      return true;
--    }
--  else
--    return false;
-+  dir_list (thread_current ()->wd);
-+
-+  return true;
- }
  \f
  static void must_succeed_function (int, bool) NO_INLINE;
+ #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
@@ -1042,7 +1034,7 @@ diff -u src/filesys/filesys.c~ src/filesys/filesys.c
 @@ -173,9 +308,13 @@ static void
  do_format (void)
  {
-   printf ("Formatting filesystem...");
+   printf ("Formatting file system...");
 +
 +  /* Set up free map. */
    free_map_create ();
@@ -1067,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);
@@ -1076,8 +1068,10 @@ 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-18 20:20:48.000000000 -0700
@@ -1198,32 +1192,32 @@ diff -u src/filesys/fsutil.c~ src/filesys/fsutil.c
 @@ -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
@@ -2206,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. */
@@ -2214,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)
+    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;
@@ -2226,23 +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;
++  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)
@@ -2265,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;
@@ -2280,11 +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 (filename);
+-  palloc_free_page (file_name);
 +  /* Allocate wait_status. */
 +  if (success)
 +    {
@@ -2308,7 +2302,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    if (!success) 
      thread_exit ();
  
-@@ -76,18 +128,47 @@ execute_thread (void *filename_)
+@@ -76,18 +128,47 @@ execute_thread (void *file_name_)
    NOT_REACHED ();
  }
  
@@ -2410,11 +2404,11 @@ diff -u src/userprog/process.c~ src/userprog/process.c
     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;
@@ -2423,7 +2417,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
    int i;
  
    /* Allocate and activate page directory. */
-@@ -220,13 +330,28 @@ load (const char *filename, void (**eip)
+@@ -220,13 +330,28 @@ load (const char *file_name, void (**eip)
      goto done;
    process_activate ();
  
@@ -2433,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
-@@ -301,7 +426,7 @@ load (const char *filename, void (**eip)
+@@ -301,7 +426,7 @@ load (const char *file_name, void (**eip)
      }
  
    /* Set up stack. */
@@ -2462,7 +2456,7 @@ diff -u src/userprog/process.c~ src/userprog/process.c
      goto done;
  
    /* Start address. */
-@@ -311,14 +436,11 @@ load (const char *filename, void (**eip)
+@@ -311,14 +436,11 @@ load (const char *file_name, void (**eip)
  
   done:
    /* We arrive here whether the load is successful or not. */
@@ -2661,7 +2655,7 @@ Index: src/userprog/syscall.c
 diff -u src/userprog/syscall.c~ src/userprog/syscall.c
 --- 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,594 @@
+@@ -1,20 +1,671 @@
  #include "userprog/syscall.h"
  #include <stdio.h>
 +#include <string.h>
@@ -2699,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 *);
 -
@@ -2744,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;
@@ -2794,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().
@@ -2903,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. */
 +  };
 + 
@@ -2914,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);
@@ -2953,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);
@@ -2975,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) 
 +    {
@@ -3035,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) 
 +    {
@@ -3086,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;
 +}
 + 
@@ -3094,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. */
@@ -3103,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;
@@ -3157,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;
@@ -3227,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. */
@@ -3247,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);
 +    }
 +