Big commit: Added symlink support to the kernel.

- added needed syscalls to access symlink support from userland
- implemented lstat(), symlink(), and readlink()
- added dev_t to ktypes.h (for now - should be in a public header anyway)
- added symlink support to the "ls" command (now calls lstat() and shows the
  link target with the -l option)
- changed the sys_read_stat() call to support symlinks, and updated files
  using that function (it gets an extra argument: bool traverseLink)


git-svn-id: file:///srv/svn/repos/haiku/trunk/current@560 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2002-08-03 02:03:27 +00:00
parent 409a1aeacd
commit ae372703ce
15 changed files with 336 additions and 366 deletions
+15
View File
@@ -351,6 +351,7 @@ KernelStaticLibraryObjects libc.a :
<$(SOURCE_GRIST)!libc!unistd>lseek.o
<$(SOURCE_GRIST)!libc!unistd>open.o
<$(SOURCE_GRIST)!libc!unistd>opendir.o
<$(SOURCE_GRIST)!libc!unistd>link.o
<$(SOURCE_GRIST)!libc!unistd>pread.o
<$(SOURCE_GRIST)!libc!unistd>pwrite.o
<$(SOURCE_GRIST)!libc!unistd>read.o
@@ -467,6 +468,7 @@ KernelLd libc.so :
<$(SOURCE_GRIST)!libc!unistd>lseek.o
<$(SOURCE_GRIST)!libc!unistd>open.o
<$(SOURCE_GRIST)!libc!unistd>opendir.o
<$(SOURCE_GRIST)!libc!unistd>link.o
<$(SOURCE_GRIST)!libc!unistd>pread.o
<$(SOURCE_GRIST)!libc!unistd>pwrite.o
<$(SOURCE_GRIST)!libc!unistd>read.o
@@ -585,6 +587,19 @@ KernelLd ls :
bin/ls
;
KernelLd symlink :
libglue2.o
<$(SOURCE_GRIST)!apps!symlink>main.o
libc.so
libm.so
:
$(SUBDIR)/ldscripts/$(OBOS_ARCH)/app.ld
:
:
:
bin/symlink
;
# Note: shell is a built in target, thus we need the grist.
KernelLd obos_shell :
libglue2.o
+1
View File
@@ -7,6 +7,7 @@ SubInclude OBOS_TOP src kernel apps filetest ;
SubInclude OBOS_TOP src kernel apps fortune ;
SubInclude OBOS_TOP src kernel apps hostname ;
SubInclude OBOS_TOP src kernel apps ls ;
SubInclude OBOS_TOP src kernel apps symlink ;
SubInclude OBOS_TOP src kernel apps ps ;
SubInclude OBOS_TOP src kernel apps rld ;
SubInclude OBOS_TOP src kernel apps shell ;
+31 -14
View File
@@ -12,7 +12,7 @@
extern char *__progname;
void (*disp_func)(const char *, struct stat *) = NULL;
void (*disp_func)(const char *, const char *, struct stat *) = NULL;
static int show_all = 0;
mode_t perms [9] = {
@@ -27,7 +27,9 @@ mode_t perms [9] = {
S_IXOTH
};
static void display_l(const char *filename, struct stat *stat)
static void
display_l(const char *path, const char *filename, struct stat *stat)
{
const char *type;
char perm[11];
@@ -51,16 +53,32 @@ static void display_l(const char *filename, struct stat *stat)
}
if (S_ISDIR(stat->st_mode))
perm[0] = 'd';
printf("%10s %12lld %s\n" ,perm ,stat->st_size ,filename);
else if (S_ISLNK(stat->st_mode))
perm[0] = 'l';
else if (S_ISCHR(stat->st_mode))
perm[0] = 'c';
printf("%10s %12lld %s" ,perm ,stat->st_size ,filename);
if (S_ISLNK(stat->st_mode)) {
char buffer[1024];
if (readlink(path, buffer, sizeof(buffer)) != 0)
strcpy(buffer, "???");
printf(" (-> %s)\n", buffer);
} else
putchar('\n');
}
static void display(const char *filename, struct stat *stat)
static void
display(const char *path, const char *filename, struct stat *stat)
{
printf("%s\n", filename);
}
int main(int argc, char *argv[])
int
main(int argc, char *argv[])
{
int rc;
int rc2;
@@ -85,14 +103,13 @@ int main(int argc, char *argv[])
argc -= optind;
argv += optind;
if(*argv == NULL) {
if (*argv == NULL)
arg = ".";
} else {
else
arg = *argv;
}
rc = stat(arg, &st);
if(rc < 0) {
if (rc < 0) {
printf("%s: %s: %s\n", __progname,
arg, strerror(rc));
goto err_ls;
@@ -109,7 +126,7 @@ int main(int argc, char *argv[])
/* process the '.' entry */
rc = stat(arg, &st);
if (rc == 0) {
(*disp_func)(".", &st);
(*disp_func)(arg, ".", &st);
totbytes += st.st_size;
}
}
@@ -128,9 +145,9 @@ int main(int argc, char *argv[])
}
strlcat(buf2, de->d_name, sizeof(buf2));
rc2 = stat(buf2, &st);
rc2 = lstat(buf2, &st);
if (rc2 == 0) {
(*disp_func)(de->d_name, &st);
(*disp_func)(buf2, de->d_name, &st);
totbytes += st.st_size;
}
count++;
@@ -140,7 +157,7 @@ int main(int argc, char *argv[])
printf("%lld bytes in %d files\n", totbytes, count);
} else {
(*disp_func)(arg, &st);
(*disp_func)(arg, arg, &st);
}
err_ls:
+4 -3
View File
@@ -2,6 +2,7 @@
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
** Distributed under the terms of the NewOS License.
*/
#include <syscalls.h>
#include <stdio.h>
#include <string.h>
@@ -168,13 +169,13 @@ int cmd_stat(int argc, char *argv[])
int rc;
struct stat stat;
if(argc < 2) {
if (argc < 2) {
printf("not enough arguments to stat\n");
return 0;
}
rc = sys_read_stat(argv[1], &stat);
if(rc >= 0) {
rc = sys_read_stat(argv[1], true, &stat);
if (rc >= 0) {
printf("stat of file '%s': \n", argv[1]);
printf("vnid 0x%x\n", (unsigned int)stat.st_ino);
// printf("type %d\n", stat.type);
@@ -99,7 +99,7 @@ static int bus_find_device_recurse(int *n, char *base_path, int max_path_len, in
dirent->d_name[dirent->d_reclen] = '\0';
strlcat(base_path, dirent->d_name, max_path_len);
err = sys_read_stat(base_path, &stat);
err = sys_read_stat(base_path, true, &stat);
if (err < 0)
continue;
+171 -101
View File
@@ -499,14 +499,10 @@ get_vnode_from_fd(struct io_context *ioContext, int fd)
return NULL;
vnode = descriptor->vnode;
if (vnode == NULL)
goto out;
if (vnode != NULL)
inc_vnode_ref_count(vnode);
inc_vnode_ref_count(vnode);
out:
put_fd(descriptor);
return vnode;
}
@@ -562,7 +558,7 @@ entry_ref_to_vnode(fs_id fsID,vnode_id directoryID,const char *name,struct vnode
static int
vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int count)
vnode_path_to_vnode(struct vnode *vnode, char *path, bool traverseLeafLink, struct vnode **_vnode, int count)
{
int status = 0;
@@ -624,45 +620,64 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int
return ERR_VFS_PATH_NOT_FOUND;
}
// If the new node is a symbolic link, resolve it (if we've been told to do it)
if (S_ISLNK(type) && !(!traverseLeafLink && nextPath[0] == '\0')) {
char *buffer;
// it's not exactly nice style using goto in this way, but hey, it works :-/
if (count + 1 > MAX_SYM_LINKS) {
status = B_LINK_LIMIT;
goto resolve_link_error;
}
buffer = kmalloc(SYS_MAX_PATH_LEN);
if (buffer == NULL) {
status = B_NO_MEMORY;
goto resolve_link_error;
}
status = FS_CALL(nextVnode,fs_read_link)(nextVnode->mount->cookie, nextVnode->private_node, buffer, SYS_MAX_PATH_LEN);
if (status < B_OK) {
kfree(buffer);
resolve_link_error:
put_vnode(vnode);
put_vnode(nextVnode);
return status;
}
put_vnode(nextVnode);
// Check if we start from the root directory or the current
// directory ("vnode" still points to that one).
// Cut off all leading slashes if it's the root directory
path = buffer;
if (path[0] == '/') {
// we don't need the old directory anymore
put_vnode(vnode);
while (*++path == '/')
;
vnode = root_vnode;
inc_vnode_ref_count(vnode);
}
status = vnode_path_to_vnode(vnode, path, traverseLeafLink, &nextVnode, count + 1);
kfree(buffer);
if (status < B_OK) {
put_vnode(vnode);
return status;
}
}
// decrease the ref count on the old dir we just looked up into
put_vnode(vnode);
path = nextPath;
vnode = nextVnode;
// If the new node is a symbolic link, resolve it
if (S_ISLNK(type)) {
char *buffer;
if (count + 1 > MAX_SYM_LINKS) {
put_vnode(vnode);
return B_LINK_LIMIT;
}
buffer = kmalloc(SYS_MAX_PATH_LEN);
if (buffer == NULL) {
put_vnode(vnode);
return B_NO_MEMORY;
}
status = FS_CALL(vnode,fs_read_link)(vnode->mount->cookie, vnode->private_node, buffer, SYS_MAX_PATH_LEN);
if (status < B_OK) {
put_vnode(vnode);
kfree(buffer);
return status;
}
status = vnode_path_to_vnode(vnode, buffer, &nextVnode, count + 1);
put_vnode(vnode);
kfree(buffer);
if (status < B_OK)
return status;
vnode = nextVnode;
}
// see if we hit a mount point
if (vnode->covered_by) {
nextVnode = vnode->covered_by;
@@ -678,7 +693,7 @@ vnode_path_to_vnode(struct vnode *vnode, char *path, struct vnode **_vnode, int
static int
path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
path_to_vnode(char *path, bool traverseLink, struct vnode **_vnode, bool kernel)
{
struct vnode *start;
int linkCount = 0;
@@ -702,7 +717,7 @@ path_to_vnode(char *path, struct vnode **_vnode, bool kernel)
mutex_unlock(&context->io_mutex);
}
return vnode_path_to_vnode(start, path, _vnode, 0);
return vnode_path_to_vnode(start, path, traverseLink, _vnode, 0);
}
@@ -730,7 +745,7 @@ path_to_dir_vnode(char *path, struct vnode **_vnode, char *filename, bool kernel
p[1] = '\0';
}
}
return path_to_vnode(path, _vnode, kernel);
return path_to_vnode(path, true, _vnode, kernel);
}
@@ -1013,9 +1028,9 @@ vfs_get_vnode_from_fd(int fd, bool kernel, void **vnode)
int
vfs_get_vnode_from_path(const char *path, bool kernel, void **vnode)
vfs_get_vnode_from_path(const char *path, bool kernel, void **_vnode)
{
struct vnode *v;
struct vnode *vnode;
int err;
char buf[SYS_MAX_PATH_LEN+1];
@@ -1024,13 +1039,10 @@ vfs_get_vnode_from_path(const char *path, bool kernel, void **vnode)
strncpy(buf, path, SYS_MAX_PATH_LEN);
buf[SYS_MAX_PATH_LEN] = 0;
err = path_to_vnode(buf, &v, kernel);
if (err < 0)
goto err;
err = path_to_vnode(buf, true, &vnode, kernel);
if (err >= 0)
*_vnode = vnode;
*vnode = v;
err:
return err;
}
@@ -1731,7 +1743,7 @@ file_open(char *path, int omode, bool kernel)
FUNCTION(("file_open: entry. path = '%s', omode %d, kernel %d\n", path, omode, kernel));
// get the vnode matching the path
status = path_to_vnode(path, &vnode, kernel);
status = path_to_vnode(path, true, &vnode, kernel);
if (status < B_OK)
return status;
@@ -1884,7 +1896,7 @@ dir_open(char *path, bool kernel)
FUNCTION(("dir_open: path = '%s', kernel %d\n", path, kernel));
status = path_to_vnode(path, &vnode, kernel);
status = path_to_vnode(path, true, &vnode, kernel);
if (status < 0)
return status;
@@ -1979,6 +1991,27 @@ common_sync(int fd, bool kernel)
}
static int
common_read_link(char *path, char *buffer, size_t bufferSize, bool kernel)
{
struct vnode *vnode;
int status;
status = path_to_vnode(path, false, &vnode, kernel);
if (status < B_OK)
return status;
if (FS_CALL(vnode,fs_read_link) != NULL)
status = FS_CALL(vnode,fs_read_link)(vnode->mount->cookie, vnode->private_node, buffer, bufferSize);
else
status = B_BAD_VALUE;
put_vnode(vnode);
return status;
}
static int
common_symlink(char *path, const char *toPath, bool kernel)
{
@@ -1987,6 +2020,8 @@ common_symlink(char *path, const char *toPath, bool kernel)
struct vnode *vnode;
int status;
FUNCTION(("common_symlink(path = %s, toPath = %s, kernel = %d)\n", path, toPath, kernel));
status = path_to_dir_vnode(path, &vnode, name, kernel);
if (status < B_OK)
return status;
@@ -2009,7 +2044,7 @@ common_unlink(char *path, bool kernel)
struct vnode *vnode;
int status;
FUNCTION(("vfs_unlink: path '%s', kernel %d\n", path, kernel));
FUNCTION(("common_unlink: path '%s', kernel %d\n", path, kernel));
status = path_to_dir_vnode(path, &vnode, filename, kernel);
if (status < 0)
@@ -2027,18 +2062,20 @@ common_unlink(char *path, bool kernel)
static int
common_rename(char *path, char *newpath, bool kernel)
common_rename(char *path, char *newPath, bool kernel)
{
struct vnode *vnode1, *vnode2;
char filename1[SYS_MAX_NAME_LEN];
char filename2[SYS_MAX_NAME_LEN];
int status;
FUNCTION(("common_rename(path = %s, newPath = %s, kernel = %d)\n", path, newPath, kernel));
status = path_to_dir_vnode(path, &vnode1, filename1, kernel);
if (status < 0)
goto err;
status = path_to_dir_vnode(newpath, &vnode2, filename2, kernel);
status = path_to_dir_vnode(newPath, &vnode2, filename2, kernel);
if (status < 0)
goto err1;
@@ -2062,14 +2099,14 @@ err:
static int
common_write_stat(char *path, const struct stat *stat, int statMask, bool kernel)
common_write_stat(char *path, bool traverseLeafLink, const struct stat *stat, int statMask, bool kernel)
{
struct vnode *vnode;
int status;
FUNCTION(("vfs_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, statMask, kernel));
FUNCTION(("common_write_stat: path '%s', stat 0x%p, stat_mask %d, kernel %d\n", path, stat, statMask, kernel));
status = path_to_vnode(path, &vnode, kernel);
status = path_to_vnode(path, traverseLeafLink, &vnode, kernel);
if (status < 0)
return status;
@@ -2137,7 +2174,7 @@ fs_mount(char *path, const char *device, const char *fs_name, void *args, bool k
mount->covers_vnode = NULL; // this is the root mount
} else {
err = path_to_vnode(path,&covered_vnode,kernel);
err = path_to_vnode(path, true, &covered_vnode, kernel);
if (err < 0)
goto err2;
@@ -2210,7 +2247,7 @@ fs_unmount(char *path, bool kernel)
FUNCTION(("vfs_unmount: entry. path = '%s', kernel %d\n", path, kernel));
err = path_to_vnode(path, &vnode, kernel);
err = path_to_vnode(path, true, &vnode, kernel);
if (err < 0)
return ERR_VFS_PATH_NOT_FOUND;
@@ -2395,10 +2432,10 @@ set_cwd(char *path, bool kernel)
struct stat stat;
int rc;
FUNCTION(("vfs_set_cwd: path = \'%s\'\n", path));
FUNCTION(("set_cwd: path = \'%s\'\n", path));
// Get vnode for passed path, and bail if it failed
rc = path_to_vnode(path, &vnode, kernel);
rc = path_to_vnode(path, true, &vnode, kernel);
if (rc < 0)
return rc;
@@ -2580,7 +2617,20 @@ sys_create_dir(const char *path, int perms)
int
sys_symlink(const char *userPath, const char *userToPath)
sys_read_link(const char *path, char *buffer, size_t bufferSize)
{
char pathCopy[SYS_MAX_PATH_LEN + 1];
int status;
strncpy(pathCopy, path, SYS_MAX_PATH_LEN);
pathCopy[SYS_MAX_PATH_LEN] = '\0';
return common_read_link(pathCopy, buffer, bufferSize, true);
}
int
sys_create_symlink(const char *userPath, const char *userToPath)
{
char path[SYS_MAX_PATH_LEN + 1];
char toPath[SYS_MAX_PATH_LEN + 1];
@@ -2629,37 +2679,37 @@ sys_rename(const char *oldpath, const char *newpath)
int
sys_read_stat(const char *path, struct stat *stat)
sys_read_stat(const char *path, bool traverseLeafLink, struct stat *stat)
{
char buf[SYS_MAX_PATH_LEN+1];
char buffer[SYS_MAX_PATH_LEN + 1];
struct vnode *vnode;
int status;
strncpy(buf, path, SYS_MAX_PATH_LEN);
buf[SYS_MAX_PATH_LEN] = 0;
strncpy(buffer, path, SYS_MAX_PATH_LEN);
buffer[SYS_MAX_PATH_LEN] = 0;
FUNCTION(("sys_read_stat: path '%s', stat %p,\n", path, stat));
status = path_to_vnode(buf, &vnode, true);
status = path_to_vnode(buffer, traverseLeafLink, &vnode, true);
if (status < 0)
return status;
status = FS_CALL(vnode,fs_read_stat)(vnode->mount->cookie, vnode->private_node, stat);
dec_vnode_ref_count(vnode, false);
put_vnode(vnode);
return status;
}
int
sys_write_stat(const char *path, struct stat *stat, int stat_mask)
sys_write_stat(const char *path, bool traverseLeafLink, struct stat *stat, int statMask)
{
char buf[SYS_MAX_PATH_LEN+1];
char buffer[SYS_MAX_PATH_LEN + 1];
strncpy(buf, path, SYS_MAX_PATH_LEN);
buf[SYS_MAX_PATH_LEN] = 0;
strncpy(buffer, path, SYS_MAX_PATH_LEN);
buffer[SYS_MAX_PATH_LEN] = 0;
return common_write_stat(buf, stat, stat_mask, true);
return common_write_stat(buffer, traverseLeafLink, stat, statMask, true);
}
@@ -2901,15 +2951,15 @@ user_create_dir_entry_ref(dev_t device, ino_t inode, const char *uname, int perm
int
user_create_dir(const char *upath, int perms)
user_create_dir(const char *userPath, int perms)
{
char path[SYS_MAX_PATH_LEN + 1];
int status;
if (!CHECK_USER_ADDRESS(upath))
if (!CHECK_USER_ADDRESS(userPath))
return ERR_VM_BAD_USER_MEMORY;
status = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
if (status < 0)
return status;
path[SYS_MAX_PATH_LEN] = '\0';
@@ -2919,7 +2969,31 @@ user_create_dir(const char *upath, int perms)
int
user_symlink(const char *userPath, const char *userToPath)
user_read_link(const char *userPath, char *userBuffer, size_t bufferSize)
{
char path[SYS_MAX_PATH_LEN + 1];
char buffer[SYS_MAX_PATH_LEN + 1];
int status;
if (!CHECK_USER_ADDRESS(userPath)
|| !CHECK_USER_ADDRESS(userBuffer))
return B_BAD_ADDRESS;
status = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
if (status < 0)
return status;
path[SYS_MAX_PATH_LEN] = '\0';
status = common_read_link(path, buffer, bufferSize, false);
if (status < B_OK)
return status;
return user_strncpy(userBuffer, buffer, SYS_MAX_PATH_LEN);
}
int
user_create_symlink(const char *userPath, const char *userToPath)
{
char path[SYS_MAX_PATH_LEN + 1];
char toPath[SYS_MAX_PATH_LEN + 1];
@@ -2993,25 +3067,25 @@ user_rename(const char *uoldpath, const char *unewpath)
int
user_read_stat(const char *upath, struct stat *ustat)
user_read_stat(const char *userPath, bool traverseLink, struct stat *userStat)
{
char path[SYS_MAX_PATH_LEN];
char path[SYS_MAX_PATH_LEN + 1];
struct vnode *vnode = NULL;
struct stat stat;
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
if (!CHECK_USER_ADDRESS(userPath)
|| !CHECK_USER_ADDRESS(userStat))
return B_BAD_ADDRESS;
if ((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN-1);
rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
if (rc < 0)
return rc;
path[SYS_MAX_PATH_LEN-1] = 0;
path[SYS_MAX_PATH_LEN] = 0;
rc = path_to_vnode(path, &vnode, false);
FUNCTION(("user_read_stat(path = %s, traverseLeafLink = %d)\n", path, traverseLink));
rc = path_to_vnode(path, traverseLink, &vnode, false);
if (rc < 0)
return rc;
@@ -3023,35 +3097,31 @@ user_read_stat(const char *upath, struct stat *ustat)
if (rc < 0)
return rc;
rc = user_memcpy(ustat, &stat, sizeof(struct stat));
return rc;
return user_memcpy(userStat, &stat, sizeof(struct stat));
}
int
user_write_stat(const char *upath, struct stat *ustat, int stat_mask)
user_write_stat(const char *userPath, bool traverseLeafLink, struct stat *userStat, int statMask)
{
char path[SYS_MAX_PATH_LEN+1];
struct stat stat;
int rc;
if ((addr)upath >= KERNEL_BASE && (addr)upath <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
if (!CHECK_USER_ADDRESS(userPath)
|| !CHECK_USER_ADDRESS(userStat))
return B_BAD_ADDRESS;
if ((addr)ustat >= KERNEL_BASE && (addr)ustat <= KERNEL_TOP)
return ERR_VM_BAD_USER_MEMORY;
rc = user_strncpy(path, upath, SYS_MAX_PATH_LEN);
rc = user_strncpy(path, userPath, SYS_MAX_PATH_LEN);
if (rc < 0)
return rc;
path[SYS_MAX_PATH_LEN] = 0;
rc = user_memcpy(&stat, ustat, sizeof(struct stat));
rc = user_memcpy(&stat, userStat, sizeof(struct stat));
if (rc < 0)
return rc;
return common_write_stat(path, &stat, stat_mask, false);
return common_write_stat(path, traverseLeafLink, &stat, statMask, false);
}
+2 -2
View File
@@ -415,7 +415,7 @@ static int recurse_directory(const char *path, const char *match)
strlcat(newpath, "/", slen);
strlcat(newpath, dirent->d_name, slen);
if ((res = sys_read_stat(newpath, &stat)) != B_NO_ERROR) {
if ((res = sys_read_stat(newpath, true, &stat)) != B_NO_ERROR) {
kfree(newpath);
break;
}
@@ -758,7 +758,7 @@ static inline int module_traverse_dir(module_iterator *iter)
iter->cur_header = NULL;
iter->module_pos = 0;
if ((res = sys_read_stat(path, &stat)) != B_NO_ERROR)
if ((res = sys_read_stat(path, true, &stat)) != B_NO_ERROR)
return res;
if (S_ISREG(stat.st_mode)) {
+11 -5
View File
@@ -111,20 +111,26 @@ int syscall_dispatcher(unsigned long call_num, void *arg_buffer, uint64 *call_re
case SYSCALL_CREATE_DIR:
*call_ret = user_create_dir((const char *)arg0, (int)arg1);
break;
case SYSCALL_CREATE_SYMLINK:
*call_ret = user_create_symlink((const char *)arg0, (const char *)arg1);
break;
case SYSCALL_READ_LINK:
*call_ret = user_read_link((const char *)arg0, (char *)arg1, (size_t)arg2);
break;
case SYSCALL_UNLINK:
*call_ret = user_unlink((const char *)arg0);
break;
case SYSCALL_RENAME:
*call_ret = user_rename((const char *)arg0, (const char *)arg1);
break;
case SYSCALL_RSTAT:
*call_ret = user_read_stat((const char *)arg0, (struct stat *)arg1);
case SYSCALL_READ_STAT:
*call_ret = user_read_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2);
break;
case SYSCALL_FSTAT:
case SYSCALL_FD_STAT:
*call_ret = user_fstat((int)arg0, (struct stat*)arg1);
break;
case SYSCALL_WSTAT:
*call_ret = user_write_stat((const char *)arg0, (struct stat *)arg1, (int)arg2);
case SYSCALL_WRITE_STAT:
*call_ret = user_write_stat((const char *)arg0, (bool)arg1, (struct stat *)arg2, (int)arg3);
break;
case SYSCALL_SYSTEM_TIME:
*call_ret = system_time();