diff --git a/kernel/sysfile.c b/kernel/sysfile.c
index 3fd28fa3c43ee88e4c9408e52b3c9079c7cdec47..26b39629517e2222247fdb60f8936ad79415b839 100644
--- a/kernel/sysfile.c
+++ b/kernel/sysfile.c
@@ -1,9 +1,3 @@
-//
-// File-system system calls.
-// Mostly argument checking, since we don't trust
-// user code, and calls into file.c and fs.c.
-//
-
 
 #include "include/types.h"
 #include "include/riscv.h"
@@ -72,6 +66,37 @@ sys_dup(void)
   return fd;
 }
 
+uint64
+sys_dup3(void)
+{
+  struct file *f1;
+  struct file *f2;
+  int oldfd;
+  int newfd;
+
+  if(argfd(0, &oldfd, &f1) < 0)
+    return -1;
+  if(argint(1, &newfd) < 0)
+    return -1;
+  
+  if(newfd == oldfd)
+    return newfd;
+
+  if(newfd < 0 || newfd >= NOFILE)
+    return -1;
+
+  if(myproc()->ofile[newfd]){
+    f2 = myproc()->ofile[newfd];
+    myproc()->ofile[newfd] = 0;
+    fileclose(f2);
+  }
+
+  myproc()->ofile[newfd] = f1;
+  filedup(f1);
+
+  return newfd;
+}
+
 uint64
 sys_read(void)
 {
@@ -110,6 +135,33 @@ sys_close(void)
   return 0;
 }
 
+
+static void 
+getkstat(struct dirent *de, struct kstat *kst){
+  kst->st_dev = de->dev;
+  kst->st_ino = de->first_clus;
+  kst->st_mode = (de->attribute & ATTR_DIRECTORY) ? S_IFDIR : S_IFREG;
+  kst->st_nlink = 1;
+  kst->st_uid = 0;
+  kst->st_gid = 0;
+  kst->st_rdev = 0;
+  kst->__pad = 0;
+  kst->__pad2 = 0;
+  kst->st_size = de->file_size;
+  kst->st_blksize = get_byts_per_clus();
+  kst->st_blocks = (kst->st_size / kst->st_blksize);
+  if (kst->st_blocks * kst->st_blksize < kst->st_size)
+    kst->st_blocks++;
+  kst->st_atime_nsec = 0;
+  kst->st_atime_sec = 0;
+  kst->st_ctime_nsec = 0;
+  kst->st_ctime_sec = 0;
+  kst->st_mtime_nsec = 0;
+  kst->st_mtime_sec = 0;
+  kst->__unused[0] = 0;
+  kst->__unused[1] = 0;
+}
+
 uint64
 sys_fstat(void)
 {
@@ -119,6 +171,25 @@ sys_fstat(void)
   if(argfd(0, 0, &f) < 0 || argaddr(1, &st) < 0)
     return -1;
   return filestat(f, st);
+
+
+}
+
+uint64
+sys_fstatat(void)
+{
+  struct file *f;
+  struct kstat kst;
+  uint64 kst_addr;
+  if(argfd(0, 0, &f) < 0 || argaddr(1, &kst_addr) < 0)
+    return -1;
+
+  getkstat(f->ep, &kst);
+  if(copyout2(kst_addr, (char*)&kst, sizeof(kst)) < 0){
+    printf("sys_fstat:copyout2 failed\n");
+    return -1;
+  }
+  return 0;
 }
 
 static struct dirent*
@@ -160,6 +231,48 @@ create(char *path, short type, int mode)
   return ep;
 }
 
