diff options
| author | Mole Shang <135e2@135e2.dev> | 2024-02-18 16:27:05 +0800 | 
|---|---|---|
| committer | Mole Shang <135e2@135e2.dev> | 2024-02-18 16:27:05 +0800 | 
| commit | 0cf897cbe05fd8485162619db4244f4159d0eb52 (patch) | |
| tree | b18d401102a0215f979f12ec3acf709f9e7224c4 | |
| parent | 659b978caa5c97bbc2477d1393461c944544a1a7 (diff) | |
| download | xv6-labs-fs.tar.gz xv6-labs-fs.tar.bz2 xv6-labs-fs.zip | |
lab fs/symlink: finishfs
| -rw-r--r-- | Makefile | 1 | ||||
| -rw-r--r-- | kernel/fcntl.h | 1 | ||||
| -rw-r--r-- | kernel/file.h | 1 | ||||
| -rw-r--r-- | kernel/stat.h | 1 | ||||
| -rw-r--r-- | kernel/syscall.c | 3 | ||||
| -rw-r--r-- | kernel/sysfile.c | 71 | ||||
| -rw-r--r-- | user/user.h | 1 | ||||
| -rwxr-xr-x | user/usys.pl | 1 | 
8 files changed, 80 insertions, 0 deletions
| @@ -189,6 +189,7 @@ UPROGS=\  	$U/_xargs\  	$U/_trace\  	$U/_sysinfotest\ +	$U/_symlinktest\ diff --git a/kernel/fcntl.h b/kernel/fcntl.h index 44861b9..d7bb43b 100644 --- a/kernel/fcntl.h +++ b/kernel/fcntl.h @@ -1,5 +1,6 @@  #define O_RDONLY  0x000  #define O_WRONLY  0x001  #define O_RDWR    0x002 +#define O_NOFOLLOW 0x010  #define O_CREATE  0x200  #define O_TRUNC   0x400 diff --git a/kernel/file.h b/kernel/file.h index b993cc3..05d9377 100644 --- a/kernel/file.h +++ b/kernel/file.h @@ -46,3 +46,4 @@ extern struct devsw devsw[];  #define CONSOLE 1  #define STATS   2 + diff --git a/kernel/stat.h b/kernel/stat.h index 19543af..9554d30 100644 --- a/kernel/stat.h +++ b/kernel/stat.h @@ -1,6 +1,7 @@  #define T_DIR     1   // Directory  #define T_FILE    2   // File  #define T_DEVICE  3   // Device +#define T_SYMLINK 4   // Symbolic link  struct stat {    int dev;     // File system's disk device diff --git a/kernel/syscall.c b/kernel/syscall.c index 172c5ea..c39ebd8 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -119,6 +119,7 @@ extern uint64 sys_connect(void);  #ifdef LAB_PGTBL  extern uint64 sys_pgaccess(void);  #endif +extern uint64 sys_symlink(void);  // An array mapping syscall numbers from syscall.h  // to the function that handles the system call. @@ -154,6 +155,7 @@ static uint64 (*syscalls[])(void) = {  [SYS_sysinfo] sys_sysinfo,  [SYS_sigalarm] sys_sigalarm,  [SYS_sigreturn] sys_sigreturn, +[SYS_symlink] sys_symlink,  };  // syscall name maps for SYS_trace: @@ -189,6 +191,7 @@ static char *syscall_names[] = {  [SYS_sysinfo] "sysinfo",  [SYS_sigalarm]  "sigalarm",  [SYS_sigreturn] "sigreturn", +[SYS_symlink]  "symlink",  }; diff --git a/kernel/sysfile.c b/kernel/sysfile.c index 4b2189a..9c12d44 100644 --- a/kernel/sysfile.c +++ b/kernel/sysfile.c @@ -16,6 +16,15 @@  #include "file.h"  #include "fcntl.h" +// symlink +#define SYMLINK_MAXFOLLOW 254 + +struct symlink { +  uint len; +  char target[MAXPATH]; +}; + +  // Fetch the nth word-sized system call argument as a file descriptor  // and return both the descriptor and the corresponding struct file.  static int @@ -258,6 +267,8 @@ create(char *path, short type, short major, short minor)      ilock(ip);      if(type == T_FILE && (ip->type == T_FILE || ip->type == T_DEVICE))        return ip; +    if(type == T_SYMLINK) +      return ip;      iunlockput(ip);      return 0;    } @@ -301,6 +312,37 @@ create(char *path, short type, short major, short minor)    return 0;  } +// create a symbolic link to path +uint64 +sys_symlink(void) +{ +  char path[MAXPATH]; +  struct inode *ip; +  struct symlink sl = {0}; + +  if(argstr(0, sl.target, MAXPATH) < 0 || argstr(1, path, MAXPATH) < 0) +    return -1; + +  sl.len = strlen(sl.target); + +  begin_op(); +  if((ip = create(path, T_SYMLINK, 0, 0)) == 0){ +    end_op(); +    return -1; +  } + +  if(writei(ip, 0, (uint64)&sl.len, 0, sizeof(sl.len)) != sizeof(sl.len) || writei(ip, 0, (uint64)sl.target, sizeof(sl.len), sl.len+1) != sl.len+1){ +    iunlockput(ip); +    end_op(); +    return -1; +  } + +  iupdate(ip); +  iunlockput(ip); +  end_op(); +  return 0; +} +  uint64  sys_open(void)  { @@ -341,6 +383,35 @@ sys_open(void)      return -1;    } +  if(ip->type == T_SYMLINK && !(omode & O_NOFOLLOW)){ +    int len = 0; +    uchar i; +    for(i = 0; i < SYMLINK_MAXFOLLOW; i++){ +      if(readi(ip, 0, (uint64)&len, 0, sizeof(len)) != sizeof(len) || +          readi(ip, 0, (uint64)path, sizeof(len), len+1) != len+1) { +        iunlockput(ip); +        end_op(); +        return -1; +      } +      iunlockput(ip); + +      if((ip = namei(path)) == 0) { +        end_op(); +        return -1; +      } + +      ilock(ip); +      if(ip->type != T_SYMLINK) +        break; +    } + +    if (i >= SYMLINK_MAXFOLLOW) { +      iunlockput(ip); +      end_op(); +      return -1; +    } +  } +    if((f = filealloc()) == 0 || (fd = fdalloc(f)) < 0){      if(f)        fileclose(f); diff --git a/user/user.h b/user/user.h index 3544ac4..c1bccdd 100644 --- a/user/user.h +++ b/user/user.h @@ -39,6 +39,7 @@ int trace(int);  int sysinfo(struct sysinfo*);  int sigalarm(int ticks, void (*handler)());  int sigreturn(void); +int symlink(char *, char *);  // ulib.c  int stat(const char*, struct stat*); diff --git a/user/usys.pl b/user/usys.pl index 33af0ad..7f07795 100755 --- a/user/usys.pl +++ b/user/usys.pl @@ -42,3 +42,4 @@ entry("connect");  entry("pgaccess");  entry("sigalarm");  entry("sigreturn"); +entry("symlink"); | 
