Browse Source

Support linkat, unlinkat, mkdirat syscalls

Also, old-style syscalls e.g. open are now implemented with e.g. openat.
pull/9/head
Andrew Waterman 11 years ago
parent
commit
0a81fd3a93
  1. 33
      pk/file.c
  2. 4
      pk/frontend.c
  3. 2
      pk/frontend.h
  4. 2
      pk/init.c
  5. 139
      pk/syscall.c
  6. 5
      pk/syscall.h

33
pk/file.c

@ -27,7 +27,7 @@ void file_decref(file_t* f)
mb();
atomic_set(&f->refcnt, 0);
frontend_syscall(SYS_close, kfd, 0, 0, 0, 0);
frontend_syscall(SYS_close, kfd, 0, 0, 0, 0, 0, 0);
}
}
@ -86,22 +86,7 @@ file_t* file_get(int fd)
file_t* file_open(const char* fn, int flags, int mode)
{
file_t* f = file_get_free();
if (f == NULL)
return ERR_PTR(-ENOMEM);
size_t fn_size = strlen(fn)+1;
long ret = frontend_syscall(SYS_open, (long)fn, fn_size, flags, mode, 0);
if (ret >= 0)
{
f->kfd = ret;
return f;
}
else
{
file_decref(f);
return ERR_PTR(ret);
}
return file_openat(AT_FDCWD, fn, flags, mode);
}
file_t* file_openat(int dirfd, const char* fn, int flags, int mode)
@ -111,7 +96,7 @@ file_t* file_openat(int dirfd, const char* fn, int flags, int mode)
return ERR_PTR(-ENOMEM);
size_t fn_size = strlen(fn)+1;
long ret = frontend_syscall(SYS_openat, dirfd, (long)fn, fn_size, flags, mode);
long ret = frontend_syscall(SYS_openat, dirfd, (long)fn, fn_size, flags, mode, 0, 0);
if (ret >= 0)
{
f->kfd = ret;
@ -140,34 +125,34 @@ int fd_close(int fd)
ssize_t file_read(file_t* f, void* buf, size_t size)
{
populate_mapping(buf, size, PROT_WRITE);
return frontend_syscall(SYS_read, f->kfd, (uintptr_t)buf, size, 0, 0);
return frontend_syscall(SYS_read, f->kfd, (uintptr_t)buf, size, 0, 0, 0, 0);
}
ssize_t file_pread(file_t* f, void* buf, size_t size, off_t offset)
{
populate_mapping(buf, size, PROT_WRITE);
return frontend_syscall(SYS_pread, f->kfd, (uintptr_t)buf, size, offset, 0);
return frontend_syscall(SYS_pread, f->kfd, (uintptr_t)buf, size, offset, 0, 0, 0);
}
ssize_t file_write(file_t* f, const void* buf, size_t size)
{
populate_mapping(buf, size, PROT_READ);
return frontend_syscall(SYS_write, f->kfd, (uintptr_t)buf, size, 0, 0);
return frontend_syscall(SYS_write, f->kfd, (uintptr_t)buf, size, 0, 0, 0, 0);
}
ssize_t file_pwrite(file_t* f, const void* buf, size_t size, off_t offset)
{
populate_mapping(buf, size, PROT_READ);
return frontend_syscall(SYS_pwrite, f->kfd, (uintptr_t)buf, size, offset, 0);
return frontend_syscall(SYS_pwrite, f->kfd, (uintptr_t)buf, size, offset, 0, 0, 0);
}
int file_stat(file_t* f, struct stat* s)
{
populate_mapping(s, sizeof(*s), PROT_WRITE);
return frontend_syscall(SYS_fstat, f->kfd, (uintptr_t)s, 0, 0, 0);
return frontend_syscall(SYS_fstat, f->kfd, (uintptr_t)s, 0, 0, 0, 0, 0);
}
ssize_t file_lseek(file_t* f, size_t ptr, int dir)
{
return frontend_syscall(SYS_lseek, f->kfd, ptr, dir, 0, 0);
return frontend_syscall(SYS_lseek, f->kfd, ptr, dir, 0, 0, 0, 0);
}

4
pk/frontend.c

@ -5,7 +5,7 @@
#include "frontend.h"
#include <stdint.h>
long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4)
long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4, long a5, long a6)
{
static volatile uint64_t magic_mem[8];
@ -18,6 +18,8 @@ long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4)
magic_mem[3] = a2;
magic_mem[4] = a3;
magic_mem[5] = a4;
magic_mem[6] = a5;
magic_mem[7] = a6;
mb();

2
pk/frontend.h