+
+//在f指定的目录项下创建目录,否则在当前工作目录下创建目录
+static struct dirent*
+create2(char *path, short type, int mode, struct file *f)
+{
+  struct dirent *ep, *dp;
+  char name[FAT32_MAX_FILENAME + 1];
+
+  if((dp = enameparent2(path, name, f)) == NULL){
+    printf("can't find dir\n");
+    return NULL;
+  }
+  if (type == T_DIR) {
+    mode = ATTR_DIRECTORY;
+  } else if (mode & O_RDONLY) {
+    mode = ATTR_READ_ONLY;
+  } else {
+    mode = 0;  
+  }
+
+  elock(dp);
+  if ((ep = ealloc(dp, name, mode)) == NULL) {
+    eunlock(dp);
+    eput(dp);
+    return NULL;
+  }
+  
+  if ((type == T_DIR && !(ep->attribute & ATTR_DIRECTORY)) ||
+      (type == T_FILE && (ep->attribute & ATTR_DIRECTORY))) {
+    eunlock(dp);
+    eput(ep);
+    eput(dp);
+    return NULL;
+  }
+
+  eunlock(dp);
+  eput(dp);
+
+  elock(ep);
+  return ep;
+}
+
 uint64
 sys_open(void)
 {
@@ -208,10 +321,98 @@ sys_open(void)
   f->writable = (omode & O_WRONLY) || (omode & O_RDWR);
 
   eunlock(ep);
+  
+  return fd;
+}
+
+
+uint64
+sys_openat(void)
+{
+  char path[FAT32_MAX_PATH];
+  int fd, flags, mode;
+  struct file *f;
+  struct file *f2;
+  struct dirent *ep;
+  f2 = NULL;
+
+  if(argint(0, &fd) < 0 || argstr(1, path, FAT32_MAX_PATH) < 0 || argint(2, &flags) < 0 || argint(3, &mode) < 0){
+    printf("can't read registers\n");
+    return -1;
+  }
+
+  //不是绝对路径
+  if(*path != '/' && fd >= 0 && fd < NOFILE){
+    f2 = myproc()->ofile[fd];
+  }
+  
+
+  if(flags & O_CREATE){
+    if(S_ISDIR(mode)){
+      ep = create2(path, T_DIR, flags, f2);
+      if(ep == NULL){
+        printf("create a dir failed\n");
+        return -1;
+      }
+    } else{
+      ep = create2(path, T_FILE, flags, f2);
+      if(ep == NULL){
+        printf("create a file failed\n");
+        return -1;
+      }
+    }
+  } else{//打开已有文件
+
+    if((ep = ename2(path, f2)) == NULL){
+      return -1;//从这退出了
+    }
+
+    elock(ep);
+
+    if((ep->attribute & ATTR_DIRECTORY) && ((flags & O_RDWR) || (flags & O_WRONLY))){
+      printf("dir can't write\n");
+      eunlock(ep);
+      eput(ep);
+      return -1;
+    }
+
+    if((flags & O_DIRECTORY) && !(ep->attribute & ATTR_DIRECTORY)){
+      printf("it is not dir\n");
+      eunlock(ep);
+      eput(ep);
+      return -1;
+    }
+
+  }
+
+  if((f = filealloc()) == NULL || (fd = fdalloc(f)) < 0){
+    printf("no free filetable or fd\n");
+    if (f) {
+      fileclose(f);
+    }
+    eunlock(ep);
+    eput(ep);
+    return -1;
+  }
+
+  if(!(ep->attribute & ATTR_DIRECTORY) && (flags & O_TRUNC)){
+    etrunc(ep);
+  }
+
+  f->type = FD_ENTRY;
+  f->off = (flags & O_APPEND) ? ep->file_size : 0;
+  f->ep = ep;
+  f->readable = !(flags & O_WRONLY);
+  f->writable = (flags & O_WRONLY) || (flags & O_RDWR);
+
+  eunlock(ep);
+
 
   return fd;
 }
 
+
+//接收路径作为参数,在当前工作目录下创建目录
 uint64
 sys_mkdir(void)
 {
@@ -226,6 +427,56 @@ sys_mkdir(void)
   return 0;
 }
 
