summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex AUVOLAT <alexis211@gmail.com>2012-05-17 13:30:09 +0200
committerAlex AUVOLAT <alexis211@gmail.com>2012-05-17 13:30:09 +0200
commit7c9a48b4e6d66cf4f62e7bad9e22ab06923e47ef (patch)
treedf44a926f105c913c77525d35441d20a632f1440
parentc6d35a5f4fdda6ae2e98498f19a4adaee6d95692 (diff)
downloadTCE-7c9a48b4e6d66cf4f62e7bad9e22ab06923e47ef.tar.gz
TCE-7c9a48b4e6d66cf4f62e7bad9e22ab06923e47ef.zip
Beginning of a VFS implemented. C++ is great.
-rw-r--r--doc/syscalls.txt33
-rw-r--r--doc/vfs.txt3
-rw-r--r--src/common/include/string.h2
-rw-r--r--src/common/include/tce/syscalls.h27
-rw-r--r--src/common/include/tce/vfs.h42
-rw-r--r--src/common/string.c4
-rw-r--r--src/kernel/Makefile5
-rw-r--r--src/kernel/config.h4
-rw-r--r--src/kernel/core/kmain.cpp3
-rw-r--r--src/kernel/lib/earray.cpp6
-rw-r--r--src/kernel/lib/earray.h2
-rw-r--r--src/kernel/mem/_dlmalloc.h2
-rw-r--r--src/kernel/mem/mem.h4
-rw-r--r--src/kernel/task/syscall.cpp71
-rw-r--r--src/kernel/task/task.cpp19
-rw-r--r--src/kernel/task/task.h8
-rw-r--r--src/kernel/vfs/node.cpp122
-rw-r--r--src/kernel/vfs/node.h41
-rw-r--r--src/kernel/vfs/vdir.cpp55
-rw-r--r--src/kernel/vfs/vdir.h32
-rw-r--r--src/user/lib/include/tce/syscall.h11
-rw-r--r--src/user/lib/std/stdio.c1
-rw-r--r--src/user/lib/tce/syscall.c41
-rw-r--r--src/user/test/main.c65
24 files changed, 559 insertions, 44 deletions
diff --git a/doc/syscalls.txt b/doc/syscalls.txt
index 952b95e..39982c0 100644
--- a/doc/syscalls.txt
+++ b/doc/syscalls.txt
@@ -15,11 +15,36 @@ id=eax Name Parameters Description
7 irq_wait ebx: irq number Waits for an IRQ (requires privilege PL_DRIVER)
8 proc_priv none Returns current process privilege level
- 9 sbrk ebx: size Allocates some memory
- 10 brk ebx: new_end Allocates/frees some memory
+ 10 sbrk ebx: size Allocates some memory
+ 11 brk ebx: new_end Allocates/frees some memory
- 11 mmap (see linux specs) not implemented
- 12 munmap (see linux specs) not implemented
+ 12 mmap (see linux specs) not implemented
+ 13 munmap (see linux specs) not implemented
+
+ 20 open ebx: char* filename open a file, returns a descriptor
+ ecx: mode
+ 21 open_relative ebx: root open a file, returns a descriptor
+ ecx: char* filename
+ edx: mode
+ 22 stat ebx: char* filename get file info
+ ecx: struct* info
+ 23 stat_relative ebx: root get file info
+ ecx: char* filename
+ edx: struct* info
+ 24 statf ebx: file descriptor get file info
+ ecx: struct* info
+ 25 close ebx: file descriptor close file
+ 26 read ebx: file descriptor read from file
+ ecx: offset
+ edx: length
+ esi: pointer to data
+ 27 write ebx: file descriptor write to file
+ ecx: offset
+ edx: length
+ esi: pointer to data
+ 28 link ebx: char* from symlink/hardlink/mount/...
+ ecx: char* to
+ edx: mode
If a processes wishes to exit with an error code, it HAS to use process_exit. thread_exit will do nothing.
diff --git a/doc/vfs.txt b/doc/vfs.txt
index 255ddb0..5a6a0b2 100644
--- a/doc/vfs.txt
+++ b/doc/vfs.txt
@@ -8,11 +8,13 @@ File are objects that implement an abstract file class in the kernel. Its method
- int stat(struct file_info *info)
- file* get_child(char* name)
- int add_child(char* name, file *child)
+- int get_size()
The following syscall interface is given to the process (fd_t is a file descriptor, an int) :
- fd_t open(char* filename, int mode)
- fd_t open_relative(fd_t root, char* filename, int mode)
- int stat(char* filename, struct file_info *info)
+- int stat_relative(fd_t root, char* filename, struct file_info *info)
- int statf(fd_t file, struct file_info *info)
- void close(fd_t file)
- int read(fd_t file, size_t offset, size_t len, char *buffer)
@@ -33,6 +35,7 @@ File open modes flags :
- FM_APPEND append data
- FM_TRUNC truncate existing file
- FM_CREATE create file if it doesn't exist
+- FM_DELETE delete the file - incompatible with everything else
note : if mode contains neither FM_READ nor FM_WRITE, then the file will be created/truncated according to the flags given,
but will not be actually oppenned, so the return value of open will be 0.
diff --git a/src/common/include/string.h b/src/common/include/string.h
index e6aa86e..19e87c1 100644
--- a/src/common/include/string.h
+++ b/src/common/include/string.h
@@ -10,7 +10,7 @@ extern "C" {
int strlen(const char *str);
char *strcpy(char *dest, const char *src);
-// char *strdup(const char *src); // uses malloc, that's bad
+char *strdup(const char *src); // uses malloc, that's bad
char *strchr(const char *str, char c);
char *strcat(char *dest, const char *src);
int strcmp(const char *s1, const char *s2);
diff --git a/src/common/include/tce/syscalls.h b/src/common/include/tce/syscalls.h
index 3b5b68f..6c67523 100644
--- a/src/common/include/tce/syscalls.h
+++ b/src/common/include/tce/syscalls.h
@@ -9,11 +9,30 @@
#define SC_THREAD_NEW 6
#define SC_IRQ_WAIT 7
#define SC_PROC_PRIV 8
-#define SC_SBRK 9
-#define SC_BRK 10
+#define SC_SBRK 10
+#define SC_BRK 11
// NOT YET IMPLEMENTED
-#define SC_MMAP 11
-#define SC_MUNMAP 12
+#define SC_MMAP 12
+#define SC_MUNMAP 13
+
+#define SC_OPEN 20
+#define SC_OPEN_RELATIVE 21
+#define SC_STAT 22
+#define SC_STAT_RELATIVE 23
+#define SC_STATF 24
+#define SC_CLOSE 25
+#define SC_READ 26
+#define SC_WRITE 27
+#define SC_LINK 28
+
+
+// ERRORS
+#define E_NOT_IMPLEMENTED -1
+#define E_NOT_FOUND -2
+#define E_INVALID_FD -3
+#define E_TOO_SHORT -4 // not enough space for data to be copied to
+#define E_INVALID_RANGE -5
+#define E_INVALID -6 // anything went wrong - invalid parameter, usually
#endif
diff --git a/src/common/include/tce/vfs.h b/src/common/include/tce/vfs.h
new file mode 100644
index 0000000..20ea03b
--- /dev/null
+++ b/src/common/include/tce/vfs.h
@@ -0,0 +1,42 @@
+#ifndef DEF_TCE_VFS_H
+#define DEF_TCE_VFS_H
+
+#include <types.h>
+
+typedef size_t FILE;
+
+typedef struct _file_info {
+ uint32_t type;
+ uint32_t dev_type;
+ uint32_t mode;
+ uint32_t uid, gid;
+ size_t size;
+} file_info;
+
+// file open flags
+#define FM_READ 0x00000001
+#define FM_WRITE 0x00000002
+#define FM_APPEND 0x00000004
+#define FM_TRUNC 0x00000008
+#define FM_CREATE 0x00000010
+#define FM_DELETE 0x00000020
+
+// link modes
+#define LM_SYMLINK 1
+#define LM_HARDLINK 2
+#define LM_MOUNT 3
+#define LM_OUTPUT_TO 4
+
+// file type flags
+#define FT_FILE 0x00000001
+#define FT_DIR 0x00000002
+#define FT_SYMLINK 0x00000004
+#define FT_DEV 0x00000008
+#define FT_TERMINAL 0x00000010
+
+// device types
+#define DT_BLOCK 1
+#define DT_KEYBOARD 2
+#define DT_DISPLAY 3
+
+#endif
diff --git a/src/common/string.c b/src/common/string.c
index 120fd5d..3825e47 100644
--- a/src/common/string.c
+++ b/src/common/string.c
@@ -20,12 +20,12 @@ char *strcpy(char *dest, const char *src) {
return (char*)src;
}
-/*char *strdup(const char *src) {
+char *strdup(const char *src) {
char* ret = malloc(strlen(src) + 1);
if (ret == NULL) return ret;
strcpy(ret, src);
return ret;
-}*/
+}
char *strcat(char *dest, const char *src) {
char *dest2 = dest;
diff --git a/src/kernel/Makefile b/src/kernel/Makefile
index 2a18bc8..0537388 100644
--- a/src/kernel/Makefile
+++ b/src/kernel/Makefile
@@ -2,9 +2,10 @@ Out = kernel.elf
Obj = core/loader_.o core/kmain.o core/sys.o \
core/monitor.o task/timer.o \
task/idt.o task/idt_.o task/task.o task/task_.o task/syscall.o task/sched.o \
- lib/bitset.o lib/std.o lib/cpp.o lib/earray.o \
+ lib/bitset.o lib/std.o lib/cpp.o \
mem/mem.o mem/paging.o mem/gdt.o mem/_dlmalloc.o mem/seg.o \
- linker/elf.o
+ linker/elf.o \
+ vfs/node.o vfs/vdir.o
ExtObj = $(SrcPath)/common/_common.o
diff --git a/src/kernel/config.h b/src/kernel/config.h
index 0fb4697..ffb56d2 100644
--- a/src/kernel/config.h
+++ b/src/kernel/config.h
@@ -2,8 +2,8 @@
#define DEF_CONFIG_H
#define K_OS_NAME "T/CE"
-#define K_OS_VER "0.0.5"
-#define K_OS_CODENAME "CPLUSPLUS==\\o/"
+#define K_OS_VER "0.1.0"
+#define K_OS_CODENAME "Mind Your VFS"
#endif
diff --git a/src/kernel/core/kmain.cpp b/src/kernel/core/kmain.cpp
index 8b77bcf..eb2c3ec 100644
--- a/src/kernel/core/kmain.cpp
+++ b/src/kernel/core/kmain.cpp
@@ -11,6 +11,7 @@
#include <mem/paging.h>
#include <mem/mem.h>
#include <linker/elf.h>
+#include <vfs/node.h>
/* The kernel's main procedure. This function is called in loader_.asm.
This function calls the initializer functions for all system parts.
@@ -55,6 +56,8 @@ extern "C" void kmain(multiboot_info_t* mbd, int32_t magic) {
//kheap_init();
timer_init(30);
tasking_init();
+
+ vfs_setup();
monitor_write("\nLoading modules :\n");
for (i = 0; i < mbd->mods_count; i++) {
diff --git a/src/kernel/lib/earray.cpp b/src/kernel/lib/earray.cpp
index 5760822..3a41f18 100644
--- a/src/kernel/lib/earray.cpp
+++ b/src/kernel/lib/earray.cpp
@@ -1,5 +1,3 @@
-#include "earray.h"
-
#include <mem/mem.h>
#include <core/sys.h>
#include <lib/cpp.h>
@@ -101,7 +99,7 @@ T *earray<T>::at(int num) {
mutex_unlock(&mutex);
return 0;
}
- void* ret = data[i][j];
+ T* ret = data[i][j];
mutex_unlock(&mutex);
return ret;
}
@@ -145,7 +143,7 @@ void earray<T>::set(int num, T* ptr) {
}
}
} else {
- if (data[a] = 0) {
+ if (data[a] == 0) {
data[a] = (T**)kmalloc(vect_len * sizeof(T*));
for (i = 0; i < vect_len; i++) data[a][i] = 0;
}
diff --git a/src/kernel/lib/earray.h b/src/kernel/lib/earray.h
index d3d7a9b..9a43612 100644
--- a/src/kernel/lib/earray.h
+++ b/src/kernel/lib/earray.h
@@ -32,6 +32,6 @@ struct earray {
int count() { return elements; }
};
-
+#include <earray.cpp>
#endif
diff --git a/src/kernel/mem/_dlmalloc.h b/src/kernel/mem/_dlmalloc.h
index a80273c..23682be 100644
--- a/src/kernel/mem/_dlmalloc.h
+++ b/src/kernel/mem/_dlmalloc.h
@@ -12,7 +12,7 @@
#define LACKS_SYS_PARAM_H
#define LACKS_STDLIB_H
-#define USE_DL_PREFIX
+// #define USE_DL_PREFIX
#define USE_LOCKS 2
diff --git a/src/kernel/mem/mem.h b/src/kernel/mem/mem.h
index 085d9ce..4201983 100644
--- a/src/kernel/mem/mem.h
+++ b/src/kernel/mem/mem.h
@@ -14,8 +14,8 @@ void kfree_page(void* page);
extern "C" void* ksbrk(size_t size);
extern "C" void kbrk(void* ptr);
-#define kmalloc dlmalloc
-#define kfree dlfree
+#define kmalloc malloc
+#define kfree free
extern bool _no_more_ksbrk;
extern size_t mem_placementAddr;
diff --git a/src/kernel/task/syscall.cpp b/src/kernel/task/syscall.cpp
index 678677d..797c5db 100644
--- a/src/kernel/task/syscall.cpp
+++ b/src/kernel/task/syscall.cpp
@@ -3,6 +3,7 @@
#include "timer.h"
#include <core/monitor.h>
#include <core/sys.h>
+#include <vfs/node.h>
#define CALL0(name, scname) static void scname(registers* r) { r->eax = name(); }
#define CALL1(name, scname) static void scname(registers* r) { \
@@ -11,6 +12,8 @@
r->eax = name(r->ebx, r->ecx); }
#define CALL3(name, scname) static void scname(registers* r) { \
r->eax = name(r->ebx, r->ecx, r->edx); }
+#define CALL4(name, scname) static void scname(registers* r) { \
+ r->eax = name(r->ebx, r->ecx, r->edx, r->esi); }
#define CALL0V(name, scname) static void scname(registers* r) { name(); }
#define CALL1V(name, scname) static void scname(registers* r) { name(r->ebx); }
#define CALL2V(name, scname) static void scname(registers* r) { name(r->ebx, r->ecx); }
@@ -26,29 +29,83 @@ CALL0(proc_priv, proc_priv_sc);
CALL1(process_sbrk, proc_sbrk_sc);
CALL1V(process_brk, proc_brk_sc);
+CALL1V(close, close_sc);
+
static void printk_sc(registers *r) {
monitor_write((char*)r->ebx);
}
static void thread_new_sc(registers* r) {
cli();
- new thread(current_thread->process, (thread_entry)r->ebx, (void*)r->ecx, (void*)r->edx);
+ new thread(current_process, (thread_entry)r->ebx, (void*)r->ecx, (void*)r->edx);
sti();
}
+static void open_sc(registers *r) {
+ r->eax = open((char*)r->ebx, r->ecx);
+}
+
+static void open_relative_sc(registers *r) {
+ r->eax = open_relative(r->ebx, (char*)r->ecx, r->edx);
+}
+
+static void stat_sc(registers *r) {
+ r->eax = stat((char*)r->ebx, (file_info*)r->ecx);
+}
+
+static void stat_relative_sc(registers *r) {
+ r->eax = stat_relative(r->ebx, (char*)r->ecx, (file_info*)r->edx);
+}
+
+static void statf_sc(registers *r) {
+ r->eax = statf(r->ebx, (file_info*)r->ecx);
+}
+
+static void read_sc(registers *r) {
+ r->eax = read(r->ebx, r->ecx, r->edx, (char*)r->esi);
+}
+
+static void write_sc(registers *r) {
+ r->eax = write(r->ebx, r->ecx, r->edx, (char*)r->esi);
+}
+
+static void link_sc(registers *r) {
+ r->eax = link((char*)r->ebx, (char*)r->ecx, r->edx);
+}
+
+
int_callback syscalls[NUMBER_OF_SYSCALLS] = { // This must correspond to common/include/tce/syscalls.h
- 0,
- thread_exit_sc, //0
+ 0, // 0
+ thread_exit_sc,
schedule_sc,
thread_sleep_sc,
process_exit_sc,
- printk_sc,
- thread_new_sc, //5
+ printk_sc, //5
+ thread_new_sc,
irq_wait_sc,
proc_priv_sc,
- proc_sbrk_sc,
+ 0,
+ proc_sbrk_sc, //10
proc_brk_sc,
- 0 };
+ 0,
+ 0,
+ 0,
+ 0, //15
+ 0,
+ 0,
+ 0,
+ 0,
+ open_sc, //20
+ open_relative_sc,
+ stat_sc,
+ stat_relative_sc,
+ statf_sc,
+ close_sc, //25
+ read_sc,
+ write_sc,
+ link_sc,
+ 0
+ };
/* Called in idt_.asm on a system call (interrupt 64).
diff --git a/src/kernel/task/task.cpp b/src/kernel/task/task.cpp
index 92820f9..3998bfe 100644
--- a/src/kernel/task/task.cpp
+++ b/src/kernel/task/task.cpp
@@ -20,7 +20,7 @@ extern "C" uint32_t read_eip();
extern "C" void task_idle(void*);
static uint32_t nextpid = 1;
-process *processes = 0, *kernel_process;
+process *processes = 0, *kernel_process = 0, *current_process = 0;
thread *current_thread = 0, *idle_thread = 0;
uint32_t tasking_tmpStack[KSTACKSIZE];
@@ -78,8 +78,9 @@ void schedule() {
current_thread = sched_dequeue();
ASSERT(current_thread != 0);
+ current_process = current_thread->process;
- pagedir_switch(current_thread->process->pagedir);
+ pagedir_switch(current_process->pagedir);
gdt_setKernelStack(((uint32_t)current_thread->kernelStack_addr) + current_thread->kernelStack_size);
@@ -135,8 +136,8 @@ void thread::wakeUp() {
/* Returns the privilege level of the current process. */
int proc_priv() {
- if (current_thread == 0 || current_thread->process == 0) return PL_UNKNOWN;
- return current_thread->process->privilege;
+ if (current_thread == 0 || current_process == 0) return PL_UNKNOWN;
+ return current_process->privilege;
}
/* For internal use only. Called by thread_exit_stackJmp on a stack that will not be deleted.
@@ -272,7 +273,7 @@ thread::thread(class process *proc, thread_entry entry_point, void *data, void *
}
/* Creates a new process. Creates a struct process and fills it up. */
-process::process(process* _parent, uint32_t _uid, uint32_t _privilege) {
+process::process(process* _parent, uint32_t _uid, uint32_t _privilege) : fd(12, 64) {
pid = (nextpid++);
uid = _uid;
thread_count = 0;
@@ -284,6 +285,8 @@ process::process(process* _parent, uint32_t _uid, uint32_t _privilege) {
data = 0;
dataseg = 0;
+ fd.add((node*)-1); // descriptor #0 must not be used
+
stack = 0;
if (privilege >= PL_USER) { //We are running in user mode
size_t stacksBottom = K_HIGHHALF_ADDR - 0x01000000;
@@ -338,7 +341,7 @@ static void process_delete(process *pr) {
}
size_t process_sbrk(size_t size) {
- process *p = current_thread->process;
+ process *p = current_process;
if (p->data == 0) return -1;
ASSERT(p->data < K_HIGHHALF_ADDR);
if (p->data + size >= K_HIGHHALF_ADDR) return -1;
@@ -378,9 +381,7 @@ size_t process_sbrk(size_t size) {
}
void process_brk(size_t ptr) {
- process *p = current_thread->process;
-
ASSERT(ptr < K_HIGHHALF_ADDR);
- process_sbrk(ptr - p->data);
+ process_sbrk(ptr - current_process->data);
}
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index 301f8be..1c32657 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -5,6 +5,8 @@
#include <mem/paging.h>
#include "idt.h"
+#include <lib/earray.h>
+
#define TS_RUNNING 0
#define TS_WAKEWAIT 2 //Waiting to be waked up by something precise (thread currently blocked)
@@ -21,6 +23,7 @@
typedef void (*thread_entry)(void*);
class thread;
+class node;
class process {
public:
@@ -34,7 +37,9 @@ class process {
process *next; //Forms a linked list
thread *threads;
- process() {} // must not be used directly
+ earray<node> fd; // file descriptors
+
+ process() : fd(4, 4) {} // must not be used directly
process(process *parent, uint32_t uid, uint32_t privilege);
};
@@ -55,6 +60,7 @@ class thread {
};
extern thread *current_thread;
+extern process *current_process;
void tasking_init();
#ifdef __cplusplus
diff --git a/src/kernel/vfs/node.cpp b/src/kernel/vfs/node.cpp
new file mode 100644
index 0000000..9900a3c
--- /dev/null
+++ b/src/kernel/vfs/node.cpp
@@ -0,0 +1,122 @@
+#include "node.h"
+#include "vdir.h"
+#include <core/monitor.h>
+
+int node::open(process *proc, int mode) {
+ //TODO : permission checks
+ return 0; // ok
+}
+
+int node::stat(file_info *info) {
+ info->type = type;
+ info->dev_type = dev_type;
+ info->mode = mode;
+ info->uid = uid;
+ info->gid = gid;
+ info->size = this->get_size();
+ return 0;
+}
+
+node *root = 0;
+
+void vfs_setup() {
+ root = new vdir(0);
+ root->add_child(".dev", new vdir(root));
+
+ monitor_write("[VFS] ");
+}
+
+node* vfs_find(node* root, char* path) {
+ node* el = root;
+ char *member = path;
+
+ while (*path != 0 && el != 0) {
+ if (*path == '/') {
+ if (member == path) {
+ member++;
+ path++;
+ } else {
+ *path = 0;
+ el = el->get_child(member);
+ path++;
+ member = path;
+ }
+ } else {
+ path++;
+ }
+ }
+ if (el != 0 && member != path) {
+ el = el->get_child(member);
+ }
+
+ return el;
+}
+
+node* vfs_read_fd(FILE d) {
+ return current_process->fd.at(d);
+}
+
+// Syscalls
+
+static FILE i_open(node* r, char* filename, int mode) {
+ node* f = vfs_find(r, filename);
+ if (f == 0) return E_NOT_FOUND;
+ //TODO : different actions depending on open mode
+ int e = f->open(current_process, mode);
+ if (e != 0) return e;
+ return current_process->fd.add(f);
+}
+
+FILE open(char* filename, int mode) {
+ return i_open(root, filename, mode);
+}
+
+FILE open_relative(FILE root, char* filename, int mode) {
+ node* n = vfs_read_fd(root);
+ if (n == 0) return E_INVALID_FD;
+ return i_open(n, filename, mode);
+}
+
+int stat(char* filename, file_info *info) {
+ node *f = vfs_find(root, filename);
+ if (f == 0) return E_NOT_FOUND;
+ return f->stat(info);
+}
+
+int stat_relative(FILE root, char* filename, file_info *info) {
+ node *r = vfs_read_fd(root);
+ if (r == 0) return E_INVALID_FD;
+ node *f = vfs_find(r, filename);
+ if (f == 0) return E_NOT_FOUND;
+ return f->stat(info);
+}
+
+int statf(FILE file, file_info *info) {
+ node *f = vfs_read_fd(file);
+ if (f == 0) return E_INVALID_FD;
+ return f->stat(info);
+}
+
+void close(FILE file) {
+ node *f = vfs_read_fd(file);
+ if (f != 0) {
+ f->close(current_process);
+ current_process->fd.set(file, 0);
+ }
+}
+
+int read(FILE file, size_t offset, size_t len, char* buffer) {
+ node *f = vfs_read_fd(file);
+ if (f == 0) return E_INVALID_FD;
+ return f->read(offset, len, buffer);
+}
+
+int write(FILE file, size_t offset, size_t len, char* buffer) {
+ node *f = vfs_read_fd(file);
+ if (f == 0) return E_INVALID_FD;
+ return f->write(offset, len, buffer);
+}
+
+int link(char* from, char* to, int mode) {
+ return E_NOT_IMPLEMENTED;
+}
diff --git a/src/kernel/vfs/node.h b/src/kernel/vfs/node.h
new file mode 100644
index 0000000..2d16dab
--- /dev/null
+++ b/src/kernel/vfs/node.h
@@ -0,0 +1,41 @@
+#ifndef DEF_VFS_NODE_H
+#define DEF_VFS_NODE_H
+
+#include <tce/vfs.h>
+#include <tce/syscalls.h>
+
+#include <task/task.h>
+
+class node {
+ public:
+ node* parent;
+ int type, dev_type;
+ int mode, uid, gid;
+
+ node(node* p, int t) : parent(p), type(t) {}
+
+ virtual int open(process *proc, int mode);
+ virtual void close(process *proc) {}
+ virtual int read(size_t offset, size_t len, char *buffer) { return E_NOT_IMPLEMENTED; }
+ virtual int write(size_t offset, size_t len, char* buffer) { return E_NOT_IMPLEMENTED; }
+ int stat(file_info *info);
+ virtual node* get_child(char* name) { return 0; }
+ virtual int add_child(char* name, node *child) { return E_NOT_IMPLEMENTED; }
+ virtual size_t get_size() { return 0; }
+};
+
+void vfs_setup();
+node* vfs_find(node* root, char* filename);
+
+// syscall interface
+FILE open(char* filename, int mode);
+FILE open_relative(FILE root, char* filename, int mode);
+int stat(char* filename, file_info *info);
+int stat_relative(FILE root, char* filename, file_info *info);
+int statf(FILE file, file_info *info);
+void close(FILE file);
+int read(FILE file, size_t offset, size_t len, char *buffer);
+int write(FILE file, size_t offset, size_t len, char *buffer);
+int link(char* from, char* to, int mode);
+
+#endif
diff --git a/src/kernel/vfs/vdir.cpp b/src/kernel/vfs/vdir.cpp
new file mode 100644
index 0000000..299c0e7
--- /dev/null
+++ b/src/kernel/vfs/vdir.cpp
@@ -0,0 +1,55 @@
+#include "vdir.h"
+
+vdir::vdir(node* parent) : node(parent, FT_DIR), children(8, 64) {
+ children.add(new vdir_child(".", this));
+ child_count = 1;
+
+ if (parent != 0) {
+ children.add(new vdir_child("..", parent));
+ child_count++;
+ }
+}
+
+node* vdir::get_child(char* name) {
+ for (unsigned i = 0; i < child_count; i++) {
+ vdir_child *c = children.at(i);
+ ASSERT(c != 0);
+ if (strcmp(c->name, name) == 0) return c->el;
+ }
+ return 0;
+}
+
+int vdir::read(size_t offset, size_t len, char* buffer) {
+ if (offset >= child_count) return 0;
+ vdir_child *c = children.at(offset);
+ ASSERT(c != 0);
+ size_t nlen = strlen(c->name);
+ if (len <= nlen) {
+ return E_TOO_SHORT;
+ }
+ strcpy(buffer, c->name);
+ return nlen;
+}
+
+int vdir::write(size_t offset, size_t len, char* buffer) {
+ // rename file
+ if (offset >= child_count) return E_INVALID_RANGE;
+ vdir_child *c = children.at(offset);
+ ASSERT(c != 0);
+ if (len == 0) return E_INVALID;
+ kfree(c->name);
+ c->name = (char*)kmalloc(len + 1);
+ for (unsigned i = 0; i < len; i++) c->name[i] = buffer[i];
+ c->name[len] = 0;
+ return len;
+}
+
+size_t vdir::get_size() {
+ return child_count;
+}
+
+int vdir::add_child(char* name, node *child) {
+ ASSERT((int)child_count == children.add(new vdir_child(name, child)));
+ child_count++;
+ return 0;
+}
diff --git a/src/kernel/vfs/vdir.h b/src/kernel/vfs/vdir.h
new file mode 100644
index 0000000..9595409
--- /dev/null
+++ b/src/kernel/vfs/vdir.h
@@ -0,0 +1,32 @@
+#ifndef DEF_VFS_VDIR_H
+#define DEF_VFS_VDIR_H
+
+#include "node.h"
+#include <lib/earray.h>
+#include <string.h>
+
+struct vdir_child {
+ char* name;
+ node *el;
+
+ vdir_child(char* na, node* nd) : el(nd) {
+ name = strdup(na);
+ }
+};
+
+class vdir : public node {
+ earray<vdir_child> children;
+ size_t child_count;
+
+ public:
+ vdir(node* parent);
+
+ virtual int read(size_t offset, size_t len, char* buffer);
+ virtual int write(size_t offset, size_t len, char* buffer); // rename file
+ virtual node* get_child(char* name);
+ virtual int add_child(char* name, node *child);
+ virtual size_t get_size();
+};
+
+#endif
+
diff --git a/src/user/lib/include/tce/syscall.h b/src/user/lib/include/tce/syscall.h
index 7bcdd2b..028b544 100644
--- a/src/user/lib/include/tce/syscall.h
+++ b/src/user/lib/include/tce/syscall.h
@@ -3,6 +3,7 @@
#include <types.h>
#include <tce/syscalls.h>
+#include <tce/vfs.h>
#define NEW_STACK_SIZE 0x8000
@@ -18,4 +19,14 @@ int proc_priv();
void* sbrk(size_t size);
void brk(void* ptr);
+FILE open(char* filename, int mode);
+FILE open_relative(FILE root, char* filename, int mode);
+int stat(char* filename, file_info *info);
+int stat_relative(FILE root, char* filename, file_info *info);
+int statf(FILE file, file_info *info);
+void close(FILE file);
+int read(FILE file, size_t offset, size_t len, char *buffer);
+int write(FILE file, size_t offset, size_t len, char *buffer);
+int link(char* from, char* to, int mode);
+
#endif
diff --git a/src/user/lib/std/stdio.c b/src/user/lib/std/stdio.c
index 63ad357..c11dd05 100644
--- a/src/user/lib/std/stdio.c
+++ b/src/user/lib/std/stdio.c
@@ -32,7 +32,6 @@ void printk_int(int number) {
}
r[order] = 0;
printk(s);
- free(s);
}
void printk_hex(unsigned v) {
diff --git a/src/user/lib/tce/syscall.c b/src/user/lib/tce/syscall.c
index c7965a9..4e81475 100644
--- a/src/user/lib/tce/syscall.c
+++ b/src/user/lib/tce/syscall.c
@@ -1,6 +1,7 @@
#include <tce/syscall.h>
#include <stdlib.h>
#include <sched.h>
+#include <tce/vfs.h>
static size_t call(size_t a, size_t b, size_t c, size_t d, size_t e, size_t f) {
size_t ret;
@@ -62,6 +63,8 @@ int proc_priv() {
return call(SC_PROC_PRIV, 0, 0, 0, 0, 0);
}
+// ******** memory
+
void* sbrk(size_t s) {
return (void*)call(SC_SBRK, s, 0, 0, 0, 0);
}
@@ -69,3 +72,41 @@ void* sbrk(size_t s) {
void brk(void* ptr) {
return call (SC_BRK, ptr, 0, 0, 0, 0);
}
+
+// ********** file
+
+FILE open(char* filename, int mode) {
+ return call(SC_OPEN, (unsigned)filename, mode, 0, 0, 0);
+}
+
+FILE open_relative(FILE root, char* filename, int mode) {
+ return call(SC_OPEN_RELATIVE, root, (unsigned) filename, mode, 0, 0);
+}
+
+int stat(char* filename, file_info *info) {
+ return call(SC_STAT, (unsigned) filename, (unsigned) info, 0, 0, 0);
+}
+
+int stat_relative(FILE root, char* filename, file_info *info) {
+ return call(SC_STAT_RELATIVE, root, (unsigned) filename, (unsigned) info, 0, 0);
+}
+
+int statf(FILE file, file_info *info) {
+ return call(SC_STATF, file, (unsigned)info, 0, 0, 0);
+}
+
+void close(FILE file) {
+ call(SC_CLOSE, file, 0, 0, 0, 0);
+}
+
+int read(FILE file, size_t offset, size_t len, char *buffer) {
+ return call(SC_READ, file, offset, len, (unsigned) buffer, 0);
+}
+
+int write(FILE file, size_t offset, size_t len, char* buffer) {
+ return call(SC_WRITE, file, offset, len, (unsigned) buffer, 0);
+}
+
+int link(char* from, char* to, int mode) {
+ return call(SC_LINK, (unsigned) from, (unsigned)to, mode, 0, 0);
+}
diff --git a/src/user/test/main.c b/src/user/test/main.c
index ec14c21..a7df667 100644
--- a/src/user/test/main.c
+++ b/src/user/test/main.c
@@ -1,9 +1,14 @@
#include <tce/syscall.h>
#include <stdlib.h>
+#include <stdio.h>
+
+int threads = 0;
void thread_cascade(void* d) {
int n = (int)d;
+ threads ++;
+
if (d == 0) {
//printk("{#} 0 cascade element started => end\n");
printk("*");
@@ -25,6 +30,41 @@ void thread_cascade(void* d) {
//printk("{#} Thread cascade element finished.\n");
printk(".");
}
+
+ threads--;
+}
+
+void list_dir(FILE f, int lv) {
+ char buf[256];
+ int i = 0, k;
+ int r;
+ file_info info;
+
+ while ((r = read(f, i, 256, buf)) > 0) {
+ for (k = 0; k < lv; k++) printk(" ");
+ printk(buf); printk("\t\t");
+
+ stat_relative(f, buf, &info);
+ printk_hex(info.type);
+ if (info.type & FT_DIR) {
+ printk("\t");
+ if (strcmp(buf, ".") != 0 && strcmp(buf, "..") != 0) {
+ FILE ff = open_relative(f, buf, 0);
+ if (ff <= 0) {
+ printk("error: "); printk_int(ff); printk("\n");
+ } else {
+ printk("fd: "); printk_int(ff); printk("\n");
+ list_dir(ff, lv+1);
+ close(ff);
+ }
+ } else {
+ printk("\n");
+ }
+ } else {
+ printk("\n");
+ }
+ i++;
+ }
}
int main() {
@@ -32,12 +72,31 @@ int main() {
printk_hex((uint32_t)malloc(42));
printk("\n");
- printk("(test app) Creating thread cascade (total 2**8 = 256 threads)\n");
- thread_new(thread_cascade, (void*)8);
+ printk(" -> Creating thread cascade (total 2**4 = 16 threads)\n");
+ thread_new(thread_cascade, (void*)4);
- printk("(test app) Main thread now sleeping... forever...\n");
+ printk(" -> Main thread now sleeping...\n");
while (1) {
+ thread_sleep(100);
+ if (threads == 0) break;
+ }
+ printk("\n -> Ok, let's try something else.\n");
+
+ FILE f = open("/", 0);
+ if (f <= 0) {
+ printk(" -> Could not open '/', error #");
+ printk_int(f);
+ printk("...\n");
+ } else {
+ printk("Now enumerating '/' (fd "); printk_int(f); printk(") :\n");
+ list_dir(f, 1);
+ close(f);
+ }
+
+ printk(" -> Now sleeping, forever and ever...\n");
+ while(1) {
thread_sleep(1000);
}
+
return 0;
}