diff options
author | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
---|---|---|
committer | Andrew Waterman <waterman@s141.Millennium.Berkeley.EDU> | 2011-06-19 20:47:29 -0700 |
commit | 0edaecc54329048eb91ad6a45338265ef1a4569c (patch) | |
tree | b0695be27ac3b1e14aa944c4820683fcd8adefca /pk/file.c | |
parent | e63e4fbe8794c68e1ad846a36e33cba62e801b34 (diff) | |
download | pk-0edaecc54329048eb91ad6a45338265ef1a4569c.zip pk-0edaecc54329048eb91ad6a45338265ef1a4569c.tar.gz pk-0edaecc54329048eb91ad6a45338265ef1a4569c.tar.bz2 |
temporary undoing of renaming
Diffstat (limited to 'pk/file.c')
-rw-r--r-- | pk/file.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/pk/file.c b/pk/file.c new file mode 100644 index 0000000..cf370b5 --- /dev/null +++ b/pk/file.c @@ -0,0 +1,150 @@ +#include <string.h> +#include <errno.h> +#include "file.h" +#include "pk.h" +#include "frontend.h" +#include "pcr.h" + +#define MAX_FDS 32 +file_t* fds[MAX_FDS]; +#define MAX_FILES 32 +file_t files[MAX_FILES] = {[0 ... MAX_FILES-1] = {-1,{0}}}; +file_t *stdout, *stdin, *stderr; + +static void file_incref(file_t* f) +{ + atomic_add(&f->refcnt,1); +} + +void file_decref(file_t* f) +{ + if(atomic_add(&f->refcnt,-1) == 2) + { + if(f->kfd != -1) + { + frontend_syscall(SYS_close,f->kfd,0,0,0); + f->kfd = -1; + } + atomic_add(&f->refcnt,-1); // I think this could just be atomic_set(..,0) + } +} + +static file_t* file_get_free() +{ + for(int i = 0; i < MAX_FILES; i++) + { + if(atomic_read(&files[i].refcnt) == 0) + { + if(atomic_add(&files[i].refcnt,1) == 0) + { + atomic_add(&files[i].refcnt,1); + return &files[i]; + } + file_decref(&files[i]); + } + } + return NULL; +} + +static int fd_get_free() +{ + for(int i = 0; i < MAX_FDS; i++) + if(fds[i] == NULL) + return i; + return -1; +} + +int file_dup(file_t* f) +{ + int fd = fd_get_free(); + if(fd == -1) + return -1; + file_incref(f); + fds[fd] = f; + return fd; +} + +void file_init() +{ + stdin = file_get_free(); + stdout = file_get_free(); + stderr = file_get_free(); + + stdin->kfd = 0; + stdout->kfd = 1; + stderr->kfd = 2; + + // create user FDs 0, 1, and 2 + file_dup(stdin); + file_dup(stdout); + file_dup(stderr); +} + +file_t* file_get(int fd) +{ + return fd < 0 || fd >= MAX_FDS ? NULL : fds[fd]; +} + +sysret_t file_open(const char* fn, size_t len, int flags, int mode) +{ + file_t* f = file_get_free(); + if(!f) + return (sysret_t){-1,ENOMEM}; + + sysret_t ret = frontend_syscall(SYS_open,(long)fn,len,flags,mode); + if(ret.result != -1) + { + f->kfd = ret.result; + ret.result = (long)f; + } + else + file_decref(f); + + return ret; +} + +int fd_close(int fd) +{ + file_t* f = file_get(fd); + if(!f) + return -1; + fds[fd] = NULL; + file_decref(f); + return 0; +} + +sysret_t file_read(file_t* f, char* buf, size_t size) +{ + return frontend_syscall(SYS_read,f->kfd,(long)buf,size,0); +} + +sysret_t file_pread(file_t* f, char* buf, size_t size, off_t offset) +{ + return frontend_syscall(SYS_pread,f->kfd,(long)buf,size,offset); +} + +sysret_t file_write(file_t* f, const char* buf, size_t size) +{ + if(f->kfd == 1 || f->kfd == 2) + { + for(size_t i = 0; i < size; i++) + mtpcr(PCR_CONSOLE,buf[i]); + } + + return frontend_syscall(SYS_write,f->kfd,(long)buf,size,0); +} + +sysret_t file_pwrite(file_t* f, const char* buf, size_t size, off_t offset) +{ + return frontend_syscall(SYS_pwrite,f->kfd,(long)buf,size,offset); +} + +sysret_t file_stat(file_t* f, struct stat* s) +{ + return frontend_syscall(SYS_fstat,f->kfd,(long)s,0,0); +} + +sysret_t file_lseek(file_t* f, size_t ptr, int dir) +{ + return frontend_syscall(SYS_lseek,f->kfd,ptr,dir,0); +} |