From 668bbfdaea7e8cba8233ebffe2a9d46a66e257cd Mon Sep 17 00:00:00 2001 From: Alexis211 Date: Sun, 13 Sep 2009 18:27:42 +0200 Subject: We now can navigate in the VFS using the integrated shell. --- Source/Kernel/Core/kmain.wtf.cpp | 91 +++++++++++++++------ Source/Kernel/FileSystems/RamFS/RamFS.class.cpp | 2 + Source/Kernel/FileSystems/RamFS/RamFS.class.h | 1 + .../Kernel/FileSystems/RamFS/RamFileNode.class.h | 2 +- Source/Kernel/Library/String.class.cpp | 16 ++-- Source/Kernel/Library/String.class.h | 18 ++-- Source/Kernel/Library/Vector.class.cpp | 29 +++++-- Source/Kernel/Library/Vector.class.h | 4 +- Source/Kernel/Makefile | 2 + Source/Kernel/Melon.ke | Bin 131870 -> 167382 bytes Source/Kernel/VFS/DirectoryNode.class.cpp | 76 +++++++++++++++++ Source/Kernel/VFS/DirectoryNode.class.h | 47 ++--------- Source/Kernel/VFS/FSNode.proto.h | 9 +- Source/Kernel/VFS/FileNode.class.h | 3 + Source/Kernel/VFS/FileSystem.proto.h | 1 + Source/Kernel/VFS/VFS.ns.h | 13 ++- 16 files changed, 216 insertions(+), 98 deletions(-) create mode 100644 Source/Kernel/VFS/DirectoryNode.class.cpp (limited to 'Source') diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp index 6806411..808e254 100644 --- a/Source/Kernel/Core/kmain.wtf.cpp +++ b/Source/Kernel/Core/kmain.wtf.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -111,47 +112,83 @@ void kmain(multiboot_info_t* mbd, u32int magic) { FloppyController::detect(); OK(kvt); FileSystem* fs = new RamFS((u8int*)mods[0].mod_start, 1024 * 1024); - DirectoryNode* rd; - rd = fs->getRootNode(); - /*FileNode* f; - f = rd->createFile(String("test")); - f->write(0, 4, (u8int*)"plop"); */ + DirectoryNode* cwd; + cwd = fs->getRootNode(); + VFS::setRootNode(cwd); asm volatile("sti"); while(1) { kvt->setColor(0); - *kvt << "> "; + *kvt << cwd->getName() << " : "; kvt->setColor(8); - String tmp = kvt->readLine(); + Vector tokens = kvt->readLine().split(" "); kvt->setColor(0); - if (tmp == "help") { + if (tokens[0] == "help") { *kvt << " - Command list for integrated kernel shell:\n"; *kvt << " - help shows this help screen\n"; *kvt << " - reboot reboots your computer\n"; + *kvt << " - ls [] shows contents of a directory\n"; + *kvt << " - cd goes to directory \n"; + *kvt << " - cat shows contents of file \n"; + *kvt << " - pwd prints current directory\n"; *kvt << " - devices shows all detected devices on your computer\n"; *kvt << " - free shows memory usage (physical frames and kernel heap)\n"; *kvt << " - uptime shows seconds since boot\n"; *kvt << " - part shows all detected block devices and partitions\n"; - } else if (tmp == "ls") { - for (u32int i = 0; i < rd->getLength(); i++) { - FSNode* n = rd->getChild(i); + } else if (tokens[0] == "reboot") { + Sys::reboot(); + } else if (tokens[0] == "ls") { + DirectoryNode* d = cwd; + if (tokens.size() == 2) { + FSNode* n = VFS::find(tokens[1], cwd); + d = NULL; + if (n == NULL) + *kvt << "No such directory : " << tokens[1] << "\n"; + else if (n->type() != NT_DIRECTORY) + *kvt << "Not a directory : " << tokens[1] << "\n"; + else + d = (DirectoryNode*)n; + } + for (u32int i = 0; d != NULL && i < d->getLength(); i++) { + FSNode* n = d->getChild(i); if (n->type() == NT_FILE) { FileNode* f = (FileNode*)n; - *kvt << "Found file " << f->getName() << ", length " << (s32int)f->getLength() << " :\n"; - u8int* d = (u8int*)Mem::kalloc(f->getLength() + 1); - f->read(0, f->getLength(), d); - d[f->getLength()] = 0; - *kvt << String((const char*)d); - Mem::kfree(d); - *kvt << "\n"; + *kvt << " - FILE\t" << f->getName(); + kvt->setCursorCol(30); + *kvt << (s32int)f->getLength() << " bytes.\n"; } else if (n->type() == NT_DIRECTORY) { - *kvt << "Found directory " << n->getName() << ", " << (s32int)n->getLength() << " items.\n"; + *kvt << " - DIR\t" << n->getName(); + kvt->setCursorCol(30); + *kvt << (s32int)n->getLength() << " items.\n"; } } - } else if (tmp == "reboot") { - Sys::reboot(); - } else if (tmp == "devices") { + } else if (tokens[0] == "cd") { + FSNode* n = VFS::find(tokens[1], cwd); + if (n == NULL) + *kvt << "No such directory : " << tokens[1] << "\n"; + else if (n->type() != NT_DIRECTORY) + *kvt << "Not a directory : " << tokens[1] << "\n"; + else + cwd = (DirectoryNode*)n; + } else if (tokens[0] == "cat") { + for (u32int i = 1; i < tokens.size(); i++) { + FSNode* n = VFS::find(tokens[i], cwd); + if (n == NULL) { + *kvt << "No such file : " << tokens[1] << "\n"; + } else if (n->type() != NT_FILE) { + *kvt << "Not a file : " << tokens[1] << "\n"; + } else { + FileNode* f = (FileNode*) n; + u8int *buff = (u8int*)Mem::kalloc(f->getLength()); + f->read(0, f->getLength(), buff); + *kvt << String((const char*) buff); + Mem::kfree(buff); + } + } + } else if (tokens[0] == "pwd") { + *kvt << "Current location : " << VFS::path(cwd) << "\n"; + } else if (tokens[0] == "devices") { Vector dev = Dev::findDevices(); *kvt << " - Detected devices :\n"; for (u32int i = 0; i < dev.size(); i++) { @@ -159,16 +196,16 @@ void kmain(multiboot_info_t* mbd, u32int magic) { kvt->setCursorCol(25); *kvt << dev[i]->getName() << "\n"; } - } else if (tmp == "free") { + } else if (tokens[0] == "free") { u32int frames = PhysMem::total(), freef = PhysMem::free(); *kvt << " - Free frames : " << (s32int)freef << " (" << (s32int)(freef * 4 / 1024) << "Mo) of " << (s32int)frames << " (" << (s32int)(frames * 4 / 1024) << "Mo).\n"; u32int kh = Mem::kheapSize(), freek = Mem::kheapFree; *kvt << " - Kernel heap free : " << (s32int)(freek / 1024 / 1024) << "Mo (" << (s32int)(freek / 1024) << "Ko) of " << (s32int)(kh / 1024 / 1024) << "Mo (" << (s32int)(kh / 1024) << "Ko).\n"; - } else if (tmp == "uptime") { + } else if (tokens[0] == "uptime") { *kvt << " - Uptime : " << (s32int)(Time::uptime()) << "s.\n"; - } else if (tmp == "part") { + } else if (tokens[0] == "part") { *kvt << " * ID\tClass Name\n"; for (u32int i = 0; i < Part::devices.size(); i++) { *kvt << " - " << (s32int)i << "\t"; @@ -187,8 +224,8 @@ void kmain(multiboot_info_t* mbd, u32int magic) { } } } - } else if (!tmp.empty()) { - *kvt << " - Unrecognized command: " << tmp << "\n"; + } else if (tokens.size() > 1 or tokens[0] != "") { + *kvt << " - Unrecognized command: " << tokens[0] << "\n"; } } PANIC("END OF KMAIN"); diff --git a/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp index f5a502f..7e29e08 100644 --- a/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp +++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp @@ -139,3 +139,5 @@ DirectoryNode* RamFS::createDirectory(DirectoryNode* parent, String name) { return d; } + +bool RamFS::remove(DirectoryNode* parent, FSNode* node) { return true; } diff --git a/Source/Kernel/FileSystems/RamFS/RamFS.class.h b/Source/Kernel/FileSystems/RamFS/RamFS.class.h index 034a948..0a3f0c4 100644 --- a/Source/Kernel/FileSystems/RamFS/RamFS.class.h +++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.h @@ -37,6 +37,7 @@ class RamFS : public FileSystem { bool loadContents(DirectoryNode* dir); FileNode* createFile(DirectoryNode* parent, String name); DirectoryNode* createDirectory(DirectoryNode* parent, String name); + bool remove(DirectoryNode* parent, FSNode* node); }; #endif diff --git a/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h b/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h index 142d763..d600630 100644 --- a/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h +++ b/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h @@ -11,7 +11,7 @@ class RamFileNode : public FileNode { u32int uid = 0, u32int gid = 0) : FileNode(name, fs, parent, 0, permissions, uid, gid), m_data(0) {} - u8int *m_data; + u8int *m_data; //We don't take care of allocation/freeing here, RamFS:: does that for us void setLength(u32int length) { m_length = length; } }; diff --git a/Source/Kernel/Library/String.class.cpp b/Source/Kernel/Library/String.class.cpp index b8e01d5..5ee216c 100644 --- a/Source/Kernel/Library/String.class.cpp +++ b/Source/Kernel/Library/String.class.cpp @@ -116,7 +116,7 @@ void String::operator= (const char* string) { m_string[m_length] = 0; } -bool String::operator== (const String &other) { +bool String::operator== (const String &other) const { if (m_length != other.m_length) return false; for (u32int i = 0; i < m_length; i++) { if (m_string[i] != other.m_string[i]) return false; @@ -124,7 +124,7 @@ bool String::operator== (const String &other) { return true; } -bool String::operator== (const char* string) { +bool String::operator== (const char* string) const { if (m_length != WChar::utf8len(string)) return false; int i = 0, l = strlen(string), c = 0; WChar tmp; @@ -181,22 +181,22 @@ String& String::operator+= (WChar other) { return *this; } -String& String::operator+ (const String &other) { //Can be optimized +String& String::operator+ (const String &other) const { //Can be optimized String ret(*this); return (ret += other); } -String& String::operator+ (const char* other) { //Can be optimized +String& String::operator+ (const char* other) const { //Can be optimized String ret(*this); return (ret += other); } -String& String::operator+ (WChar other) { +String& String::operator+ (WChar other) const { String ret(*this); return (ret += other); } -s32int String::toInt() { +s32int String::toInt() const { if (m_string == 0) return 0; s32int pos = 0, number = 0; bool negative = false; @@ -213,7 +213,7 @@ s32int String::toInt() { return number; } -u32int String::toInt16() { +u32int String::toInt16() const { if (m_string == 0) return 0; u32int pos = 0, number = 0; if (m_string[0].value == '0' && m_string[1].value == 'x') pos = 2; @@ -254,7 +254,7 @@ bool String::empty() const { return (m_length == 0); } -Vector String::split(WChar c) { +Vector String::split(WChar c) const { Vector ret; ret.push(String("")); for (u32int i = 0; i < m_length; i++) { diff --git a/Source/Kernel/Library/String.class.h b/Source/Kernel/Library/String.class.h index 6b48a30..01cc6a8 100644 --- a/Source/Kernel/Library/String.class.h +++ b/Source/Kernel/Library/String.class.h @@ -23,23 +23,25 @@ class String { void operator= (const String &other); void operator= (const char* string); - bool operator== (const String &other); - bool operator== (const char* string); + bool operator== (const String &other) const; + bool operator== (const char* string) const; + bool operator!= (const String &other) { return !(operator== (other)); } + bool operator!= (const char* other) { return !(operator== (other)); } String &operator+= (const String &other); String &operator+= (const char* other); String &operator+= (WChar other); - String &operator+ (const String &other); - String &operator+ (const char* other); - String &operator+ (WChar other); - s32int toInt(); - u32int toInt16(); //From HEX + String &operator+ (const String &other) const; + String &operator+ (const char* other) const; + String &operator+ (WChar other) const; + s32int toInt() const; + u32int toInt16() const; //From HEX WChar& operator[] (int index) const; u32int size() const; void clear(); bool empty() const; - Vector split(WChar c); + Vector split(WChar c) const; String substr(s32int start, s32int size); }; diff --git a/Source/Kernel/Library/Vector.class.cpp b/Source/Kernel/Library/Vector.class.cpp index 91196b8..8b032ca 100644 --- a/Source/Kernel/Library/Vector.class.cpp +++ b/Source/Kernel/Library/Vector.class.cpp @@ -1,5 +1,12 @@ using namespace CMem; //strlen and memcpy +#define DELDATA if (m_data != NULL and m_size != 0) { \ + for (u32int i = 0; i < m_size; i++) { \ + m_data[i].~T(); \ + } \ + Mem::kfree(m_data); \ +} + template Vector::Vector() { //DEBUG_HEX((u32int)this); DEBUG(" NEW EMPTY"); @@ -16,11 +23,14 @@ Vector::Vector(u32int size) { } template -Vector::Vector(u32int size, T value) { +Vector::Vector(u32int size, const T& value) { //DEBUG_HEX((u32int)this); DEBUG(" NEW FILLED"); //m_data = (T*)Mem::kalloc(size * sizeof(T)); - m_data = new T[size](value); + m_data = new T[size]; m_size = size; + for (u32int i = 0; i < m_size; i++) { + new (&m_data[i]) T(value); + } /*for (u32int i = 0; i < size; i++) { m_data[i] = new(&m_data[i]) T(value); }*/ @@ -39,18 +49,20 @@ Vector::Vector(const Vector &other) { template Vector& Vector::operator= (const Vector &other) { //DEBUG_HEX((u32int)this); DEBUG(" COPY EQ"); - if (m_data != 0) delete[] m_data; + DELDATA; m_size = other.m_size; m_data = (T*)Mem::kalloc(m_size * sizeof(T)); for (u32int i = 0; i < m_size; i++) { new(&m_data[i]) T(other.m_data[i]); } + return *this; } template Vector::~Vector() { //DEBUG_HEX((u32int)this); DEBUG(" DELETE"); - if (m_data != 0) delete[] m_data; + DELDATA; + //if (m_data != 0) delete[] m_data; } template @@ -59,10 +71,13 @@ T& Vector::operator[] (u32int index) { } template -void Vector::push(T element) { +void Vector::push(const T& element) { T* newdata = (T*)Mem::kalloc((m_size + 1) * sizeof(T)); - memcpy((u8int*)newdata, (const u8int*) m_data, m_size * sizeof(T)); + if (m_size != 0 and m_data != 0) { + memcpy((u8int*)newdata, (const u8int*) m_data, m_size * sizeof(T)); + } new(&newdata[m_size]) T(element); //Construct by copy + //newdata[m_size] = element; m_size++; Mem::kfree(m_data); m_data = newdata; @@ -114,7 +129,7 @@ bool Vector::empty() { template void Vector::clear() { if (empty()) return; - delete [] m_data; + DELDATA m_data = 0; m_size = 0; } diff --git a/Source/Kernel/Library/Vector.class.h b/Source/Kernel/Library/Vector.class.h index f16303b..ca86c2a 100644 --- a/Source/Kernel/Library/Vector.class.h +++ b/Source/Kernel/Library/Vector.class.h @@ -12,14 +12,14 @@ class Vector { public: Vector(); Vector(u32int size); - Vector(u32int size, T value); + Vector(u32int size, const T& value); Vector(const Vector &other); Vector& operator= (const Vector &other); ~Vector(); T& operator[] (u32int index); - void push(T element); + void push(const T& element); //void push(T& element); void pop(); diff --git a/Source/Kernel/Makefile b/Source/Kernel/Makefile index 7f2bf29..79dfbb3 100644 --- a/Source/Kernel/Makefile +++ b/Source/Kernel/Makefile @@ -38,6 +38,8 @@ Objects = Core/loader.wtf.o \ Library/WChar.class.o \ VFS/Partition.class.o \ VFS/Part.ns.o \ + VFS/VFS.ns.o \ + VFS/DirectoryNode.class.o \ FileSystems/RamFS/RamFS.class.o \ SyscallManager/IDT.ns.o \ SyscallManager/IDT.wtf.o \ diff --git a/Source/Kernel/Melon.ke b/Source/Kernel/Melon.ke index c9d56ba..418c1a8 100755 Binary files a/Source/Kernel/Melon.ke and b/Source/Kernel/Melon.ke differ diff --git a/Source/Kernel/VFS/DirectoryNode.class.cpp b/Source/Kernel/VFS/DirectoryNode.class.cpp new file mode 100644 index 0000000..d624e97 --- /dev/null +++ b/Source/Kernel/VFS/DirectoryNode.class.cpp @@ -0,0 +1,76 @@ +#include "DirectoryNode.class.h" + +bool DirectoryNode::removable() { + if (!m_contentLoaded) + if (!loadContent()) + return false; + return m_children.empty(); +} + +bool DirectoryNode::loadContent() { + if (m_contentLoaded) return true; + bool b = m_fs->loadContents(this); + if (!b) return false; + m_length = m_children.size(); + m_contentLoaded = true; + return b; +} + +FSNode* DirectoryNode::getChild(u32int index) { + if (!m_contentLoaded) + if (!loadContent()) + return NULL; + if (index >= m_children.size()) return NULL; + return m_children[index]; +} + +FSNode* DirectoryNode::getChild(const String& name) { + if (!m_contentLoaded) + if (!loadContent()) + return NULL; + for (u32int i = 0; i < m_children.size(); i++) { + if (name == m_children[i]->getName()) + return m_children[i]; + } + return NULL; +} + +FileNode* DirectoryNode::createFile(const String& name) { + FileNode* n = m_fs->createFile(this, name); + m_length = m_children.size(); + return n; +} + +DirectoryNode* DirectoryNode::createDirectory(const String& name) { + DirectoryNode* n = m_fs->createDirectory(this, name); + m_length = m_children.size(); + return n; +} + +bool DirectoryNode::remove(FSNode* child) { + //Check node is indeed one of our childs + if (!m_contentLoaded) + if (!loadContent()) + return false; + u32int idx = (u32int) - 1; + for (u32int i = 0; i < m_children.size(); i++) { + if (m_children[i] == child) { + idx = i; + break; + } + } + if (idx == (u32int) - 1) return false; + + //Check if we can remove node + if (!m_children[idx]->removable()) return false; + if (m_fs != m_children[idx]->getFS()) return false; //We could !be on the same FS + + //Ask FS to remove node + if (!m_fs->remove(this, child)) return false; + + //Remove node from our children list + m_children[idx] = m_children.back(); + m_children.pop(); + + return true; +} diff --git a/Source/Kernel/VFS/DirectoryNode.class.h b/Source/Kernel/VFS/DirectoryNode.class.h index cb1574c..5de523e 100644 --- a/Source/Kernel/VFS/DirectoryNode.class.h +++ b/Source/Kernel/VFS/DirectoryNode.class.h @@ -13,48 +13,19 @@ class DirectoryNode : public FSNode { DirectoryNode(String name, FileSystem* fs, FSNode* parent, u32int permissions = 0777, u32int uid = 0, u32int gid = 0) : FSNode(name, fs, parent, 0, permissions, uid, gid), m_children(), m_contentLoaded(false) {} + virtual ~DirectoryNode() {} Vector &getChildren() { return m_children; } //MUST BE USED ONLY BY FILESYSTEMS u8int type() { return NT_DIRECTORY; } - - bool loadContent() { - if (m_contentLoaded) return true; - bool b = m_fs->loadContents(this); - if (!b) return false; - m_length = m_children.size(); - m_contentLoaded = true; - return b; - } - - FSNode* getChild(u32int index) { - if (!m_contentLoaded) - if (!loadContent()) - return NULL; - if (index >= m_children.size()) return NULL; - return m_children[index]; - } - - FSNode* getChild(String name) { - if (!m_contentLoaded) - if (!loadContent()) - return NULL; - for (u32int i = 0; i < m_children.size(); i++) { - if (name == m_children[i]->getName()) - return m_children[i]; - } - return NULL; - } - FileNode* createFile(String name) { - FileNode* n = m_fs->createFile(this, name); - m_length = m_children.size(); - return n; - } - DirectoryNode* createDirectory(String name) { - DirectoryNode* n = m_fs->createDirectory(this, name); - m_length = m_children.size(); - return n; - } + bool removable(); + + bool loadContent(); + FSNode* getChild(u32int index); + FSNode* getChild(const String& name); + FileNode* createFile(const String& name); + DirectoryNode* createDirectory(const String& name); + bool remove(FSNode* child); //Removes a child node from this directory }; #endif diff --git a/Source/Kernel/VFS/FSNode.proto.h b/Source/Kernel/VFS/FSNode.proto.h index fb24a82..bcf9393 100644 --- a/Source/Kernel/VFS/FSNode.proto.h +++ b/Source/Kernel/VFS/FSNode.proto.h @@ -19,16 +19,17 @@ class FSNode { u32int m_length; u32int m_permissions, m_uid, m_gid; FileSystem *m_fs; - FSNode *m_parent; - + FSNode *m_parent; + + public: FSNode(String name, FileSystem* fs, FSNode* parent, u32int 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) {} - - public: + virtual ~FSNode() {} virtual u8int type() = 0; + virtual bool removable() = 0; //True for files, false for non-empty directories, true otherwise const String& getName() { return m_name; } u32int getLength() { return m_length; } diff --git a/Source/Kernel/VFS/FileNode.class.h b/Source/Kernel/VFS/FileNode.class.h index 29fab45..b3a3f67 100644 --- a/Source/Kernel/VFS/FileNode.class.h +++ b/Source/Kernel/VFS/FileNode.class.h @@ -9,7 +9,10 @@ class FileNode : public FSNode { u32int uid = 0, u32int gid = 0): FSNode(name, fs, parent, length, permissions, uid, gid) {} public: + virtual ~FileNode() {} + u8int type() { return NT_FILE; } + bool removable() { return true; } u32int read(u64int position, u32int max_length, u8int *data) { return m_fs->read(this, position, max_length, data); diff --git a/Source/Kernel/VFS/FileSystem.proto.h b/Source/Kernel/VFS/FileSystem.proto.h index 79bb84c..2f768a7 100644 --- a/Source/Kernel/VFS/FileSystem.proto.h +++ b/Source/Kernel/VFS/FileSystem.proto.h @@ -30,6 +30,7 @@ class FileSystem { virtual bool loadContents(DirectoryNode* dir) = 0; virtual FileNode* createFile(DirectoryNode* parent, String name) = 0; virtual DirectoryNode* createDirectory(DirectoryNode* parent, String name) = 0; + virtual bool remove(DirectoryNode* parent, FSNode* node) = 0; }; #endif diff --git a/Source/Kernel/VFS/VFS.ns.h b/Source/Kernel/VFS/VFS.ns.h index 622d120..1021d7c 100644 --- a/Source/Kernel/VFS/VFS.ns.h +++ b/Source/Kernel/VFS/VFS.ns.h @@ -1,15 +1,22 @@ #ifndef DEF_VFS_NS_H #define DEF_VFS_NS_H -#include +#include #include typedef FileSystem* (* mountcallback)(Partition* partition); namespace VFS { void registerMountCallback(mountcallback mcb); - bool mount(Partition* partition); - bool setRootNode(FSNode* root); + bool mount(Partition* partition, DirectoryNode mountpoint); + bool setRootNode(DirectoryNode* root); + DirectoryNode* getRootNode(); + + FSNode* find(const String& path, FSNode* start = 0); + FSNode* createFile(const String& path, FSNode* start = 0); + FSNode* createDirectory(const String& path, FSNode* start = 0); + bool remove(const String& path, FSNode* start = 0); //Returns false for non-empty directories + String path(FSNode* node); //Returns complete path for a node } #endif -- cgit v1.2.3