make grade 100/100
This commit is contained in:
parent
f187a07854
commit
4368fbf44c
1
Makefile
1
Makefile
@ -188,6 +188,7 @@ UPROGS=\
|
|||||||
$U/_grind\
|
$U/_grind\
|
||||||
$U/_wc\
|
$U/_wc\
|
||||||
$U/_zombie\
|
$U/_zombie\
|
||||||
|
$U/_symlinktest\
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -3,3 +3,4 @@
|
|||||||
#define O_RDWR 0x002
|
#define O_RDWR 0x002
|
||||||
#define O_CREATE 0x200
|
#define O_CREATE 0x200
|
||||||
#define O_TRUNC 0x400
|
#define O_TRUNC 0x400
|
||||||
|
#define O_NOFOLLOW 0x800
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#define T_DIR 1 // Directory
|
#define T_DIR 1 // Directory
|
||||||
#define T_FILE 2 // File
|
#define T_FILE 2 // File
|
||||||
#define T_DEVICE 3 // Device
|
#define T_DEVICE 3 // Device
|
||||||
|
#define T_SYMLINK 4
|
||||||
struct stat {
|
struct stat {
|
||||||
int dev; // File system's disk device
|
int dev; // File system's disk device
|
||||||
uint ino; // Inode number
|
uint ino; // Inode number
|
||||||
|
|||||||
@ -101,6 +101,7 @@ extern uint64 sys_unlink(void);
|
|||||||
extern uint64 sys_link(void);
|
extern uint64 sys_link(void);
|
||||||
extern uint64 sys_mkdir(void);
|
extern uint64 sys_mkdir(void);
|
||||||
extern uint64 sys_close(void);
|
extern uint64 sys_close(void);
|
||||||
|
extern uint64 sys_symlink(void);
|
||||||
|
|
||||||
// An array mapping syscall numbers from syscall.h
|
// An array mapping syscall numbers from syscall.h
|
||||||
// to the function that handles the system call.
|
// to the function that handles the system call.
|
||||||
@ -126,6 +127,7 @@ static uint64 (*syscalls[])(void) = {
|
|||||||
[SYS_link] sys_link,
|
[SYS_link] sys_link,
|
||||||
[SYS_mkdir] sys_mkdir,
|
[SYS_mkdir] sys_mkdir,
|
||||||
[SYS_close] sys_close,
|
[SYS_close] sys_close,
|
||||||
|
[SYS_symlink] sys_symlink,
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@ -20,3 +20,4 @@
|
|||||||
#define SYS_link 19
|
#define SYS_link 19
|
||||||
#define SYS_mkdir 20
|
#define SYS_mkdir 20
|
||||||
#define SYS_close 21
|
#define SYS_close 21
|
||||||
|
#define SYS_symlink 22
|
||||||
@ -335,6 +335,36 @@ sys_open(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ip->type == T_SYMLINK && !(omode & O_NOFOLLOW)) {
|
||||||
|
int symlink_step = 0;
|
||||||
|
while (ip->type == T_SYMLINK) {
|
||||||
|
if (symlink_step++ > 10) {
|
||||||
|
// printf("\x1b[031mFailed\x1b[0m due to deep symlink\n");
|
||||||
|
iunlockput(ip); // on error, put inode 'cause only success open need to use the file after the syscall
|
||||||
|
end_op();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int len_target = readi(ip, 0, (uint64)path, 0, MAXPATH);
|
||||||
|
iunlockput(ip); // no more need to use this inode
|
||||||
|
if (len_target == 0) {
|
||||||
|
printf("\x1b[031mFailed\x1b[0m to read symlink %s\n", path);
|
||||||
|
end_op();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
// get target's inode
|
||||||
|
if((ip = namei(path)) == 0){
|
||||||
|
// printf("\x1b[031mFailed\x1b[0m open symlink target %s\n", path);
|
||||||
|
end_op();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ilock(ip);
|
||||||
|
if(ip->type == T_DIR && omode != O_RDONLY){
|
||||||
|
iunlockput(ip);
|
||||||
|
end_op();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){
|
if(ip->type == T_DEVICE && (ip->major < 0 || ip->major >= NDEV)){
|
||||||
iunlockput(ip);
|
iunlockput(ip);
|
||||||
end_op();
|
end_op();
|
||||||
@ -503,3 +533,32 @@ sys_pipe(void)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64
|
||||||
|
sys_symlink(void)
|
||||||
|
{
|
||||||
|
char target[MAXPATH], path[MAXPATH];
|
||||||
|
int len_target, len_path;
|
||||||
|
struct inode* ip;
|
||||||
|
if ((len_target = argstr(0, target, MAXPATH)) < 0)
|
||||||
|
return -1;
|
||||||
|
if ((len_path = argstr(1, path, MAXPATH)) < 0)
|
||||||
|
return -1;
|
||||||
|
// printf("\x1b[033msys_symlink\x1b[0m %s -> %s\n", path, target);
|
||||||
|
begin_op();
|
||||||
|
ip = create(path, T_SYMLINK, 0, 0);
|
||||||
|
if (ip == 0) {
|
||||||
|
end_op();
|
||||||
|
// printf("\x1b[031mFailed\x1b[0m to create path %s\n", path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (writei(ip, 0, (uint64)target, 0, len_target) != len_target) {
|
||||||
|
iunlockput(ip);
|
||||||
|
end_op();
|
||||||
|
printf("\x1b[031mFailed\x1b[0m to write symlink target %s to %s\n", target, path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
iunlockput(ip); // no need to keep this inode ref, if not put, in-RAM inode pool will run out
|
||||||
|
end_op();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@ -32,11 +32,8 @@ main()
|
|||||||
printf("bigfile: file is too small\n");
|
printf("bigfile: file is too small\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
printf("bef close fd\n");
|
|
||||||
close(fd);
|
close(fd);
|
||||||
printf("aft close fd\n");
|
|
||||||
fd = open("big.file", O_RDONLY);
|
fd = open("big.file", O_RDONLY);
|
||||||
printf("aft open\n");
|
|
||||||
if(fd < 0){
|
if(fd < 0){
|
||||||
printf("bigfile: cannot re-open big.file for reading\n");
|
printf("bigfile: cannot re-open big.file for reading\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
|
|||||||
@ -22,6 +22,7 @@ int getpid(void);
|
|||||||
char* sbrk(int);
|
char* sbrk(int);
|
||||||
int sleep(int);
|
int sleep(int);
|
||||||
int uptime(void);
|
int uptime(void);
|
||||||
|
int symlink(char* target, char* path);
|
||||||
|
|
||||||
// ulib.c
|
// ulib.c
|
||||||
int stat(const char*, struct stat*);
|
int stat(const char*, struct stat*);
|
||||||
|
|||||||
@ -36,3 +36,4 @@ entry("getpid");
|
|||||||
entry("sbrk");
|
entry("sbrk");
|
||||||
entry("sleep");
|
entry("sleep");
|
||||||
entry("uptime");
|
entry("uptime");
|
||||||
|
entry("symlink");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user