summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Source/Kernel/Core/kmain.wtf.cpp3
-rw-r--r--Source/Kernel/FileSystems/RamFS/RamFS.class.cpp8
-rw-r--r--Source/Kernel/Makefile1
-rwxr-xr-xSource/Kernel/Melon.kebin167382 -> 145145 bytes
-rw-r--r--Source/Kernel/TaskManager/Process.class.cpp22
-rw-r--r--Source/Kernel/TaskManager/Process.class.h5
-rw-r--r--Source/Kernel/VFS/DirectoryNode.class.cpp2
-rw-r--r--Source/Kernel/VFS/FSNode.proto.h7
-rw-r--r--Source/Kernel/VFS/File.class.cpp110
-rw-r--r--Source/Kernel/VFS/File.class.h42
-rw-r--r--Source/Kernel/VFS/FileNode.class.h11
-rw-r--r--Source/Kernel/VFS/VFS.ns.cpp135
12 files changed, 338 insertions, 8 deletions
diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp
index 59d74b5..aef98e3 100644
--- a/Source/Kernel/Core/kmain.wtf.cpp
+++ b/Source/Kernel/Core/kmain.wtf.cpp
@@ -120,7 +120,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) {
while(1) {
kvt->setColor(0);
- *kvt << cwd->getName() << " : ";
+ *kvt << "[" << cwd->getName() << "]# ";
kvt->setColor(8);
Vector<String> tokens = kvt->readLine().split(" ");
kvt->setColor(0);
@@ -150,6 +150,7 @@ void kmain(multiboot_info_t* mbd, u32int magic) {
else
d = (DirectoryNode*)n;
}
+ if (d != NULL) *kvt << "Contents of directory " << VFS::path(d) << " :\n";
for (u32int i = 0; d != NULL && i < d->getLength(); i++) {
FSNode* n = d->getChild(i);
if (n->type() == NT_FILE) {
diff --git a/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp
index 7e29e08..c5d0656 100644
--- a/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp
+++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp
@@ -140,4 +140,10 @@ DirectoryNode* RamFS::createDirectory(DirectoryNode* parent, String name) {
return d;
}
-bool RamFS::remove(DirectoryNode* parent, FSNode* node) { return true; }
+bool RamFS::remove(DirectoryNode* parent, FSNode* node) {
+ if (node->type() == NT_FILE) {
+ u8int *d = ((RamFileNode*)node)->m_data;
+ if (d != 0) Mem::kfree(d);
+ }
+ return true;
+}
diff --git a/Source/Kernel/Makefile b/Source/Kernel/Makefile
index 79dfbb3..3dbd125 100644
--- a/Source/Kernel/Makefile
+++ b/Source/Kernel/Makefile
@@ -39,6 +39,7 @@ Objects = Core/loader.wtf.o \
VFS/Partition.class.o \
VFS/Part.ns.o \
VFS/VFS.ns.o \
+ VFS/File.class.o \
VFS/DirectoryNode.class.o \
FileSystems/RamFS/RamFS.class.o \
SyscallManager/IDT.ns.o \
diff --git a/Source/Kernel/Melon.ke b/Source/Kernel/Melon.ke
index 59e3b8b..3ec26f0 100755
--- a/Source/Kernel/Melon.ke
+++ b/Source/Kernel/Melon.ke
Binary files differ
diff --git a/Source/Kernel/TaskManager/Process.class.cpp b/Source/Kernel/TaskManager/Process.class.cpp
index f94e652..ec1fcc9 100644
--- a/Source/Kernel/TaskManager/Process.class.cpp
+++ b/Source/Kernel/TaskManager/Process.class.cpp
@@ -1,6 +1,7 @@
#include "Process.class.h"
#include <TaskManager/Task.ns.h>
#include <MemoryManager/PhysMem.ns.h>
+#include <VFS/File.class.h>
Process::Process() { //Private constructor, does nothing
}
@@ -40,7 +41,7 @@ Process::Process(String cmdline, u32int uid) {
m_stacksstart = 0xC0000000;
}
-Process::~Process() { //TODO : clean up process
+Process::~Process() {
exit(); //Kill all threads
delete m_pagedir;
}
@@ -59,6 +60,11 @@ void Process::exit() {
delete m_threads.back();
m_threads.pop();
}
+ for (u32int i = 0; i < m_fileDescriptors.size(); i++) {
+ m_fileDescriptors[i]->close(false);
+ delete m_fileDescriptors[i];
+ }
+ m_fileDescriptors.clear();
m_state = P_FINISHED;
}
@@ -82,6 +88,20 @@ void Process::threadFinishes(Thread* thread, u32int retval) {
}
}
+void Process::registerFileDescriptor(File* fd) {
+ m_fileDescriptors.push(fd);
+}
+
+void Process::unregisterFileDescriptor(File* fd) {
+ for (u32int i = 0; i < m_fileDescriptors.size(); i++) {
+ if (m_fileDescriptors[i] == fd) {
+ m_fileDescriptors[i] = m_fileDescriptors.back();
+ m_fileDescriptors.pop();
+ break;
+ }
+ }
+}
+
PageDirectory* Process::getPagedir() {
return m_pagedir;
}
diff --git a/Source/Kernel/TaskManager/Process.class.h b/Source/Kernel/TaskManager/Process.class.h
index 581d6b1..8b0a030 100644
--- a/Source/Kernel/TaskManager/Process.class.h
+++ b/Source/Kernel/TaskManager/Process.class.h
@@ -17,6 +17,7 @@
#define STACKSIZE 4096 //Can change
class Thread;
+class File;
class Process {
friend class Thread;
@@ -34,6 +35,7 @@ class Process {
VirtualTerminal *m_vt;
Vector<Thread*> m_threads;
+ Vector<File*> m_fileDescriptors;
public:
static Process* createKernel(String cmdline, VirtualTerminal *vt); //Also creates a Thread for what's curently happening
@@ -45,6 +47,9 @@ class Process {
void registerThread(Thread* t); //Called when a thread starts
void threadFinishes(Thread* thread, u32int retval); //Called when a thread finishes
+ void registerFileDescriptor(File* fd);
+ void unregisterFileDescriptor(File* fd);
+
PageDirectory* getPagedir();
VirtualTerminal* getVirtualTerminal();
diff --git a/Source/Kernel/VFS/DirectoryNode.class.cpp b/Source/Kernel/VFS/DirectoryNode.class.cpp
index d624e97..95d2245 100644
--- a/Source/Kernel/VFS/DirectoryNode.class.cpp
+++ b/Source/Kernel/VFS/DirectoryNode.class.cpp
@@ -72,5 +72,7 @@ bool DirectoryNode::remove(FSNode* child) {
m_children[idx] = m_children.back();
m_children.pop();
+ delete child;
+
return true;
}
diff --git a/Source/Kernel/VFS/FSNode.proto.h b/Source/Kernel/VFS/FSNode.proto.h
index bcf9393..8773543 100644
--- a/Source/Kernel/VFS/FSNode.proto.h
+++ b/Source/Kernel/VFS/FSNode.proto.h
@@ -16,13 +16,13 @@ enum {
class FSNode {
protected:
String m_name;
- u32int m_length;
+ u64int m_length;
u32int m_permissions, m_uid, m_gid;
FileSystem *m_fs;
FSNode *m_parent;
public:
- FSNode(String name, FileSystem* fs, FSNode* parent, u32int length = 0, u32int permissions = 0777,
+ FSNode(String name, FileSystem* fs, FSNode* parent, u64int length = 0, u32int permissions = 0777,
u32int uid = 0, u32int gid = 0) :
m_name(name), m_length(length), m_permissions(permissions),
m_uid(uid), m_gid(gid), m_fs(fs), m_parent(parent) {}
@@ -30,9 +30,10 @@ class FSNode {
virtual u8int type() = 0;
virtual bool removable() = 0; //True for files, false for non-empty directories, true otherwise
+ virtual bool used() { return false; } //True if file is read/written from/to
const String& getName() { return m_name; }
- u32int getLength() { return m_length; }
+ u64int getLength() { return m_length; }
u32int getPermissions() { return m_permissions; }
u32int getUid() { return m_uid; }
u32int getGid() { return m_gid; }
diff --git a/Source/Kernel/VFS/File.class.cpp b/Source/Kernel/VFS/File.class.cpp
new file mode 100644
index 0000000..ba837e9
--- /dev/null
+++ b/Source/Kernel/VFS/File.class.cpp
@@ -0,0 +1,110 @@
+#include "File.class.h"
+#include <VFS/VFS.ns.h>
+#include <TaskManager/Task.ns.h>
+
+File::File() : m_file(NULL), m_valid(false), m_writable(false), m_position(0) {
+}
+
+File::File(String filename, u8int mode, FSNode* start) :
+ m_file(NULL), m_valid(false), m_writable(false), m_position(0) {
+ open(filename, mode, start);
+}
+
+File::~File() {
+ close();
+}
+
+bool File::open(String filename, u8int mode, FSNode* start) {
+ if (m_valid) return false;
+
+ FSNode* node = VFS::find(filename, start);
+ if (node == NULL) return false;
+ if (node->type() != NT_FILE) return false;
+
+ m_file = (FileNode*) node;
+
+ m_writable = (mode != FM_READ);
+ if (!m_file->writable() and m_writable) return false;
+
+ if (mode == FM_READ or mode == FM_REPLACE) {
+ m_position = 0;
+ } else if (mode == FM_TRUNCATE) {
+ if (!m_file->truncate()) return false;
+ m_position = 0;
+ } else if (mode == FM_APPEND) {
+ m_position = m_file->getLength();
+ }
+
+ if (m_writable)
+ m_file->m_readers++;
+ else
+ m_file->m_writers++;
+
+ Task::currentProcess->registerFileDescriptor(this);
+ m_valid = true;
+ return true;
+}
+
+u32int File::read(u32int max_length, u8int *data) {
+ if (!m_valid) return 0;
+ u32int l = m_file->read(m_position, max_length, data);
+ m_position += l;
+ return l;
+}
+
+bool File::write(u32int length, u8int *data) {
+ if (!m_valid) return false;
+ if (!m_writable) return false;
+ if (m_file->write(m_position, length, data)) {
+ m_position += length;
+ return true;
+ }
+ return false;
+}
+
+bool File::seek(u64int count, u8int mode) {
+ if (!m_valid) return false;
+ if (mode == SM_FORWARD) {
+ if (m_position + count <= m_file->getLength()) {
+ m_position += count;
+ return true;
+ } else {
+ return false;
+ }
+ } else if (mode == SM_BACKWARD) {
+ if (count <= m_position) {
+ m_position -= count;
+ return true;
+ } else {
+ return false;
+ }
+ } else if (mode == SM_BEGINNING) {
+ if (count <= m_file->getLength()) {
+ m_position = count;
+ return true;
+ } else {
+ return false;
+ }
+ } else if (mode == SM_END) {
+ if (count <= m_file->getLength()) {
+ m_position = m_file->getLength() - count;
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+}
+
+void File::close(bool unregisterFD) {
+ if (!m_valid) return;
+ if (m_writable)
+ m_file->m_writers--;
+ else
+ m_file->m_readers--;
+ m_valid = false;
+ m_file = NULL;
+ m_position = 0;
+ m_writable = false;
+ if (unregisterFD) Task::currentProcess->unregisterFileDescriptor(this);
+}
diff --git a/Source/Kernel/VFS/File.class.h b/Source/Kernel/VFS/File.class.h
new file mode 100644
index 0000000..dace2cf
--- /dev/null
+++ b/Source/Kernel/VFS/File.class.h
@@ -0,0 +1,42 @@
+#ifndef DEF_FILE_CLASS_H
+#define DEF_FILE_CLASS_H
+
+#include <VFS/FileNode.class.h>
+
+enum {
+ FM_READ = 0, //Open for read, put cursor at beginning
+ FM_TRUNCATE = 1, //Open for write, truncating file before
+ FM_APPEND = 2, //Open for write, put cursor at end
+ FM_REPLACE = 3 //Open for write, put cursor at beginning
+};
+
+enum {
+ SM_FORWARD = 0, //Seek from actual position
+ SM_BACKWARD = 1, //Seek from actual position, backward
+ SM_BEGINNING = 2, //Seek from start of file
+ SM_END = 3, //Seek from end of file
+};
+
+class File {
+ private:
+ FileNode* m_file;
+ bool m_valid; //Is a file opened and valid ?
+ bool m_writable; //Is file opened for write ?
+ u64int m_position;
+
+ public:
+ File();
+ File(String filename, u8int mode = FM_READ, FSNode* start = 0);
+ ~File();
+
+ bool open(String filename, u8int mode = FM_READ, FSNode* start = 0);
+ u32int read(u32int max_length, u8int *data);
+ bool write(u32int length, u8int *data);
+ bool seek(u64int count, u8int mode);
+ u64int getPosition() { return m_position; }
+ void close(bool unregisterFD = true); //unregisterFD = whether or not we must unregister the file descriptor from process
+
+ bool valid() { return m_valid; }
+};
+
+#endif
diff --git a/Source/Kernel/VFS/FileNode.class.h b/Source/Kernel/VFS/FileNode.class.h
index b3a3f67..ac170ae 100644
--- a/Source/Kernel/VFS/FileNode.class.h
+++ b/Source/Kernel/VFS/FileNode.class.h
@@ -4,16 +4,24 @@
#include <VFS/FSNode.proto.h>
class FileNode : public FSNode {
+ friend class File;
+
protected:
+ u32int m_readers, m_writers;
+
FileNode(String name, FileSystem* fs, FSNode* parent, u32int length = 0, u32int permissions = 0777,
- u32int uid = 0, u32int gid = 0): FSNode(name, fs, parent, length, permissions, uid, gid) {}
+ u32int uid = 0, u32int gid = 0): FSNode(name, fs, parent, length, permissions, uid, gid),
+ m_readers(0), m_writers(0) {}
public:
virtual ~FileNode() {}
u8int type() { return NT_FILE; }
bool removable() { return true; }
+ bool used() { return (m_readers != 0 or m_writers != 0); }
+ bool writable() { return m_fs->isWritable(); }
+ //protected:
u32int read(u64int position, u32int max_length, u8int *data) {
return m_fs->read(this, position, max_length, data);
}
@@ -25,7 +33,6 @@ class FileNode : public FSNode {
bool truncate() {
return m_fs->truncate(this);
}
-
};
#endif
diff --git a/Source/Kernel/VFS/VFS.ns.cpp b/Source/Kernel/VFS/VFS.ns.cpp
new file mode 100644
index 0000000..6db791a
--- /dev/null
+++ b/Source/Kernel/VFS/VFS.ns.cpp
@@ -0,0 +1,135 @@
+#include "VFS.ns.h"
+#include <VFS/FileNode.class.h>
+
+namespace VFS {
+
+DirectoryNode *rootNode;
+
+//TODO : mount stuff
+
+bool setRootNode(DirectoryNode* node) {
+ rootNode = node;
+ return true;
+}
+
+DirectoryNode* getRootNode() {
+ return rootNode;
+}
+
+FSNode* find(const String& path, FSNode* start) {
+ if (start == 0) start = rootNode;
+
+ Vector<String> p = path.split("/");
+
+ FSNode* node = start;
+ if (p[0].empty()) node = rootNode; //Empty first element means string starts with "/"
+ for (u32int i = 0; i < p.size(); i++) {
+ if (p[i] == "..") {
+ node = node->getParent();
+ } else if (!p[i].empty() and p[i] != ".") {
+ if (node->type() == NT_DIRECTORY) {
+ node = ((DirectoryNode*)node)->getChild(p[i]);
+ } else {
+ node = NULL;
+ }
+ }
+ if (node == NULL) return node;
+ }
+
+ return node;
+}
+
+FSNode* createFile(const String& path, FSNode* start) {
+ if (start == 0) start = rootNode;
+
+ Vector<String> p = path.split("/");
+ String name = p.back();
+ p.pop();
+
+ FSNode* node = start;
+ if (!path.empty()) {
+ if (p[0].empty()) node = rootNode;
+ for (u32int i = 0; i < p.size(); i++) {
+ if (p[i] == "..") {
+ node = node->getParent();
+ } else if (!p[i].empty() and p[i] != ".") {
+ if (node->type() == NT_DIRECTORY) {
+ node = ((DirectoryNode*)node)->getChild(p[i]);
+ } else {
+ node = NULL;
+ }
+ }
+ if (node == NULL) return node;
+ }
+ }
+
+ if (node->type() == NT_DIRECTORY) {
+ return ((DirectoryNode*)node)->createFile(name);
+ } else {
+ return NULL;
+ }
+}
+
+FSNode* createDirectory(const String& path, FSNode* start) {
+ if (start == 0) start = rootNode;
+
+ Vector<String> p = path.split("/");
+ String name = p.back();
+ p.pop();
+
+ FSNode* node = start;
+ if (!path.empty()) {
+ if (p[0].empty()) node = rootNode;
+ for (u32int i = 0; i < p.size(); i++) {
+ if (p[i] == "..") {
+ node = node->getParent();
+ } else if (!p[i].empty() and p[i] != ".") {
+ if (node->type() == NT_DIRECTORY) {
+ node = ((DirectoryNode*)node)->getChild(p[i]);
+ } else {
+ node = NULL;
+ }
+ }
+ if (node == NULL) return node;
+ }
+ }
+
+ if (node->type() == NT_DIRECTORY) {
+ return ((DirectoryNode*)node)->createDirectory(name);
+ } else {
+ return NULL;
+ }
+}
+
+bool remove(const String& path, FSNode* start) {
+ FSNode* node =find(path, start);
+ if (node == NULL) return false;
+ FSNode* parent = node->getParent();
+ if (parent == NULL) return false;
+
+ if (parent->type() == NT_DIRECTORY) {
+ return ((DirectoryNode*)parent)->remove(node);
+ } else {
+ return false; //Something wierd happenned
+ }
+}
+
+String path(FSNode* node) {
+ String path;
+
+ while (node != NULL) {
+ String t = "/";
+ t += node->getName();
+ if (t != "//") {
+ t += path;
+ path = t;
+ }
+ node = node->getParent();
+ }
+
+ if (path.empty()) path = "/";
+
+ return path;
+}
+
+}