diff options
author | Alexis211 <alexis211@gmail.com> | 2009-09-13 18:34:39 +0200 |
---|---|---|
committer | Alexis211 <alexis211@gmail.com> | 2009-09-13 18:34:39 +0200 |
commit | 23c20becb3542c7d5fa041ec69902abe8e2c8d64 (patch) | |
tree | fd573796e5f00cf9f61de0a3a392bd790d5d5ac9 /Source | |
parent | c4f0f07dfcb946bfceb80790aa7e5e3ec0647e04 (diff) | |
parent | 668bbfdaea7e8cba8233ebffe2a9d46a66e257cd (diff) | |
download | Melon-23c20becb3542c7d5fa041ec69902abe8e2c8d64.tar.gz Melon-23c20becb3542c7d5fa041ec69902abe8e2c8d64.zip |
Merge branch 'vfs'
Diffstat (limited to 'Source')
24 files changed, 767 insertions, 61 deletions
diff --git a/Source/Kernel/Core/kmain.wtf.cpp b/Source/Kernel/Core/kmain.wtf.cpp index a7bb6e0..808e254 100644 --- a/Source/Kernel/Core/kmain.wtf.cpp +++ b/Source/Kernel/Core/kmain.wtf.cpp @@ -19,6 +19,10 @@ #include <SyscallManager/IDT.ns.h> #include <Library/String.class.h> #include <VFS/Part.ns.h> +#include <FileSystems/RamFS/RamFS.class.h> +#include <VFS/FileNode.class.h> +#include <VFS/VFS.ns.h> +#include <VFS/DirectoryNode.class.h> #include <Ressources/logo.cd> #include <Ressources/keymap-fr.wtf.c> @@ -107,25 +111,84 @@ void kmain(multiboot_info_t* mbd, u32int magic) { PROCESSING(kvt, "Detecting floppy drives..."); FloppyController::detect(); OK(kvt); + FileSystem* fs = new RamFS((u8int*)mods[0].mod_start, 1024 * 1024); + 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<String> 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 [<dir>] shows contents of a directory\n"; + *kvt << " - cd <dir> goes to directory <dir>\n"; + *kvt << " - cat <file> shows contents of file <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 == "reboot") { + } else if (tokens[0] == "reboot") { Sys::reboot(); - } else if (tmp == "devices") { + } 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 << " - FILE\t" << f->getName(); + kvt->setCursorCol(30); + *kvt << (s32int)f->getLength() << " bytes.\n"; + } else if (n->type() == NT_DIRECTORY) { + *kvt << " - DIR\t" << n->getName(); + kvt->setCursorCol(30); + *kvt << (s32int)n->getLength() << " items.\n"; + } + } + } 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<Device*> dev = Dev::findDevices(); *kvt << " - Detected devices :\n"; for (u32int i = 0; i < dev.size(); i++) { @@ -133,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"; @@ -161,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 new file mode 100644 index 0000000..7e29e08 --- /dev/null +++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.cpp @@ -0,0 +1,143 @@ +#include "RamFS.class.h" +#include <VFS/DirectoryNode.class.h> +#include "RamFileNode.class.h" + +RamFS::RamFS(u32int maxSize) { + m_maxSize = maxSize; + m_usedSize = 0; + m_isWritable = true; + m_rootNode = new DirectoryNode("/", this, NULL); +} + +RamFS::RamFS(u8int *ptr, u32int maxSize, bool writable) { + m_maxSize = maxSize; + m_usedSize = 0; + m_isWritable = true; + m_rootNode = new DirectoryNode("/", this, NULL); + + union { + u8int* c; + initrd_header* i; + initrd_file_header* f; + } curr; + curr.c = ptr; + + if (curr.i->magic != INITRD_MAGIC) return; + u32int files = curr.i->files; + curr.i++; //Increment pointer of size of initrd header + DEBUG_HEX(files); DEBUG(" is initrd file count."); + for (u32int i = 0; i < files; i++) { + initrd_file_header h = *(curr.f); + curr.f++; //Increment pointer of size of file header + if (h.name_length != 0 or h.file_length != 0) { + String name((const char*)(curr.c)); + curr.c += h.name_length + 1; //Increment pointer of length of name + + //Find out a vector conaining parent directories, and set name to the effective file name + if (name[0] == WChar("/")) name = name.substr(1, name.size() - 1); + + //Find node for parent directory + String mname = ""; + DirectoryNode* parent = m_rootNode; + for (u32int i = 0; i < name.size(); i++) { + if (name[i] == WChar("/")) { + FSNode* n = parent->getChild(mname); + if (n == NULL) break; + if (n->type() != NT_DIRECTORY) break; + parent = (DirectoryNode*)n; + mname.clear(); + } else { + mname += name[i]; + } + } + name = mname; + + //Add new node + if (h.file_length == 0) { + parent->createDirectory(name); + } else { + FileNode* file = parent->createFile(name); + file->write(0, h.file_length, curr.c); + curr.c += h.file_length; + } + } + } +} + +bool RamFS::setName(FSNode* node, String name) { return true; } +bool RamFS::setPermissions(FSNode* node, u32int permissions) { return true; } +bool RamFS::setUid(FSNode* node, u32int uid) { return true; } +bool RamFS::setGid(FSNode* node, u32int gid) { return true; } +bool RamFS::setParent(FSNode* node, FSNode* parent) { + if (parent->getFS() == this) return true; + return false; +} + +u32int RamFS::read(FileNode* file, u64int position, u32int max_length, u8int *data) { + RamFileNode *node = (RamFileNode*) file; + if (file->getLength() <= position) return 0; + u32int length = file->getLength() - position; + if (length > max_length) length = max_length; + memcpy(data, node->m_data + position, length); + return length; +} + +bool RamFS::write(FileNode* file, u64int position, u32int length, u8int *data) { + if (!m_isWritable) return false; + RamFileNode *node = (RamFileNode*) file; + + u32int end = position + length; + if (end > node->getLength()) { + if (m_usedSize - node->getLength() + end > m_maxSize) return false; + m_usedSize -= node->getLength(); + m_usedSize += end; + + u8int* data = (u8int*)Mem::kalloc(end); + if (data == 0) return false; //Invalid pointer + if (node->m_data != 0) { + memcpy(data, node->m_data, node->getLength()); + Mem::kfree(node->m_data); + } + node->m_data = data; + node->setLength(end); + } + memcpy(node->m_data + position, data, length); + return true; +} + +bool RamFS::truncate(FileNode* file) { + if (!m_isWritable) return false; + RamFileNode *node = (RamFileNode*) file; + + Mem::kfree(node->m_data); + node->setLength(0); + node->m_data = 0; + + return true; +} + +bool RamFS::loadContents(DirectoryNode* dir) { return true; } //Nothing to do. + +FileNode* RamFS::createFile(DirectoryNode* parent, String name) { + if (!m_isWritable) return NULL; + if (parent->getFS() != this) return NULL; + + RamFileNode* n = new RamFileNode(name, this, parent); + parent->loadContent(); + parent->getChildren().push(n); + + return n; +} + +DirectoryNode* RamFS::createDirectory(DirectoryNode* parent, String name) { + if (!m_isWritable) return NULL; + if (parent->getFS() != this) return NULL; + + DirectoryNode* d = new DirectoryNode(name, this, parent); + parent->loadContent(); + parent->getChildren().push(d); + + 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 new file mode 100644 index 0000000..0a3f0c4 --- /dev/null +++ b/Source/Kernel/FileSystems/RamFS/RamFS.class.h @@ -0,0 +1,43 @@ +#ifndef DEF_RAMFS_CLASS_H +#define DEF_RAMFS_CLASS_H + +#include <VFS/FileSystem.proto.h> + +struct initrd_header { + unsigned int magic; + unsigned int files; +}; + +struct initrd_file_header { + unsigned int name_length; + unsigned int file_length; +}; + +#define INITRD_MAGIC 0x1337BEEF + +class RamFS : public FileSystem { + private: + u32int m_maxSize; + u32int m_usedSize; + + public: + RamFS(u32int maxSize); //Creates an empty RAM file system + RamFS(u8int* ptr, u32int maxSize, bool writable = true); //Creates a RAM file system from data loaded in memory. format to be defined + + bool setName(FSNode* node, String name); + bool setPermissions(FSNode* node, u32int permissions); + bool setUid(FSNode* node, u32int uid); + bool setGid(FSNode* node, u32int gid); + bool setParent(FSNode* node, FSNode* parent); + + u32int read(FileNode* file, u64int position, u32int max_length, u8int *data); + bool write(FileNode* file, u64int position, u32int length, u8int *data); + bool truncate(FileNode* file); + + 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 new file mode 100644 index 0000000..d600630 --- /dev/null +++ b/Source/Kernel/FileSystems/RamFS/RamFileNode.class.h @@ -0,0 +1,19 @@ +#ifndef DEF_RAMFILENODE_CLASS_H +#define DEF_RAMFILENODE_CLASS_H + +#include <VFS/FileNode.class.h> + +class RamFileNode : public FileNode { + friend class RamFS; + + private: + RamFileNode (String name, FileSystem* fs, FSNode* parent, u32int permissions = 0777, + u32int uid = 0, u32int gid = 0) : + FileNode(name, fs, parent, 0, permissions, uid, gid), m_data(0) {} + + u8int *m_data; //We don't take care of allocation/freeing here, RamFS:: does that for us + + void setLength(u32int length) { m_length = length; } +}; + +#endif diff --git a/Source/Kernel/Library/String.class.cpp b/Source/Kernel/Library/String.class.cpp index e70d19f..5ee216c 100644 --- a/Source/Kernel/Library/String.class.cpp +++ b/Source/Kernel/Library/String.class.cpp @@ -54,7 +54,7 @@ String::String() { m_length = 0; } -String::String(char* string) { +String::String(const char* string) { m_length = WChar::utf8len(string); if (m_length == 0) { m_string = 0; @@ -100,7 +100,7 @@ void String::operator= (const String &other) { m_string[m_length] = 0; } -void String::operator= (char* string) { +void String::operator= (const char* string) { m_length = WChar::utf8len(string); if (m_string != 0) delete [] m_string; if (m_length == 0) { @@ -116,7 +116,7 @@ void String::operator= (char* string) { m_string[m_length] = 0; } -bool String::operator== (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== (String &other) { return true; } -bool String::operator== (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; @@ -136,7 +136,7 @@ bool String::operator== (char* string) { return true; } -String& String::operator+= (String &other) { +String& String::operator+= (const String &other) { WChar* newdata = new WChar[m_length + other.m_length + 1]; for (u32int i = 0; i < m_length; i++) { newdata[i] = m_string[i]; @@ -151,7 +151,7 @@ String& String::operator+= (String &other) { return *this; } -String& String::operator+= (char* other) { +String& String::operator+= (const char* other) { WChar* newdata = new WChar[m_length + WChar::utf8len(other) + 1]; for (u32int i = 0; i < m_length; i++) { newdata[i] = m_string[i]; @@ -181,22 +181,22 @@ String& String::operator+= (WChar other) { return *this; } -String& String::operator+ (String &other) { //Can be optimized +String& String::operator+ (const String &other) const { //Can be optimized String ret(*this); return (ret += other); } -String& String::operator+ (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; @@ -236,11 +236,11 @@ u32int String::toInt16() { return number; } -WChar& String::operator[] (int index) { +WChar& String::operator[] (int index) const { return m_string[index]; } -u32int String::size() { +u32int String::size() const { return m_length; } @@ -250,11 +250,11 @@ void String::clear() { m_string = 0; } -bool String::empty() { +bool String::empty() const { return (m_length == 0); } -Vector<String> String::split(WChar c) { +Vector<String> String::split(WChar c) const { Vector<String> 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 ecbc2a0..01cc6a8 100644 --- a/Source/Kernel/Library/String.class.h +++ b/Source/Kernel/Library/String.class.h @@ -15,31 +15,33 @@ class String { static String hex(u32int number); static String number(s32int number); - String(char* string); + String(const char* string); String(); String(const String &other); ~String(); void operator= (const String &other); - void operator= (char* string); - - bool operator== (String &other); - bool operator== (char* string); - String &operator+= (String &other); - String &operator+= (char* other); + void 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+ (String &other); - String &operator+ (char* other); - String &operator+ (WChar other); - s32int toInt(); - u32int toInt16(); //From HEX - WChar& operator[] (int index); - - u32int size(); + 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(); + bool empty() const; - Vector<String> split(WChar c); + Vector<String> 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 aaa777f..8b032ca 100644 --- a/Source/Kernel/Library/Vector.class.cpp +++ b/Source/Kernel/Library/Vector.class.cpp @@ -1,22 +1,36 @@ 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 <typename T> Vector<T>::Vector() { + //DEBUG_HEX((u32int)this); DEBUG(" NEW EMPTY"); + //DEBUG_HEX(sizeof(T)); DEBUG(" sizeof(T)"); m_data = 0; m_size = 0; } template <typename T> Vector<T>::Vector(u32int size) { + //DEBUG_HEX((u32int)this); DEBUG(" NEW ZERO"); m_data = new T[size]; m_size = size; } template <typename T> -Vector<T>::Vector(u32int size, T value) { +Vector<T>::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); }*/ @@ -24,16 +38,31 @@ Vector<T>::Vector(u32int size, T value) { template <typename T> Vector<T>::Vector(const Vector<T> &other) { + //DEBUG_HEX((u32int)this); DEBUG(" COPY REF"); + 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]); + } +} + +template <typename T> +Vector<T>& Vector<T>::operator= (const Vector<T> &other) { + //DEBUG_HEX((u32int)this); DEBUG(" COPY EQ"); + 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 <typename T> Vector<T>::~Vector() { - if (m_data != 0) delete[] m_data; + //DEBUG_HEX((u32int)this); DEBUG(" DELETE"); + DELDATA; + //if (m_data != 0) delete[] m_data; } template <typename T> @@ -42,10 +71,13 @@ T& Vector<T>::operator[] (u32int index) { } template <typename T> -void Vector<T>::push(T element) { +void Vector<T>::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; @@ -97,7 +129,7 @@ bool Vector<T>::empty() { template <typename T> void Vector<T>::clear() { if (empty()) return; - Mem::kfree(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 9763d2c..ca86c2a 100644 --- a/Source/Kernel/Library/Vector.class.h +++ b/Source/Kernel/Library/Vector.class.h @@ -12,13 +12,14 @@ class Vector { public: Vector(); Vector(u32int size); - Vector(u32int size, T value); + Vector(u32int size, const T& value); Vector(const Vector<T> &other); + Vector<T>& operator= (const Vector<T> &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/Library/WChar.class.cpp b/Source/Kernel/Library/WChar.class.cpp index c1a1977..bb1269d 100644 --- a/Source/Kernel/Library/WChar.class.cpp +++ b/Source/Kernel/Library/WChar.class.cpp @@ -19,11 +19,11 @@ WChar::WChar(char c) { affectAscii(c); } -WChar::WChar(char* c) { +WChar::WChar(const char* c) { affectUtf8(c); } -u32int WChar::utf8len(char* c) { +u32int WChar::utf8len(const char* c) { int i = 0, l = CMem::strlen(c), co = 0; while (i < l) { if ((c[i] & 0x80) == 0) i += 1; @@ -41,7 +41,7 @@ void WChar::affectAscii(char c) { else value = CP437[c + 128]; } -u32int WChar::affectUtf8(char* c) { //Returns the number of bytes for the character +u32int WChar::affectUtf8(const char* c) { //Returns the number of bytes for the character /*if ((c[0] & 0xB0) == 0x80) { //11000000b == 10000000b, means we are IN a sequence value = 0; return 1; diff --git a/Source/Kernel/Library/WChar.class.h b/Source/Kernel/Library/WChar.class.h index c582017..9ddccd1 100644 --- a/Source/Kernel/Library/WChar.class.h +++ b/Source/Kernel/Library/WChar.class.h @@ -9,14 +9,14 @@ struct WChar { WChar(); //Creates a null character WChar(char c); //From ascii character - WChar(char* c); //From utf8 string + WChar(const char* c); //From utf8 string - static u32int utf8len(char* c); //Returns count of utf8 characters in string + static u32int utf8len(const char* c); //Returns count of utf8 characters in string void affectAscii(char c); - u32int affectUtf8(char* c); - void affectUtf16(char* c); - void affectUtf32(char* c); + u32int affectUtf8(const char* c); + void affectUtf16(const char* c); + void affectUtf32(const char* c); u8int toAscii(); inline WChar operator+ (u32int other) { diff --git a/Source/Kernel/Makefile b/Source/Kernel/Makefile index e0f2068..79dfbb3 100644 --- a/Source/Kernel/Makefile +++ b/Source/Kernel/Makefile @@ -38,6 +38,9 @@ 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 \ Devices/Display/VGATextOutput.class.o \ diff --git a/Source/Kernel/Melon.ke b/Source/Kernel/Melon.ke Binary files differindex 552d00c..418c1a8 100755 --- a/Source/Kernel/Melon.ke +++ b/Source/Kernel/Melon.ke diff --git a/Source/Kernel/Ressources/Welcome.txt b/Source/Kernel/Ressources/Welcome.txt new file mode 100644 index 0000000..97d6755 --- /dev/null +++ b/Source/Kernel/Ressources/Welcome.txt @@ -0,0 +1 @@ +Hi, this is a file located on an InitRD ! éàç... 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 new file mode 100644 index 0000000..5de523e --- /dev/null +++ b/Source/Kernel/VFS/DirectoryNode.class.h @@ -0,0 +1,31 @@ +#ifndef DEF_DIRECTORYNODE_CLASS_H +#define DEF_DIRECTORYNODE_CLASS_H + +#include <VFS/FileNode.class.h> +#include <Library/Vector.class.h> + +class DirectoryNode : public FSNode { + protected: + Vector<FSNode*> m_children; + bool m_contentLoaded; + + public: + 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<FSNode*> &getChildren() { return m_children; } //MUST BE USED ONLY BY FILESYSTEMS + + u8int type() { return NT_DIRECTORY; } + 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 new file mode 100644 index 0000000..bcf9393 --- /dev/null +++ b/Source/Kernel/VFS/FSNode.proto.h @@ -0,0 +1,70 @@ +#ifndef DEF_FSNODE_PROTO_H +#define DEF_FSNODE_PROTO_H + +#include <Core/common.wtf.h> +#include <Library/String.class.h> +class FSNode; +#include <VFS/FileSystem.proto.h> + +enum { + NT_FILE = 1, + NT_DIRECTORY = 2, + NT_SYMLINK = 3, + NT_MOUNTPOINT = 4 +}; + +class FSNode { + protected: + String m_name; + u32int 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, + 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) {} + 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; } + u32int getPermissions() { return m_permissions; } + u32int getUid() { return m_uid; } + u32int getGid() { return m_gid; } + FileSystem *getFS() { return m_fs; } + FSNode* getParent() { return m_parent; } + + public: + bool setName(String name) { + bool b = m_fs->setName(this, name); + if (b) m_name = name; + return b; + } + bool setPermissions(u32int permissions) { + bool b = m_fs->setPermissions(this, permissions); + if (b) m_permissions = permissions; + return b; + } + bool setUid(u32int uid) { + bool b = m_fs->setUid(this, uid); + if (b) m_uid = uid; + return b; + } + bool setGid(u32int gid) { + bool b = m_fs->setGid(this, gid); + if (b) m_gid = gid; + return b; + } + bool setParent(FSNode* parent) { + bool b = m_fs->setParent(this, parent); //FSSetParent is only expected to move files/directories in the same filesystem + if (b) m_parent = parent; + return b; + } +}; + +#endif diff --git a/Source/Kernel/VFS/FileNode.class.h b/Source/Kernel/VFS/FileNode.class.h new file mode 100644 index 0000000..b3a3f67 --- /dev/null +++ b/Source/Kernel/VFS/FileNode.class.h @@ -0,0 +1,31 @@ +#ifndef DEF_FILENODE_CLASS_H +#define DEF_FILENODE_CLASS_H + +#include <VFS/FSNode.proto.h> + +class FileNode : public FSNode { + protected: + 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) {} + + 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); + } + + bool write(u64int position, u32int length, u8int *data) { + return m_fs->write(this, position, length, data); + } + + bool truncate() { + return m_fs->truncate(this); + } + +}; + +#endif diff --git a/Source/Kernel/VFS/FileSystem.proto.h b/Source/Kernel/VFS/FileSystem.proto.h new file mode 100644 index 0000000..2f768a7 --- /dev/null +++ b/Source/Kernel/VFS/FileSystem.proto.h @@ -0,0 +1,36 @@ +#ifndef DEF_FILESYSTEM_PROTO_H +#define DEF_FILESYSTEM_PROTO_H + +#include <VFS/Partition.class.h> +class FSNode; +class FileNode; +class DirectoryNode; + +//This abstract class describes a filesystem +class FileSystem { + protected: + bool m_isWritable; //false = read only + DirectoryNode* m_rootNode; + + public: + bool isWritable() { return m_isWritable; } + DirectoryNode* getRootNode() { return m_rootNode; } + + //Must be implemented by the filesystem + virtual bool setName(FSNode* node, String name) = 0; + virtual bool setPermissions(FSNode* node, u32int permissions) = 0; + virtual bool setUid(FSNode* node, u32int uid) = 0; + virtual bool setGid(FSNode* node, u32int gid) = 0; + virtual bool setParent(FSNode* node, FSNode* parent) = 0; + + virtual u32int read(FileNode* file, u64int position, u32int max_length, u8int *data) = 0; + virtual bool write(FileNode* file, u64int position, u32int length, u8int *data) = 0; + virtual bool truncate(FileNode* file) = 0; + + 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 new file mode 100644 index 0000000..1021d7c --- /dev/null +++ b/Source/Kernel/VFS/VFS.ns.h @@ -0,0 +1,22 @@ +#ifndef DEF_VFS_NS_H +#define DEF_VFS_NS_H + +#include <VFS/DirectoryNode.class.h> +#include <VFS/FileSystem.proto.h> + +typedef FileSystem* (* mountcallback)(Partition* partition); + +namespace VFS { + void registerMountCallback(mountcallback mcb); + 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 diff --git a/Source/Kernel/VTManager/VirtualTerminal.class.cpp b/Source/Kernel/VTManager/VirtualTerminal.class.cpp index dde487c..be1299c 100644 --- a/Source/Kernel/VTManager/VirtualTerminal.class.cpp +++ b/Source/Kernel/VTManager/VirtualTerminal.class.cpp @@ -129,7 +129,7 @@ void VirtualTerminal::put(WChar c, bool updatecsr) { if (updatecsr) updateCursor(); } -void VirtualTerminal::write(String s, bool updatecsr) { +void VirtualTerminal::write(const String& s, bool updatecsr) { for (u32int i = 0; i < s.size(); i++) { put(s[i], false); } diff --git a/Source/Kernel/VTManager/VirtualTerminal.class.h b/Source/Kernel/VTManager/VirtualTerminal.class.h index 62aa650..6bdcf84 100644 --- a/Source/Kernel/VTManager/VirtualTerminal.class.h +++ b/Source/Kernel/VTManager/VirtualTerminal.class.h @@ -46,13 +46,13 @@ class VirtualTerminal { //Display functions void put(WChar c, bool updatecsr = true); - void write(String s, bool updatecsr = true); + void write(const String& s, bool updatecsr = true); void writeDec(s32int i, bool updatecsr = true); void writeHex(u32int i, bool updatecsr = true); void hexDump(u8int* ptr, u32int sz); - inline VirtualTerminal& operator<<(String s) { write(s); return *this; } + inline VirtualTerminal& operator<<(const String& s) { write(s); return *this; } //inline VirtualTerminal& operator<<(WChar c) { put(c); return *this; } inline VirtualTerminal& operator<<(s32int i) { writeDec(i); return *this; } inline VirtualTerminal& operator<<(u32int i) { writeHex(i); return *this; } diff --git a/Source/Tools/MakeRamFS/MakeRamFS b/Source/Tools/MakeRamFS/MakeRamFS Binary files differnew file mode 100755 index 0000000..be1dc1a --- /dev/null +++ b/Source/Tools/MakeRamFS/MakeRamFS diff --git a/Source/Tools/MakeRamFS/Makefile b/Source/Tools/MakeRamFS/Makefile new file mode 100644 index 0000000..019ec29 --- /dev/null +++ b/Source/Tools/MakeRamFS/Makefile @@ -0,0 +1,38 @@ +.PHONY: clean, mrproper + +CC = gcc +CXX = g++ +LD = gcc +LDFLAGS = -lstdc++ +CFLAGS = +CXXFLAGS = + +OutFile = MakeRamFS +Objects = main.o + +all: $(OutFile) + echo "* Done with $(OutFile)." + +rebuild: mrproper all + +$(OutFile): $(Objects) + echo "* Linking executable : $(OutFile)..." + $(LD) -o $(OutFile) $(LDFLAGS) $^ + +%.o: %.c + echo "* Compiling $<..." + $(CC) -c $< -o $@ $(CFLAGS) + +%.o: %.cpp + echo "* Compiling $<..." + $(CXX) -c $< -o $@ $(CXXFLAGS) + +clean: + echo "* Removing object files..." + rm -rf *.o + rm -rf */*.o + rm -rf */*/*.o + +mrproper: clean + echo "* Removing executable : $(OutFile)" + rm -rf $(OutFile) diff --git a/Source/Tools/MakeRamFS/main.cpp b/Source/Tools/MakeRamFS/main.cpp new file mode 100644 index 0000000..dcb2a2b --- /dev/null +++ b/Source/Tools/MakeRamFS/main.cpp @@ -0,0 +1,95 @@ +#include <iostream> +#include <fstream> +#include <string> + +using namespace std; + +struct ramfs_header { + unsigned int magic; //For error checking + unsigned int files; +}; + +struct ramfs_file_header { + unsigned int name_length; + unsigned int file_length; +}; + +#define INITRD_MAGIC 0x1337BEEF + +int main(int argc, char *argv[]) { + if (argc < 2) { + cerr << "Error : no output file specified." << endl; + cerr << "Usage : MakeRamFS <output.img> [<filename>:<ramfs filename> [...] ]" << endl; + return 1; + } + + ofstream output(argv[1], ios::out | ios::binary); + + ramfs_header hdr; + hdr.magic = INITRD_MAGIC; + hdr.files = argc - 2; + + output.write((char*)&hdr, sizeof(ramfs_header)); + + for (int i = 2; i < argc; i++) { + string name(argv[i]); + string file; + while (!name.empty()) { + if (name[0] == ':') { + name = name.substr(1, name.size() - 1); + break; + } + file += name[0]; + name = name.substr(1, name.size() - 1); + } + + ramfs_file_header fhdr; + + if (file == "") { //This is a directory + fhdr.name_length = name.size(); + fhdr.file_length = 0; //File length of 0 means directory + output.write((char*)&fhdr, sizeof(ramfs_file_header)); + output << name; + output << '\0'; + continue; + } + + ifstream infile(file.c_str(), ios::in | ios::binary); + + if (!infile) { + fhdr.name_length = 0; //Name and length = 0 means invalid file + fhdr.file_length = 0; + output.write((char*)&fhdr, sizeof(ramfs_file_header)); + continue; + } + + fhdr.name_length = name.size(); + fhdr.file_length = 0; + while (!infile.eof()) { + char c; + infile.read(&c, 1); + fhdr.file_length++; + } + + infile.close(); infile.open(file.c_str(), ios::in | ios::binary); //Rewind file + + output.write((char*)&fhdr, sizeof(ramfs_file_header)); + + output << name; + output << '\0'; + + char *c = new char[fhdr.file_length]; + for (int i = 0; i < fhdr.file_length; i++) { + char ch; + infile.read(&ch, 1); + output.write(&ch, 1); + } + delete [] c; + + infile.close(); + } + + output.close(); + + return 0; +} |