aboutsummaryrefslogtreecommitdiff
path: root/pk/file.c
diff options
context:
space:
mode:
authorAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-06-19 20:47:29 -0700
committerAndrew Waterman <waterman@s141.Millennium.Berkeley.EDU>2011-06-19 20:47:29 -0700
commit0edaecc54329048eb91ad6a45338265ef1a4569c (patch)
treeb0695be27ac3b1e14aa944c4820683fcd8adefca /pk/file.c
parente63e4fbe8794c68e1ad846a36e33cba62e801b34 (diff)
downloadpk-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.c150
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);
+}