diff options
author | Mole Shang <[email protected]> | 2024-02-18 16:27:05 +0800 |
---|---|---|
committer | Mole Shang <[email protected]> | 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"); |