+
+//在 dirfd 指定的目录下创建新目录,否则与 sys_mkdir() 等效
+uint64
+sys_mkdirat(void)
+{
+  int dirfd;
+  char path[FAT32_MAX_PATH];
+  char absolute_path[FAT32_MAX_PATH];
+  int mode;
+  int len;
+  char *s;
+  struct dirent *ep;
+  struct dirent *de;
+
+  if(argint(0, &dirfd) < 0 || argstr(1, path, FAT32_MAX_PATH) < 0 || argint(2, &mode) < 0){
+    return -1;
+  }
+  if(path[0] == '/'){ // absolute path
+    if((ep = create(path, T_DIR, mode)) == 0)
+      return -1;
+    eunlock(ep);
+    eput(ep);
+    return 0;
+  }
+  else if(dirfd == -100) // AT_CWDFD = -100
+    de = myproc()->cwd; 
+  else
+    de = myproc()->ofile[dirfd]->ep;
+    
+  s = absolute_path + FAT32_MAX_PATH - 1;
+  *s = '\0';
+  len = strlen(path);
+  s -= len;
+  strncpy(s, path, len);
+  while (de->parent) {
+    len = strlen(de->filename);
+    s -= len;
+    if (s <= absolute_path)          // can't reach root "/"
+      return 0;
+    strncpy(s, de->filename, len);
+    *--s = '/';
+    de = de->parent;
+  }
+  if((ep = create(s, T_DIR, mode)) == 0)
+    return -1;
+  eunlock(ep);
+  eput(ep);
+  return 0;
+}
+
 uint64
 sys_chdir(void)
 {
@@ -233,18 +484,24 @@ sys_chdir(void)
   struct dirent *ep;
   struct proc *p = myproc();
   
+  // 获取参数 path
   if(argstr(0, path, FAT32_MAX_PATH) < 0 || (ep = ename(path)) == NULL){
     return -1;
   }
+
   elock(ep);
+  // 判断是否为目录
   if(!(ep->attribute & ATTR_DIRECTORY)){
     eunlock(ep);
     eput(ep);
     return -1;
   }
   eunlock(ep);
+
+  // 释放原来的 cwd
   eput(p->cwd);
   p->cwd = ep;
+
   return 0;
 }
 
@@ -281,6 +538,46 @@ sys_pipe(void)
   return 0;
 }
 
+uint64
+sys_pipe2(void)
+{
+  uint64 fdarray; // user pointer to array of two integers
+  struct file *rf, *wf;
+  int fd0, fd1;
+  struct proc *p = myproc();
+  if(argaddr(0, &fdarray) < 0){
+    printf("can't read registers\n");
+    return -1;
+  }
+  if(pipealloc(&rf, &wf) < 0){
+    printf("create pipe failed\n");
+    return -1;
+  }
+
+  fd0 = -1;
+  if((fd0 = fdalloc(rf)) < 0 || (fd1 = fdalloc(wf)) < 0){
+    printf("no free fd\n");
+    if(fd0 >= 0)
+      p->ofile[fd0] = 0;
+    fileclose(rf);
+    fileclose(wf);
+    return -1;
+  }
+  // if(copyout(p->pagetable, fdarray, (char*)&fd0, sizeof(fd0)) < 0 ||
+  //    copyout(p->pagetable, fdarray+sizeof(fd0), (char *)&fd1, sizeof(fd1)) < 0){
+  if(copyout2(fdarray, (char*)&fd0, sizeof(fd0)) < 0 ||
+     copyout2(fdarray+sizeof(fd0), (char *)&fd1, sizeof(fd1)) < 0){
+    printf("copy failed\n");
+    p->ofile[fd0] = 0;
+    p->ofile[fd1] = 0;
+    fileclose(rf);
+    fileclose(wf);
+    return -1;
+  }
+  // printf("fd[0] = %d, fd[1] = %d\n", (*((int*)fdarray)), (*((int*)(fdarray + sizeof(fd0)))));
+  return 0;
+}
+
 // To open console device.
 uint64
 sys_dev(void)
