From e0d27cc75009e27502d57258cb64c71221b4b7d1 Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sun, 13 Sep 2009 19:41:13 +0200 Subject: Class for file descriptors introduced : File. Not used yet. --- Source/Kernel/Core/kmain.wtf.cpp | 3 +- Source/Kernel/FileSystems/RamFS/RamFS.class.cpp | 8 +- Source/Kernel/Makefile | 1 + Source/Kernel/Melon.ke | Bin 167382 -> 145145 bytes Source/Kernel/TaskManager/Process.class.cpp | 22 +++- Source/Kernel/TaskManager/Process.class.h | 5 + Source/Kernel/VFS/DirectoryNode.class.cpp | 2 + Source/Kernel/VFS/FSNode.proto.h | 7 +- Source/Kernel/VFS/File.class.cpp | 110 +++++++++++++++++++ Source/Kernel/VFS/File.class.h | 42 ++++++++ Source/Kernel/VFS/FileNode.class.h | 11 +- Source/Kernel/VFS/VFS.ns.cpp | 135 ++++++++++++++++++++++++ 12 files changed, 338 insertions(+), 8 deletions(-) create mode 100644 Source/Kernel/VFS/File.class.cpp create mode 100644 Source/Kernel/VFS/File.class.h create mode 100644 Source/Kernel/VFS/VFS.ns.cpp 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 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 Binary files a/Source/Kernel/Melon.ke and b/Source/Kernel/Melon.ke 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 #include +#include 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 m_threads; + Vector 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 +#include + +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 + +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 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 + +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 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 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 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; +} + +} -- cgit v1.2.3