@ -3,6 +3,6 @@
#ifndef _RISCV_FRONTEND_H
#define _RISCV_FRONTEND_H
long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4);
long frontend_syscall(long n, long a0, long a1, long a2, long a3, long a4, long a5, long a6);
#endif

2
pk/init.c

@ -59,7 +59,7 @@ struct mainvars {
static struct mainvars* handle_args(struct mainvars* args)
{
long r = frontend_syscall(SYS_getmainvars, (uintptr_t)args, sizeof(*args), 0, 0, 0);
long r = frontend_syscall(SYS_getmainvars, (uintptr_t)args, sizeof(*args), 0, 0, 0, 0, 0);
kassert(r == 0);
// argv[0] is the proxy kernel itself. skip it and any flags.

139
pk/syscall.c

@ -7,7 +7,6 @@
#include "vm.h"
#include <string.h>
#include <errno.h>
//#include <fcntl.h>
typedef long (*syscall_t)(long, long, long, long, long, long, long);
@ -51,7 +50,7 @@ void sys_exit(int code)
}
}
frontend_syscall(SYS_exit, code, 0, 0, 0, 0);
frontend_syscall(SYS_exit, code, 0, 0, 0, 0, 0, 0);
clear_csr(status, SR_EI);
while (1);
}
@ -98,40 +97,40 @@ ssize_t sys_write(int fd, const char* buf, size_t n)
return r;
}
int sys_open(const char* name, int flags, int mode)
static int at_kfd(int dirfd)
{
file_t* file = file_open(name, flags, mode);
if (IS_ERR_VALUE(file))
return PTR_ERR(file);
int fd = file_dup(file);
if (fd < 0)
return -ENOMEM;
return fd;
if (dirfd == AT_FDCWD)
return AT_FDCWD;
file_t* dir = file_get(dirfd);
if (dir == NULL)
return -1;
return dir->kfd;
}
int sys_openat(int dirfd, const char* name, int flags, int mode)
{
if(name[0] == '/'){
return sys_open(name, flags, mode);
}
file_t* dir = file_get(dirfd);
if(dir)
{
file_t* file = file_openat(dir->kfd, name, flags, mode);
int kfd = at_kfd(dirfd);
if (kfd != -1) {
file_t* file = file_openat(kfd, name, flags, mode);
if (IS_ERR_VALUE(file))
return PTR_ERR(file);
int fd = file_dup(file);
if (fd < 0)
if (fd < 0) {
file_decref(file);
return -ENOMEM;
}
return fd;
}
}
return -EBADF;
}
int sys_open(const char* name, int flags, int mode)
{
return sys_openat(AT_FDCWD, name, flags, mode);
}
int sys_close(int fd)
{
int ret = fd_close(fd);
@ -161,7 +160,7 @@ int sys_fcntl(int fd, int cmd, int arg)
if (f)
{
r = frontend_syscall(SYS_fcntl, f->kfd, cmd, arg, 0, 0);
r = frontend_syscall(SYS_fcntl, f->kfd, cmd, arg, 0, 0, 0, 0);
file_decref(f);
}
@ -196,76 +195,97 @@ ssize_t sys_lseek(int fd, size_t ptr, int dir)
return r;
}
long sys_stat(const char* name, void* st)
{
size_t name_size = strlen(name)+1;
populate_mapping(st, sizeof(struct stat), PROT_WRITE);
return frontend_syscall(SYS_stat, (uintptr_t)name, name_size, (uintptr_t)st, 0, 0);
}
long sys_lstat(const char* name, void* st)
{
size_t name_size = strlen(name)+1;
populate_mapping(st, sizeof(struct stat), PROT_WRITE);
return frontend_syscall(SYS_lstat, (uintptr_t)name, name_size, (uintptr_t)st, 0, 0);
return frontend_syscall(SYS_lstat, (uintptr_t)name, name_size, (uintptr_t)st, 0, 0, 0, 0);
}
long sys_fstatat(int dirfd, const char* name, void* st, int flags)
{
if(name[0] == '/'){
return sys_stat(name, st);
}
file_t* dir = file_get(dirfd);
if(dir)
{
int kfd = at_kfd(dirfd);
if (kfd != -1) {
size_t name_size = strlen(name)+1;
populate_mapping(st, sizeof(struct stat), PROT_WRITE);
return frontend_syscall(SYS_fstatat, dir->kfd, (uintptr_t)name, name_size, (uintptr_t)st, flags);
return frontend_syscall(SYS_fstatat, kfd, (uintptr_t)name, name_size, (uintptr_t)st, flags, 0, 0);
}
return -EBADF;
}
int sys_access(const char *name, int mode){
size_t name_size = strlen(name)+1;
return frontend_syscall(SYS_access, (uintptr_t)name, name_size, mode, 0, 0);
long sys_stat(const char* name, void* st)
{
return sys_fstatat(AT_FDCWD, name, st, 0);
}
int sys_faccessat(int dirfd, const char *name, int mode, int flags){
if(name[0] == '/'){
return sys_access(name, mode);
}
file_t* dir = file_get(dirfd);
if(dir)
{
long sys_faccessat(int dirfd, const char *name, int mode)
{
int kfd = at_kfd(dirfd);
if (kfd != -1) {
size_t name_size = strlen(name)+1;
return frontend_syscall(SYS_access, dir->kfd, (uintptr_t)name, name_size, mode, flags);
return frontend_syscall(SYS_faccessat, kfd, (uintptr_t)name, name_size, mode, 0, 0, 0);
}
return -EBADF;
}
long sys_access(const char *name, int mode)
{
return sys_faccessat(AT_FDCWD, name, mode);
}
long sys_linkat(int old_dirfd, const char* old_name, int new_dirfd, const char* new_name, int flags)
{
int old_kfd = at_kfd(old_dirfd);
int new_kfd = at_kfd(new_dirfd);
if (old_kfd != -1 && new_kfd != -1) {
size_t old_size = strlen(old_name)+1;
size_t new_size = strlen(new_name)+1;
return frontend_syscall(SYS_linkat, old_kfd, (uintptr_t)old_name, old_size,
new_kfd, (uintptr_t)new_name, new_size,
flags);
}
return -EBADF;
}
long sys_link(const char* old_name, const char* new_name)
{
size_t old_size = strlen(old_name)+1;
size_t new_size = strlen(new_name)+1;
return frontend_syscall(SYS_link, (uintptr_t)old_name, old_size,
(uintptr_t)new_name, new_size, 0);
return sys_linkat(AT_FDCWD, old_name, AT_FDCWD, new_name, 0);
}
long sys_unlink(const char* name, size_t len)
long sys_unlinkat(int dirfd, const char* name, int flags)
{
size_t name_size = strlen(name)+1;
return frontend_syscall(SYS_unlink, (uintptr_t)name, name_size, 0, 0, 0);
int kfd = at_kfd(dirfd);
if (kfd != -1) {
size_t name_size = strlen(name)+1;
return frontend_syscall(SYS_unlinkat, kfd, (uintptr_t)name, name_size, flags, 0, 0, 0);
}
return -EBADF;
}
long sys_unlink(const char* name)
{
return sys_unlinkat(AT_FDCWD, name, 0);
}
long sys_mkdirat(int dirfd, const char* name, int mode)
{
int kfd = at_kfd(dirfd);
if (kfd != -1) {
size_t name_size = strlen(name)+1;
return frontend_syscall(SYS_mkdirat, kfd, (uintptr_t)name, name_size, mode, 0, 0, 0);
}
return -EBADF;
}
long sys_mkdir(const char* name, int mode)
{
size_t name_size = strlen(name)+1;
return frontend_syscall(SYS_mkdir, (uintptr_t)name, name_size, mode, 0, 0);
return sys_mkdirat(AT_FDCWD, name, mode);
}
long sys_getcwd(const char* buf, size_t size)
{
populate_mapping(buf, size, PROT_WRITE);
return frontend_syscall(SYS_getcwd, (uintptr_t)buf, size, 0, 0, 0);
return frontend_syscall(SYS_getcwd, (uintptr_t)buf, size, 0, 0, 0, 0, 0);
}
size_t sys_brk(size_t pos)
@ -413,6 +433,9 @@ long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long n)
[SYS_link] = sys_link,
[SYS_unlink] = sys_unlink,
[SYS_mkdir] = sys_mkdir,
[SYS_linkat] = sys_linkat,
[SYS_unlinkat] = sys_unlinkat,
[SYS_mkdirat] = sys_mkdirat,
[SYS_getcwd] = sys_getcwd,
[SYS_brk] = sys_brk,
[SYS_uname] = sys_uname,

5
pk/syscall.h

@ -17,6 +17,9 @@
#define SYS_link 1025
#define SYS_unlink 1026
#define SYS_mkdir 1030
#define SYS_linkat 37
#define SYS_unlinkat 35
#define SYS_mkdirat 34
#define SYS_chdir 49
#define SYS_getcwd 17
#define SYS_stat 1038
@ -52,6 +55,8 @@
#define ERR_PTR(x) ((void*)(long)(x))
#define PTR_ERR(x) ((long)(x))
#define AT_FDCWD -100
void sys_exit(int code) __attribute__((noreturn));
long do_syscall(long a0, long a1, long a2, long a3, long a4, long a5, long n);

Loading…
Cancel
Save