@@ -333,8 +630,9 @@ uint64
 sys_getcwd(void)
 {
   uint64 addr;
-  if (argaddr(0, &addr) < 0)
-    return -1;
+  int size;
+  if (argaddr(0, &addr) < 0 || argint(1, &size) < 0)
+    return NULL;
 
   struct dirent *de = myproc()->cwd;
   char path[FAT32_MAX_PATH];
@@ -356,12 +654,16 @@ sys_getcwd(void)
       de = de->parent;
     }
   }
-
+  if (size < strlen(s) + 1){
+    if (copyout2(addr, s, strlen(s) + 1) < 0)
+      return NULL;
+  }
   // if (copyout(myproc()->pagetable, addr, s, strlen(s) + 1) < 0)
-  if (copyout2(addr, s, strlen(s) + 1) < 0)
-    return -1;
-  
-  return 0;
+  else{ 
+    if (copyout2(addr, s, strlen(s) + 1) < 0)
+      return NULL;
+  }
+  return addr;
 
 }
 
@@ -494,3 +796,196 @@ fail:
     eput(src);
   return -1;
 }
+
+void getdstat(struct dirent *de, struct dstat *st)
+{
+  strncpy(st->d_name, de->filename, STAT_MAX_NAME);
+  st->d_type = (de->attribute & ATTR_DIRECTORY) ? S_IFDIR : S_IFREG;
+  st->d_ino = de->first_clus;
+  st->d_off = 0;
+  st->d_reclen = de->file_size;
+}
+
+uint64
+sys_getdents64(void){
+  int len;
+  struct file *f; 
+  uint64 buf;
+  struct dstat ds;
+  if(argaddr(1, &buf) < 0 || argfd(0, 0, &f) < 0 || argint(1, &len) < 0){
+    printf("can't read registers\n");
+    return -1;
+  }
+
+  // (&ds)->d_ino    = f->ep->first_clus;
+  // (&ds)->d_off    = 0;
+  // (&ds)->d_reclen = f->ep->file_size;
+  // (&ds)->d_type   = (f->ep->attribute & ATTR_DIRECTORY) ? S_IFDIR : S_IFREG;
+  // strncpy((&ds)->d_name, f->ep->filename, STAT_MAX_NAME);
+  getdstat(f->ep, &ds);
+  if(copyout2(buf, (char*)&ds, sizeof(ds)) < 0){
+    printf("copy wrong\n");
+    return -1;
+  }
+
+  return sizeof(ds);
+  // return 0;
+}
+
+uint64
+sys_mount(void)
+{
+      char mount_path[FAT32_MAX_PATH];
+    char dev_path[FAT32_MAX_PATH];
+    char  fstype[10];
+     int  flags;
+  struct dirent *ep,*dev_ep;
+
+    if(argstr(0,dev_path,FAT32_MAX_PATH)<0||argstr(1,mount_path,FAT32_MAX_PATH)<0)
+    {
+      return -1;
+    }
+
+    if(argstr(2,fstype,10)<0|| argint(3, (int*)&flags) <0)
+    {
+        return -1;
+    }
+    //mountpoint  not allowed the root
+    if(strncmp("/",mount_path,2)==0)
+    {
+      printf("not allowed\n");
+      return -1;
+    }
+    if((dev_ep=ename(dev_path))==NULL)
+    {
+      printf("dev not found file");
+      return -1;
+    }
+
+   if((ep=ename(mount_path))==NULL)
+   {
+       printf("mount not found file");
+     return -1;
+   }
+   
+   if(!(ep->attribute & ATTR_DIRECTORY))
+   {
+     printf("mountpoint is not a dir");
+     return -1;
+   }
+   if (strncmp("vfat", fstype, 5) != 0 &&
+		strncmp("fat32", fstype, 6) != 0)
+  {
+    printf("the fstype is not fat32");
+		return -1;
+	}
+    int ret= do_mount(ep,dev_ep);
+    return ret;
+
+  // char special[FAT32_MAX_PATH],dir[FAT32_MAX_PATH],fstype[FAT32_MAX_PATH];
+  // int flags;
+  // uint64 data;
+  
+  // if(argstr(0, special, FAT32_MAX_PATH) < 0||argstr(1, dir, FAT32_MAX_PATH) < 0||argstr(2, fstype, FAT32_MAX_PATH) < 0||argint(3, &flags) < 0||argaddr(4, &data) < 0) 
+  //   return -1;
+  
+  // struct dirent *mydir;
+  // if((mydir = ename(dir)) == 0){
+  //   return -1;
+  // }
+  // elock(mydir);
+  // mydir->attribute |= 0x40;
+  // if(emount(dir, NULL) == -1){
+  //     mydir->attribute &= ~0x40;
+  //     return -1;
+  // }
+  // eunlock(mydir);
+  // return 0;
+}
+
+uint64
+sys_umount2(void)
+{
+  	char dev_path[FAT32_MAX_PATH];
+  argstr(0,dev_path,FAT32_MAX_PATH);
+  struct dirent*ep;
+  if(strncmp("/",dev_path,2)==0)
+  {
+    printf("path error");
+    return -1;
+  }
+
+  if((ep=ename(dev_path))==NULL)
+  {
+    printf("not found file\n");
+    return -1;
+  }
+   int ret=do_umount(ep);
+	return ret;
+
+  // eumount(NULL);
+  // return 0;
+
+}
+
+
+uint64
+sys_mmap(void)
+{
+	uint64 start, len, prot, flags, fd, off;
+  if (argaddr(0, &start) < 0||argaddr(1, &len) < 0||argaddr(2, &prot)||argaddr(3, &flags)||argaddr(4, &fd)||argaddr(5, &off)){
+		return -1;
+  }
+	
+	return do_mmap(start, len, prot, flags, fd, off);
+}
+
+uint64 sys_munmap(void){
+  uint64 start, len;
+  if (argaddr(0, &start) < 0||argaddr(1, &len) < 0){
+    return -1;
+  }
+  return do_munmap(start,(long)len);
+}
+
+uint64
+sys_linkat(void){
+  int olddirfd, newdirfd;
+  char oldpath[FAT32_MAX_PATH], newpath[FAT32_MAX_PATH];
+  int flags;
+  struct file *f1, *f2;
+  f1 = NULL;f2 = NULL;
+  if(argint(0, &olddirfd) < 0 || argstr(1, oldpath, FAT32_MAX_PATH) < 0){
+    printf("can't read register\n");
+    return -1;
+  }
+  if(argint(2, &newdirfd) < 0 || argstr(3, newpath, FAT32_MAX_PATH) < 0 || argint(4, &flags) < 0){
+    printf("can't read register\n");
+    return -1;
+  }
+  if(*oldpath != '/' && olddirfd >= 0 && olddirfd < NOFILE){
+    f1 = myproc()->ofile[olddirfd];
+  }
+  if(*newpath != '/' && newdirfd >= 0 && newdirfd < NOFILE){
+    f2 = myproc()->ofile[newdirfd];
+  }
+  return link(oldpath, f1, newpath, f2);  
+}
+
+uint64
+sys_unlinkat(void){
+  int dirfd;
+  char path[FAT32_MAX_PATH];
+  int flags;
+  struct file *f;
+  f = NULL;
+  if(argint(0, &dirfd) < 0 || argstr(1, path, FAT32_MAX_PATH) < 0 || argint(2, &flags) < 0){
+    printf("can't read register\n");
+    return -1;
+  }
+  if(*path != '/' && dirfd >= 0 && dirfd < NOFILE){
+    f = myproc()->ofile[dirfd];
+  }
+  return unlink(path, f);
+}
+