diff --git a/e2fs b/e2fs new file mode 100644 index 0000000..ad150ba Binary files /dev/null and b/e2fs differ diff --git a/initrd/link b/initrd/link new file mode 120000 index 0000000..e9b09f3 --- /dev/null +++ b/initrd/link @@ -0,0 +1 @@ +test_file \ No newline at end of file diff --git a/kernel/Makefile b/kernel/Makefile index 3e7e822..78110af 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -12,7 +12,7 @@ CPPFLAGS=-fleading-underscore -fno-builtin -nostdlib -nostartfiles -nodefaultlib # -S -masm=intel CC=gcc CXX=g++ -CXXFLAGS=-fno-rtti -fno-exceptions +CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_ # Linker Information: LD=ld @@ -27,7 +27,8 @@ OBJS=boot.o lang/lang_a.o \ devices.o block/ramdisk.o fs/vfs.o fs/FileSystem.o fs/VFSMount.o \ fs/ext2/ext2.o fs/sysfs/sysfs.o fs/sysfs/sysfs_entry.o \ sys/pci.o fs/OpenFile.o fs/OpenDirectory.o \ - fs/ext2/Ext2OpenDirectory.o fs/ext2/Ext2OpenFile.o + fs/ext2/Ext2OpenDirectory.o fs/ext2/Ext2OpenFile.o \ + fs/ext2/Ext2BlockCache.o CSRC=kernel.c mm/mm.c mm/vmm.c lang/conv.c display/kout.c \ display/display.c sys/pic.c char/keyboard.c lang/lang.c \ sys/pci_classes.c @@ -36,7 +37,7 @@ CXXSRC=lang/string.cpp lang/new.cpp char/misc_char.cpp char/vconsole.cpp \ fs/ext2/ext2.cpp fs/sysfs/sysfs.cpp fs/sysfs/sysfs_entry.cpp \ sys/pci.cpp proc/proc.cpp proc/hash.cpp fs/OpenFile.cpp \ fs/OpenDirectory.cpp fs/ext2/Ext2OpenDirectory.cpp \ - fs/ext2/Ext2OpenFile.cpp + fs/ext2/Ext2OpenFile.cpp fs/ext2/Ext2BlockCache.cpp .PHONY: all depend clean html @@ -94,15 +95,16 @@ block/ramdisk.o: lang/lang.h block/ramdisk.h devices.h devices.o: hos_defines.h devices.h char/misc_char.h char/misc_char.h devices.o: char/vconsole.h block/ramdisk.h fs/vfs.o: hos_defines.h display/kout.h functions.h sys/io.h lang/lang.h -fs/vfs.o: fs/vfs.h devices.h lang/string.h lang/vector.h fs/FileSystem.h -fs/vfs.o: fs/OpenFile.h fs/OpenDirectory.h fs/VFSMount.h fs/FileSystem.h -fs/vfs.o: fs/vfs.h fs/ext2/ext2.h +fs/vfs.o: fs/vfs.h devices.h fs/FileSystem.h fs/OpenDirectory.h fs/OpenFile.h +fs/vfs.o: lang/string.h fs/VFSMount.h fs/FileSystem.h fs/ext2/ext2.h fs/vfs.h +fs/vfs.o: lang/vector.h fs/ext2/ext2.o: display/kout.h hos_defines.h mm/vmm.h multiboot.h lang/lang.h -fs/ext2/ext2.o: fs/ext2/ext2.h fs/vfs.h devices.h +fs/ext2/ext2.o: fs/ext2/ext2.h fs/vfs.h devices.h fs/ext2/Ext2OpenDirectory.h +fs/ext2/ext2.o: fs/OpenDirectory.h fs/vfs.h fs/OpenFile.h lang/string.h +fs/ext2/ext2.o: fs/ext2/Ext2OpenFile.h fs/OpenFile.h fs/sysfs/sysfs.o: display/kout.h hos_defines.h fs/vfs.h devices.h -fs/sysfs/sysfs.o: fs/sysfs/sysfs.h fs/FileSystem.h fs/OpenFile.h -fs/sysfs/sysfs.o: fs/OpenDirectory.h fs/vfs.h lang/string.h lang/vector.h -fs/sysfs/sysfs.o: fs/VFSMount.h fs/FileSystem.h fs/sysfs/sysfs_entry.h +fs/sysfs/sysfs.o: fs/sysfs/sysfs.h fs/sysfs/sysfs_entry.h lang/vector.h +fs/sysfs/sysfs.o: lang/string.h fs/sysfs/sysfs_entry.o: fs/sysfs/sysfs_entry.h lang/vector.h hos_defines.h fs/sysfs/sysfs_entry.o: lang/string.h sys/pci.o: hos_defines.h display/kout.h sys/io.h sys/pci.h lang/vector.h @@ -112,6 +114,9 @@ proc/proc.o: lang/vector.h proc/hash.o: hos_defines.h proc/hash.h lang/vector.h display/kout.h mm/vmm.h proc/hash.o: multiboot.h fs/OpenFile.o: fs/OpenFile.h hos_defines.h -fs/OpenDirectory.o: fs/OpenDirectory.h fs/vfs.h hos_defines.h devices.h -fs/OpenDirectory.o: lang/string.h lang/vector.h fs/FileSystem.h fs/OpenFile.h -fs/OpenDirectory.o: fs/VFSMount.h fs/FileSystem.h fs/vfs.h +fs/OpenDirectory.o: fs/vfs.h hos_defines.h devices.h fs/OpenDirectory.h +fs/OpenDirectory.o: fs/OpenFile.h lang/string.h +fs/ext2/Ext2OpenDirectory.o: display/kout.h hos_defines.h lang/lang.h +fs/ext2/Ext2OpenDirectory.o: fs/vfs.h devices.h fs/ext2/Ext2OpenDirectory.h +fs/ext2/Ext2OpenDirectory.o: fs/OpenDirectory.h fs/vfs.h fs/OpenFile.h +fs/ext2/Ext2OpenDirectory.o: lang/string.h fs/ext2/ext2.h diff --git a/kernel/Makefile.bak b/kernel/Makefile.bak index e0cb323..55f81ef 100644 --- a/kernel/Makefile.bak +++ b/kernel/Makefile.bak @@ -12,7 +12,7 @@ CPPFLAGS=-fleading-underscore -fno-builtin -nostdlib -nostartfiles -nodefaultlib # -S -masm=intel CC=gcc CXX=g++ -CXXFLAGS=-fno-rtti -fno-exceptions +CXXFLAGS=-fno-rtti -fno-exceptions -D_HOS_CPP_ # Linker Information: LD=ld @@ -27,7 +27,8 @@ OBJS=boot.o lang/lang_a.o \ devices.o block/ramdisk.o fs/vfs.o fs/FileSystem.o fs/VFSMount.o \ fs/ext2/ext2.o fs/sysfs/sysfs.o fs/sysfs/sysfs_entry.o \ sys/pci.o fs/OpenFile.o fs/OpenDirectory.o \ - fs/ext2/Ext2OpenDirectory.o fs/ext2/Ext2OpenFile.o + fs/ext2/Ext2OpenDirectory.o fs/ext2/Ext2OpenFile.o \ + fs/ext2/Ext2BlockCache.o CSRC=kernel.c mm/mm.c mm/vmm.c lang/conv.c display/kout.c \ display/display.c sys/pic.c char/keyboard.c lang/lang.c \ sys/pci_classes.c @@ -36,7 +37,7 @@ CXXSRC=lang/string.cpp lang/new.cpp char/misc_char.cpp char/vconsole.cpp \ fs/ext2/ext2.cpp fs/sysfs/sysfs.cpp fs/sysfs/sysfs_entry.cpp \ sys/pci.cpp proc/proc.cpp proc/hash.cpp fs/OpenFile.cpp \ fs/OpenDirectory.cpp fs/ext2/Ext2OpenDirectory.cpp \ - fs/ext2/Ext2OpenFile.cpp + fs/ext2/Ext2OpenFile.cpp fs/ext2/Ext2BlockCache.cpp .PHONY: all depend clean html @@ -93,16 +94,16 @@ block/ramdisk.o: functions.h hos_defines.h sys/io.h mm/vmm.h multiboot.h block/ramdisk.o: lang/lang.h block/ramdisk.h devices.h devices.o: hos_defines.h devices.h char/misc_char.h char/misc_char.h devices.o: char/vconsole.h block/ramdisk.h -fs/vfs.o: hos_defines.h display/kout.h functions.h sys/io.h fs/vfs.h -fs/vfs.o: devices.h lang/string.h fs/FileSystem.h fs/OpenFile.h -fs/vfs.o: fs/OpenDirectory.h fs/VFSMount.h fs/FileSystem.h fs/vfs.h -fs/vfs.o: fs/ext2/ext2.h lang/vector.h +fs/vfs.o: hos_defines.h display/kout.h functions.h sys/io.h lang/lang.h +fs/vfs.o: fs/vfs.h devices.h lang/string.h lang/vector.h fs/FileSystem.h +fs/vfs.o: fs/OpenFile.h fs/OpenDirectory.h fs/VFSMount.h fs/FileSystem.h +fs/vfs.o: fs/vfs.h fs/ext2/ext2.h fs/ext2/ext2.o: display/kout.h hos_defines.h mm/vmm.h multiboot.h lang/lang.h fs/ext2/ext2.o: fs/ext2/ext2.h fs/vfs.h devices.h fs/sysfs/sysfs.o: display/kout.h hos_defines.h fs/vfs.h devices.h fs/sysfs/sysfs.o: fs/sysfs/sysfs.h fs/FileSystem.h fs/OpenFile.h -fs/sysfs/sysfs.o: fs/OpenDirectory.h fs/vfs.h lang/string.h fs/VFSMount.h -fs/sysfs/sysfs.o: fs/FileSystem.h lang/vector.h fs/sysfs/sysfs_entry.h +fs/sysfs/sysfs.o: fs/OpenDirectory.h fs/vfs.h lang/string.h lang/vector.h +fs/sysfs/sysfs.o: fs/VFSMount.h fs/FileSystem.h fs/sysfs/sysfs_entry.h fs/sysfs/sysfs_entry.o: fs/sysfs/sysfs_entry.h lang/vector.h hos_defines.h fs/sysfs/sysfs_entry.o: lang/string.h sys/pci.o: hos_defines.h display/kout.h sys/io.h sys/pci.h lang/vector.h @@ -111,7 +112,7 @@ proc/proc.o: functions.h sys/io.h display/kout.h proc/proc.h proc/hash.h proc/proc.o: lang/vector.h proc/hash.o: hos_defines.h proc/hash.h lang/vector.h display/kout.h mm/vmm.h proc/hash.o: multiboot.h -fs/OpenFile.o: fs/OpenFile.h +fs/OpenFile.o: fs/OpenFile.h hos_defines.h fs/OpenDirectory.o: fs/OpenDirectory.h fs/vfs.h hos_defines.h devices.h -fs/OpenDirectory.o: lang/string.h fs/FileSystem.h fs/OpenFile.h fs/VFSMount.h -fs/OpenDirectory.o: fs/FileSystem.h fs/vfs.h +fs/OpenDirectory.o: lang/string.h lang/vector.h fs/FileSystem.h fs/OpenFile.h +fs/OpenDirectory.o: fs/VFSMount.h fs/FileSystem.h fs/vfs.h diff --git a/kernel/block/ramdisk.cpp b/kernel/block/ramdisk.cpp index d2e5b37..31582e2 100644 --- a/kernel/block/ramdisk.cpp +++ b/kernel/block/ramdisk.cpp @@ -3,8 +3,6 @@ // Date: 08/20/04 // Modified: 05/11/05 -#define _HOS_CPP_ _HOS_CPP_ - extern "C" { #include "functions.h" diff --git a/kernel/char/misc_char.cpp b/kernel/char/misc_char.cpp index 5111bdd..c95dd94 100644 --- a/kernel/char/misc_char.cpp +++ b/kernel/char/misc_char.cpp @@ -4,8 +4,6 @@ // Date: 05/11/05 // Modified: 05/11/05 -#define _HOS_CPP_ _HOS_CPP_ - #include "hos_defines.h" #include "devices.h" #include "misc_char.h" diff --git a/kernel/char/vconsole.cpp b/kernel/char/vconsole.cpp index bd911bb..4f85153 100644 --- a/kernel/char/vconsole.cpp +++ b/kernel/char/vconsole.cpp @@ -3,8 +3,6 @@ // Date: 08/02/04 // Modified: 05/11/05 -#define _HOS_CPP_ _HOS_CPP_ - extern "C" { #include "hos_defines.h" diff --git a/kernel/devices.cpp b/kernel/devices.cpp index a26e783..f982f26 100644 --- a/kernel/devices.cpp +++ b/kernel/devices.cpp @@ -4,8 +4,6 @@ // Date: 05/11/05 // Modified: 05/11/05 -#define _HOS_CPP_ _HOS_CPP_ - #include "hos_defines.h" #include "devices.h" #include "char/misc_char.h" diff --git a/kernel/fs/FileSystem.cpp b/kernel/fs/FileSystem.cpp index f327771..df1ddbc 100644 --- a/kernel/fs/FileSystem.cpp +++ b/kernel/fs/FileSystem.cpp @@ -4,19 +4,18 @@ // Date: 06/21/05 // Modified: 06/21/05 +#include "vfs.h" #include "FileSystem.h" -#include "OpenFile.h" -#include "OpenDirectory.h" -#include "hos_defines.h" FileSystem::FileSystem() {} FileSystem::~FileSystem() {} u32_t FileSystem::totalBlocks() {return 0;} -u32_t FileSystem::freeBlocks() {return 0;}; -u32_t FileSystem::totalInodes() {return 0;}; -u32_t FileSystem::freeInodes() {return 0;}; -u32_t FileSystem::getRootInodeNumber() {return 0;}; +u32_t FileSystem::freeBlocks() {return 0;} +u32_t FileSystem::totalInodes() {return 0;} +u32_t FileSystem::freeInodes() {return 0;} +u32_t FileSystem::getRootInodeNumber() {return 0;} -OpenFile *FileSystem::openFile(u32_t inum) {return NULL;}; -OpenDirectory *FileSystem::openDirectory(u32_t inum) {return NULL;}; -int FileSystem::stat(u32_t inum, vfs_stat_t *buf) {return -1;}; +OpenDirectory *FileSystem::openDirectory(u32_t inum, int mode) {return NULL;} +OpenFile *FileSystem::openFile(u32_t inum, int mode) {return NULL;} +int FileSystem::stat(u32_t inum, vfs_stat_t *buf) {return -1;} +int FileSystem::link_deref(u32_t inum, char *buf) {return -1;} diff --git a/kernel/fs/FileSystem.h b/kernel/fs/FileSystem.h index 7637d36..3ff010f 100644 --- a/kernel/fs/FileSystem.h +++ b/kernel/fs/FileSystem.h @@ -8,8 +8,9 @@ #define __HOS_FILESYSTEM__ __HOS_FILESYSTEM__ #include "hos_defines.h" -#include "OpenFile.h" +#include "vfs.h" #include "OpenDirectory.h" +#include "OpenFile.h" class FileSystem { @@ -25,9 +26,10 @@ public: virtual u32_t getRootInodeNumber(); - virtual OpenFile *openFile(u32_t inum); - virtual OpenDirectory *openDirectory(u32_t inum); + virtual OpenDirectory *openDirectory(u32_t inum, int mode); + virtual OpenFile *openFile(u32_t inum, int mode); virtual int stat(u32_t inum, vfs_stat_t *buf); + virtual int link_deref(u32_t inum, char *buf); }; #endif diff --git a/kernel/fs/OpenDirectory.cpp b/kernel/fs/OpenDirectory.cpp index 1fe9995..0b207fb 100644 --- a/kernel/fs/OpenDirectory.cpp +++ b/kernel/fs/OpenDirectory.cpp @@ -2,10 +2,14 @@ // Author: Josh Holtrop // Date: 12/19/05 +#include "vfs.h" #include "OpenDirectory.h" +#include "lang/string.h" OpenDirectory::OpenDirectory() {} OpenDirectory::~OpenDirectory() {} int OpenDirectory::seek(int pos, int mode) { return -1; } int OpenDirectory::read(vfs_dir_entry_t *ent) { return -1; } -int OpenDirectory::write(vfs_dir_entry_t *ent) { return -1; } +int OpenDirectory::create(char *name, int mode, u32_t permissions, u32_t dev) + { return -1; } +int OpenDirectory::unlink(char *name) { return -1; } diff --git a/kernel/fs/OpenDirectory.h b/kernel/fs/OpenDirectory.h index b05e126..b1fbda3 100644 --- a/kernel/fs/OpenDirectory.h +++ b/kernel/fs/OpenDirectory.h @@ -6,6 +6,7 @@ #define __HOS_OPENDIRECTORY_H__ __HOS_OPENDIRECTORY_H__ #include "vfs.h" +#include "lang/string.h" class OpenDirectory { @@ -14,7 +15,8 @@ public: virtual ~OpenDirectory(); virtual int seek(int pos, int mode); virtual int read(vfs_dir_entry_t *ent); - virtual int write(vfs_dir_entry_t *ent); + virtual int create(char *name, int mode, u32_t permissions, u32_t dev); + virtual int unlink(char *name); }; #endif diff --git a/kernel/fs/OpenFile.cpp b/kernel/fs/OpenFile.cpp index 2b2f521..6975a92 100644 --- a/kernel/fs/OpenFile.cpp +++ b/kernel/fs/OpenFile.cpp @@ -3,3 +3,11 @@ // Date: 12/19/05 #include "OpenFile.h" + +OpenFile::OpenFile() {} +OpenFile::~OpenFile() {} +int OpenFile::seek(int pos, int mode) { return -1; } +int OpenFile::read() { return -1; } +int OpenFile::read(void *buf, u32_t num) { return -1; } +int OpenFile::write(int chr) { return -1; } +int OpenFile::write(void *ptr, u32_t num) { return -1; } diff --git a/kernel/fs/VFSMount.cpp b/kernel/fs/VFSMount.cpp index 9b19dd8..54297d0 100644 --- a/kernel/fs/VFSMount.cpp +++ b/kernel/fs/VFSMount.cpp @@ -8,11 +8,11 @@ extern "C" { #include "display/kout.h" } +#include "vfs.h" #include "VFSMount.h" #include "hos_defines.h" #include "devices.h" #include "lang/string.h" -#include "fs/vfs.h" VFSMount::VFSMount(device_t dev, string fsType, FileSystem *fs, string mountPoint, diff --git a/kernel/fs/VFSMount.h b/kernel/fs/VFSMount.h index 7d327d4..869c0a7 100644 --- a/kernel/fs/VFSMount.h +++ b/kernel/fs/VFSMount.h @@ -10,7 +10,6 @@ #include "lang/string.h" #include "devices.h" #include "FileSystem.h" -#include "fs/vfs.h" class VFSMount { diff --git a/kernel/fs/ext2/Ext2BlockCache.cpp b/kernel/fs/ext2/Ext2BlockCache.cpp new file mode 100644 index 0000000..6490442 --- /dev/null +++ b/kernel/fs/ext2/Ext2BlockCache.cpp @@ -0,0 +1,147 @@ +// Ext2BlockCache.cpp +// Author: Josh Holtrop +// Date: 12/29/05 +// Modified: 12/29/05 + +#include "fs/vfs.h" +#include "Ext2BlockCache.h" + +extern "C" { +#include "display/kout.h" +} + +Ext2BlockCache::Ext2BlockCache(Ext2fs *fs, u32_t inum) +{ + myFS = fs; + myInum = inum; + myInodeDirty = 0; + fs->readInode(inum, &myInode); + myBlockSize = 1024 << fs->getSuper()->s_log_block_size; + for (int i = 0; i < 3; i++) + { + myCache[i] = new u8_t[myBlockSize]; + myCacheAddress[i] = 0; + myCacheDirty[i] = 0; + } +} + +Ext2BlockCache::~Ext2BlockCache() +{ + for (int i = 0; i < 3; i++) + { + if (myCacheDirty[i]) + myFS->writeBlock(myCacheAddress[i], myCache[i]); + delete[] myCache[i]; + } + if (myInodeDirty) + myFS->writeInode(myInum, &myInode); +} + +int Ext2BlockCache::readBlock(u32_t blockNum, void *buf) +{ + u32_t fsblock = getFSBlock(blockNum, 0); + if (fsblock == 0) + return -1; + return myFS->readBlock(fsblock, buf); +} + +int Ext2BlockCache::writeBlock(u32_t blockNum, void *buf) +{ + u32_t fsblock = getFSBlock(blockNum, 1); + if (fsblock == 0) + return -1; + return myFS->writeBlock(fsblock, buf); +} + +void Ext2BlockCache::setCache(u32_t level, u32_t fsblock) +{ + if (myCacheAddress[level] == fsblock) + return; + if (myCacheDirty[level]) + myFS->writeBlock(myCacheAddress[level], myCache[level]); + myCacheAddress[level] = fsblock; + myCacheDirty[level] = 0; + myFS->readBlock(fsblock, myCache[level]); +} + +u32_t Ext2BlockCache::getFSBlock(u32_t blockNum, int create) +{ + if (blockNum < 12) /* direct pointer */ + { + if (create && myInode.i_block[blockNum] == 0) + { + myInode.i_block[blockNum] = myFS->allocBlock(); + myInodeDirty = 1; + } + return myInode.i_block[blockNum]; + } + blockNum -= 12; + if (blockNum < myBlockSize) /* i_block[12] */ + { + if (create && myInode.i_block[12] == 0) + { + myInode.i_block[12] = myFS->allocBlock(); + myInodeDirty = 1; + } + setCache(0, myInode.i_block[12]); + /* blockNum indexes cache 0 */ + if (create && myCache[0][blockNum] == 0) + { + myCache[0][blockNum] = myFS->allocBlock(); + myCacheDirty[0] = 1; + } + return myCache[0][blockNum]; + } + blockNum -= myBlockSize; + if (blockNum < (myBlockSize * myBlockSize)) /* i_block[13] */ + { + if (create && myInode.i_block[13] == 0) + { + myInode.i_block[13] = myFS->allocBlock(); + myInodeDirty = 1; + } + setCache(0, myInode.i_block[13]); + /* blockNum / myBlockSize indexes cache 0 */ + if (create && myCache[0][blockNum / myBlockSize] == 0) + { + myCache[0][blockNum / myBlockSize] = myFS->allocBlock(); + myCacheDirty[0] = 1; + } + setCache(1, myCache[0][blockNum / myBlockSize]); + /* blockNum % myBlockSize indexes cache 1 */ + if (create && myCache[1][blockNum % myBlockSize] == 0) + { + myCache[1][blockNum % myBlockSize] = myFS->allocBlock(); + myCacheDirty[1] = 1; + } + return myCache[1][blockNum % myBlockSize]; + } + blockNum -= (myBlockSize * myBlockSize); /* i_block[14] */ + if (create && myInode.i_block[14] == 0) + { + myInode.i_block[14] = myFS->allocBlock(); + myInodeDirty = 1; + } + setCache(0, myInode.i_block[14]); + /* blockNum / (myBlockSize^2) indexes cache 0 */ + if (create && myCache[0][blockNum / (myBlockSize * myBlockSize)] == 0) + { + myCache[0][blockNum / (myBlockSize * myBlockSize)] = myFS->allocBlock(); + myCacheDirty[0] = 1; + } + setCache(1, myCache[0][blockNum / (myBlockSize * myBlockSize)]); + /* blockNum / myBlockSize indexes cache 1 */ + if (create && myCache[1][blockNum / myBlockSize] == 0) + { + myCache[1][blockNum / myBlockSize] = myFS->allocBlock(); + myCacheDirty[1] = 1; + } + setCache(2, myCache[1][blockNum / myBlockSize]); + /* blockNum % myBlockSize indexes cache 2 */ + if (create && myCache[2][blockNum % myBlockSize] == 0) + { + myCache[2][blockNum % myBlockSize] = myFS->allocBlock(); + myCacheDirty[2] = 1; + } + return myCache[2][blockNum % myBlockSize]; +} diff --git a/kernel/fs/ext2/Ext2BlockCache.h b/kernel/fs/ext2/Ext2BlockCache.h new file mode 100644 index 0000000..ad77089 --- /dev/null +++ b/kernel/fs/ext2/Ext2BlockCache.h @@ -0,0 +1,34 @@ +// Ext2BlockCache.h +// Author: Josh Holtrop +// Date: 12/29/05 +// Modified: 12/29/05 + +#ifndef __HOS_EXT2BLOCKCACHE_H__ +#define __HOS_EXT2BLOCKCACHE_H__ __HOS_EXT2BLOCKCACHE_H__ + +#include "fs/vfs.h" +#include "ext2.h" + +class Ext2BlockCache +{ +protected: + Ext2fs *myFS; + u32_t myInum; + ext2_inode_t myInode; + u32_t myBlockSize; + u8_t *myCache[3]; + u8_t myCacheAddress[3]; + u8_t myCacheDirty[3]; + u32_t myInodeDirty; + + void setCache(u32_t level, u32_t fsblock); + u32_t getFSBlock(u32_t block, int create); + +public: + Ext2BlockCache(Ext2fs *fs, u32_t inum); + ~Ext2BlockCache(); + int readBlock(u32_t blockNum, void *buf); + int writeBlock(u32_t blockNum, void *buf); +}; + +#endif diff --git a/kernel/fs/ext2/Ext2OpenDirectory.cpp b/kernel/fs/ext2/Ext2OpenDirectory.cpp index 656ba7b..c26688b 100644 --- a/kernel/fs/ext2/Ext2OpenDirectory.cpp +++ b/kernel/fs/ext2/Ext2OpenDirectory.cpp @@ -3,32 +3,224 @@ // Date: 12/26/05 // Modified: 12/26/05 -#include "Ext2OpenDirectory.h" extern "C" { #include "display/kout.h" #include "lang/lang.h" } -Ext2OpenDirectory::Ext2OpenDirectory() +#include "fs/vfs.h" +#include "Ext2OpenDirectory.h" +#include "Ext2OpenFile.h" +#include "ext2.h" + +Ext2OpenDirectory::Ext2OpenDirectory(Ext2fs *fs, u32_t inum, int mode) { myPosition = 0; + myFS = fs; + myInum = inum; + myMode = mode; + myCache = new Ext2BlockCache(fs, inum); + fs->readInode(inum, &myInode); + u32_t size = myInode.i_size; + u32_t logBlockSize = fs->getSuper()->s_log_block_size; + myBlockSize = 1024 << logBlockSize; + if (size % myBlockSize) + size += myBlockSize - (size % myBlockSize); + myBlocks = size >> (10 + logBlockSize); + myBuffer = new u8_t[size]; + if ((mode & VFS_MODE_RW_MASK) == VFS_MODE_READ) + readDirectory(); } +/* destroy an open ext2 directory object */ Ext2OpenDirectory::~Ext2OpenDirectory() { + delete myCache; + if ((myMode & VFS_MODE_RW_MASK) == VFS_MODE_READ) + delete[] myBuffer; } +void Ext2OpenDirectory::readDirectory() +{ + /* read in the entire directory */ + for (u32_t i = 0; i < myBlocks; i++) + myCache->readBlock(i, myBuffer + i * myBlockSize); +} + +/* seek absolute or relative, only positive direction */ int Ext2OpenDirectory::seek(int pos, int mode) { - return -1; + if (mode == SEEK_ABSOLUTE) + myPosition = 0; + if (pos > 0) + { + while (myPosition < myInode.i_size) + { + ext2_dir_entry_t *de = + (ext2_dir_entry_t *) (myBuffer + myPosition); + myPosition += de->length; + pos--; + if (pos < 1) + return 0; + } + return -1; + } + return -2; } +/* read a directory entry from the directory */ int Ext2OpenDirectory::read(vfs_dir_entry_t *ent) { - return -1; + if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_READ) + return -1; + if (myPosition >= myInode.i_size) + return EOF; + ext2_dir_entry_t *de = (ext2_dir_entry_t *) (myBuffer + myPosition); + ent->inum = de->inode; + memcpy(ent->name, de->name, de->name_length); + ent->name[de->name_length] = 0; + myPosition += de->length; + return 0; } -int Ext2OpenDirectory::write(vfs_dir_entry_t *ent) +int Ext2OpenDirectory::create(char *name, int mode, u32_t permissions, u32_t dev) { - return -1; + if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_WRITE) + return -1; + readDirectory(); + myPosition = 0; + u32_t name_length = strlen(name); + while (myPosition < myInode.i_size) + { + ext2_dir_entry_t *de = + (ext2_dir_entry_t *) (myBuffer + myPosition); + if (name_length == de->name_length && !strncmp(name, de->name, name_length)) + return -2; /* entry already exists */ + myPosition += de->length; + } + u32_t newInode = myFS->allocInode(); + if (newInode == 0) + return -3; /* no free inodes! */ + /* initialize the inode */ + ext2_inode_t in; + memset(&in, 0, sizeof(ext2_inode_t)); + u32_t ext2_mode; + switch(mode) + { + case VFS_FT_DIR: ext2_mode = EXT2_I_MODE_DIR; break; + case VFS_FT_CHAR: ext2_mode = EXT2_I_MODE_CHAR; + in.i_block[0] = dev; break; + case VFS_FT_BLOCK: ext2_mode = EXT2_I_MODE_BLOCK; + in.i_block[0] = dev; break; + case VFS_FT_FIFO: ext2_mode = EXT2_I_MODE_FIFO; break; + case VFS_FT_SOCK: ext2_mode = EXT2_I_MODE_SOCK; break; + case VFS_FT_SYMLINK: ext2_mode = EXT2_I_MODE_SYM; break; + case VFS_FT_FILE: + default: ext2_mode = EXT2_I_MODE_FILE; break; + } + in.i_mode = ext2_mode | (permissions & EXT2_I_MODE_ATTR_MASK); + in.i_links_count = 1; + myFS->writeInode(newInode, &in); + u32_t entryLength = name_length + 8; + if (entryLength & 0x3) + entryLength = (entryLength + 4) & 0xFFFFFFFC; /* multiple of 4 bytes */ + myPosition = 0; + for (;;) + { + ext2_dir_entry_t *de = + (ext2_dir_entry_t *) (myBuffer + myPosition); + u32_t thisEntryLength = de->name_length + 8; + if (thisEntryLength & 0x3) + thisEntryLength = (thisEntryLength + 4) & 0xFFFFFFFC; + if (de->length - thisEntryLength >= entryLength) + { + /* There is room in this entry for the new one */ + u32_t newLength = de->length - entryLength; + de->length = entryLength; + u32_t firstPosition = myPosition; + myPosition += de->length; + de = (ext2_dir_entry_t *) (myBuffer + myPosition); + de->length = newLength; + de->name_length = name_length; + de->inode = newInode; + memcpy(de->name, name, name_length); + writeInclusiveRange(firstPosition, + myPosition + entryLength - 1); + return 0; + } + if (myPosition + de->length >= myInode.i_size) + { + if (myFS->getSuper()->s_free_blocks_count < 2) + return -4; /* out of space on device */ + /* This is the last entry, we need to add a block */ + myBlocks++; + u8_t *newBuffer = new u8_t[myBlockSize * myBlocks]; + memcpy(newBuffer, myBuffer, myBlockSize * (myBlocks - 1)); + delete[] myBuffer; + myBuffer = newBuffer; + de = (ext2_dir_entry_t *) (myBuffer + myPosition); + u32_t thisEntryLength = de->name_length + 8; + if (thisEntryLength & 0x3) + thisEntryLength = (thisEntryLength + 4) & 0xFFFFFFFC; + u32_t leftovers = de->length - thisEntryLength; + de->length -= leftovers; + u32_t firstPosition = myPosition; + myPosition += thisEntryLength; + de = (ext2_dir_entry_t *) (myBuffer + myPosition); + de->length = myBlockSize + leftovers; + de->name_length = name_length; + de->inode = newInode; + memcpy(de->name, name, name_length); + writeInclusiveRange(firstPosition, + myPosition + myBlockSize + leftovers - 1); + return 0; + } + myPosition += de->length; + } + } + +void Ext2OpenDirectory::writeInclusiveRange(u32_t first, u32_t last) +{ + u32_t firstBlock = first / myBlockSize; + u32_t lastBlock = last / myBlockSize; + for (u32_t i = firstBlock; i <= lastBlock; i++) + myCache->writeBlock(i, myBuffer + i * myBlockSize); +} + +int Ext2OpenDirectory::unlink(char *name) +{ + if ((myMode & VFS_MODE_RW_MASK) != VFS_MODE_WRITE) + return -1; + readDirectory(); + myPosition = 0; + u32_t lastPosition = 0; + u32_t name_length = strlen(name); + while (myPosition < myInode.i_size) + { + ext2_dir_entry_t *de = + (ext2_dir_entry_t *) (myBuffer + myPosition); + if (name_length == de->name_length && !strncmp(name, de->name, name_length)) + { + ext2_inode_t inode; + myFS->readInode(de->inode, &inode); + if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) == EXT2_I_MODE_DIR) + { + if (myFS->attemptRemoveDir(de->inode)) + return -3; /* can't unlink non-empty directory */ + } + /* found entry to unlink + add the space to entry at lastPosition */ + myFS->unlink(de->inode); + ext2_dir_entry_t *lde = + (ext2_dir_entry_t *) (myBuffer + lastPosition); + lde->length += de->length; + writeInclusiveRange(lastPosition, lastPosition + 8); + return 0; + } + lastPosition = myPosition; + myPosition += de->length; + } + return -2; /* entry not found */ +} + diff --git a/kernel/fs/ext2/Ext2OpenDirectory.h b/kernel/fs/ext2/Ext2OpenDirectory.h index 98bae84..29ccadd 100644 --- a/kernel/fs/ext2/Ext2OpenDirectory.h +++ b/kernel/fs/ext2/Ext2OpenDirectory.h @@ -6,18 +6,32 @@ #ifndef __HOS_EXT2OPENDIRECTORY__ #define __HOS_EXT2OPENDIRECTORY__ __HOS_EXT2OPENDIRECTORY__ -#include "fs/OpenDirectory.h" +#include "ext2.h" +#include "Ext2BlockCache.h" class Ext2OpenDirectory : public OpenDirectory { private: - int myPosition; + u32_t myPosition; + Ext2fs *myFS; + int myMode; + u32_t myInum; + u8_t *myBuffer; + u32_t myBlocks; + u32_t myBlockSize; + Ext2BlockCache *myCache; + ext2_inode_t myInode; + + void readDirectory(); + void writeInclusiveRange(u32_t first, u32_t last); + public: - Ext2OpenDirectory(); + Ext2OpenDirectory(Ext2fs *fs, u32_t inum, int mode); ~Ext2OpenDirectory(); int seek(int pos, int mode); int read(vfs_dir_entry_t *ent); - int write(vfs_dir_entry_t *ent); + int create(char *name, int mode, u32_t permissions, u32_t dev); + int unlink(char *name); }; #endif diff --git a/kernel/fs/ext2/Ext2OpenFile.cpp b/kernel/fs/ext2/Ext2OpenFile.cpp index fe935fa..98eeb81 100644 --- a/kernel/fs/ext2/Ext2OpenFile.cpp +++ b/kernel/fs/ext2/Ext2OpenFile.cpp @@ -1,5 +1,21 @@ -// Ext2OpenFile.h +// Ext2OpenFile.cpp // Author: Josh Holtrop // Date: 12/26/05 // Modified: 12/26/05 +#include "Ext2OpenFile.h" + +Ext2OpenFile::Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode) +{ + myMode = mode; + myFS = fs; + myInum = inum; + myCache = new Ext2BlockCache(fs, inum); + fs->readInode(inum, &myInode); +} + +Ext2OpenFile::~Ext2OpenFile() +{ + delete myCache; +} + diff --git a/kernel/fs/ext2/Ext2OpenFile.h b/kernel/fs/ext2/Ext2OpenFile.h index 1b9b323..2767f54 100644 --- a/kernel/fs/ext2/Ext2OpenFile.h +++ b/kernel/fs/ext2/Ext2OpenFile.h @@ -6,10 +6,22 @@ #ifndef __HOS_EXT2OPENFILE__ #define __HOS_EXT2OPENFILE__ __HOS_EXT2OPENFILE__ +#include "ext2.h" #include "fs/OpenFile.h" +#include "Ext2BlockCache.h" class Ext2OpenFile : public OpenFile { +protected: + Ext2fs *myFS; + u32_t myInum; + int myMode; + Ext2BlockCache *myCache; + ext2_inode_t myInode; + +public: + Ext2OpenFile(Ext2fs *fs, u32_t inum, int mode); + ~Ext2OpenFile(); }; diff --git a/kernel/fs/ext2/ext2.cpp b/kernel/fs/ext2/ext2.cpp index b6461b1..8ddda62 100644 --- a/kernel/fs/ext2/ext2.cpp +++ b/kernel/fs/ext2/ext2.cpp @@ -4,7 +4,17 @@ // Date: 05/10/05 // Modified: 05/10/05 -#define _HOS_CPP_ _HOS_CPP_ +/* example ext2 filesystem block group structure containing superblock and group descriptors: + * block offset description #blocks + * ------------ ----------- ------- + * 0 superblock 1 + * 1 group descriptors gd_blocks = ceil(ceil[s_blocks_count / s_blocks_per_group] / (1024 >> [5 - s_log_block_size])) + * gd_blocks+1 block bitmap block 1 + * gd_blocks+2 inode bitmap block 1 + * gd_blocks+3 inode table itblocks = ceil[s_inodes_per_group / (1024 >> [7 - s_log_block_size])] + * gd_blocks+3+itblocks data blocks s_blocks_per_group - gd_blocks - itblocks - 3 + */ + extern "C" { #include "display/kout.h" @@ -16,12 +26,14 @@ extern "C" { #include "Ext2OpenDirectory.h" #include "Ext2OpenFile.h" +/* initialize the ext2 filesystem driver */ int ext2_init() { vfs_register("ext2", ext2__mount_func); return 0; } +/* a function to mount an ext2 filesystem and return a pointer to it */ FileSystem *ext2__mount_func(device_t dev) { ext2_super_block_t *super = @@ -37,41 +49,60 @@ FileSystem *ext2__mount_func(device_t dev) return fs; } +/* constructor for an actual ext2 filesystem object */ Ext2fs::Ext2fs(ext2_super_block_t *super, device_t dev) { myDevice = dev; memcpy(&mySuper, super, sizeof(ext2_super_block_t)); mySuperDirty = 0; - kprintf("Blocks: %d (%d free), Inodes: %d (%d free) Creator OS:\n", - mySuper.s_blocks_count, - mySuper.s_free_blocks_count, - mySuper.s_inodes_count, - mySuper.s_free_inodes_count, - mySuper.s_creator_os); + myNumGroups = /* ceil[blocks_count / blocks_per_group] */ + (mySuper.s_blocks_count + mySuper.s_blocks_per_group - 1) + / mySuper.s_blocks_per_group; + myGroupDescriptorsPerBlock = 1024 >> (5 - mySuper.s_log_block_size); + myGroupDescriptorBlocks = /* ceil[num_groups / groupDescriptorsPerBlock] */ + (myNumGroups + myGroupDescriptorsPerBlock - 1) + / myGroupDescriptorsPerBlock; + myInodesPerBlock = 1024 >> (7 - mySuper.s_log_block_size); + myInodeTableBlocks = /* ceil[inodes_per_group / inodePerBlock] */ + (mySuper.s_inodes_per_group + myInodesPerBlock - 1) + / myInodesPerBlock; + + /* test/debug code */ + OpenDirectory *od = openDirectory(2, VFS_MODE_WRITE); + kprintf("TEST: %d\n", od->unlink("link")); + kprintf("TEST: %d\n", od->create("test", VFS_FT_FILE, 0640, 0)); + kprintf("TEST: %d\n", od->create("Block File baby", VFS_FT_BLOCK, 0666, 5 << 8 | 3)); + kprintf("TEST: %d\n", od->create("Character-File", VFS_FT_CHAR, 0644, 130 << 8 | 42)); + delete od; } +/* this destructor destroys an ext2 filesystem that was mounted */ Ext2fs::~Ext2fs() { if (mySuperDirty) block_write(DEV_MAJOR(myDevice), DEV_MINOR(myDevice), 2, 2, &mySuper); } +/* return the total number of 512-blocks on the filesystem */ u32_t Ext2fs::totalBlocks() { - return mySuper.s_blocks_count << (mySuper.s_log_block_size + 1); + return mySuper.s_blocks_count >> (mySuper.s_log_block_size + 1); } +/* return the number of free 512-blocks on the filesystem */ u32_t Ext2fs::freeBlocks() { - return mySuper.s_free_blocks_count << (mySuper.s_log_block_size + 1); + return mySuper.s_free_blocks_count >> (mySuper.s_log_block_size + 1); } +/* return the total number of inodes on the filesystem */ u32_t Ext2fs::totalInodes() { return mySuper.s_inodes_count; } +/* return the free number of inodes on the filesystem */ u32_t Ext2fs::freeInodes() { return mySuper.s_free_inodes_count; @@ -83,17 +114,396 @@ u32_t Ext2fs::getRootInodeNumber() return 2; } -OpenDirectory *Ext2fs::openDirectory(u32_t inum) -{ - return NULL; -} - -OpenFile *Ext2fs::openFile(u32_t inum) +/* open a directory */ +OpenDirectory *Ext2fs::openDirectory(u32_t inum, int mode) { + ext2_inode_t inode; + readInode(inum, &inode); + if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) == EXT2_I_MODE_DIR) + return new Ext2OpenDirectory(this, inum, mode); return NULL; } +/* stat an inode */ int Ext2fs::stat(u32_t inum, vfs_stat_t *buf) { - return -1; + ext2_inode_t inode; + if (readInode(inum, &inode)) + return -1; + buf->dev = 0; + switch(inode.i_mode & EXT2_I_MODE_TYPE_MASK) + { + case EXT2_I_MODE_FIFO: buf->type = VFS_FT_FIFO; break; + case EXT2_I_MODE_CHAR: buf->type = VFS_FT_CHAR; + buf->dev = inode.i_block[0]; break; + case EXT2_I_MODE_DIR: buf->type = VFS_FT_DIR; break; + case EXT2_I_MODE_BLOCK: buf->type = VFS_FT_BLOCK; + buf->dev = inode.i_block[0]; break; + case EXT2_I_MODE_FILE: buf->type = VFS_FT_FILE; break; + case EXT2_I_MODE_SYM: buf->type = VFS_FT_SYMLINK; break; + case EXT2_I_MODE_SOCK: buf->type = VFS_FT_SOCK; break; + default: buf->type = VFS_FT_UNKNOWN; + } + buf->size = inode.i_size; + buf->inode = inum; + buf->permissions = inode.i_mode & EXT2_I_MODE_ATTR_MASK; + buf->uid = inode.i_uid; + buf->gid = inode.i_gid; + buf->atime = inode.i_atime; + buf->mtime = inode.i_mtime; + buf->ctime = inode.i_ctime; + buf->links = inode.i_links_count; + return 0; } + +/* dereference a symbolink link */ +int Ext2fs::link_deref(u32_t inum, char *buf) +{ + ext2_inode_t inode; + if (readInode(inum, &inode)) + return -1; /* Couldn't read inode */ + if ((inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_SYM) + return -2; + if (inode.i_size > VFS_MAX_PATH_LENGTH) + return -3; + if (inode.i_size < 61) + { + memcpy(buf, inode.i_block, inode.i_size); + buf[inode.i_size] = 0; + return 0; + } + char *block = new char[1024 << mySuper.s_log_block_size]; + readBlock(inode.i_block[0], block); + memcpy(buf, block, inode.i_size); + buf[inode.i_size] = 0; + delete[] block; + return 0; +} + + +/*************************** internal functions ***************************/ + +/* read an inode from the disk into memory */ +int Ext2fs::readInode(u32_t inum, ext2_inode_t *buf) +{ + if (inodeStatus(inum) != 1) + return -1; + inum--; /* turn inode number into a 0-based index */ + u32_t group = inum / mySuper.s_inodes_per_group; + u32_t index = inum % mySuper.s_inodes_per_group; + ext2_group_desc_t group_desc; + readGroupDescriptor(group, &group_desc); + ext2_inode_t *inode_block = new ext2_inode_t[8 << mySuper.s_log_block_size]; + readBlock(group_desc.bg_inode_table + + (index >> (3 + mySuper.s_log_block_size)), inode_block); + u32_t inode_block_index = index % (8 << mySuper.s_log_block_size); + memcpy(buf, inode_block + inode_block_index, sizeof(ext2_inode_t)); + delete[] inode_block; + return 0; +} + +/* write an inode from memory onto the disk */ +int Ext2fs::writeInode(u32_t inum, ext2_inode_t *buf) +{ + if (inodeStatus(inum) != 1) + return -1; + inum--; /* turn inode number into a 0-based index */ + u32_t group = inum / mySuper.s_inodes_per_group; + u32_t index = inum % mySuper.s_inodes_per_group; + ext2_group_desc_t group_desc; + readGroupDescriptor(group, &group_desc); + ext2_inode_t *inode_block = new ext2_inode_t[8 << mySuper.s_log_block_size]; + u32_t block_num = group_desc.bg_inode_table + + (index >> (3 + mySuper.s_log_block_size)); + readBlock(block_num, inode_block); + u32_t inode_block_index = index % (8 << mySuper.s_log_block_size); + memcpy(inode_block + inode_block_index, buf, sizeof(ext2_inode_t)); + writeBlock(block_num, inode_block); + delete[] inode_block; + return 0; +} + +/* read the group descriptor for a given group number */ +int Ext2fs::readGroupDescriptor(u32_t group, ext2_group_desc_t *buf) +{ + if (group >= myNumGroups) + return -1; + ext2_group_desc_t *gd_block = + new ext2_group_desc_t[myGroupDescriptorsPerBlock]; + readBlock(mySuper.s_first_data_block + 1 + + (group / myGroupDescriptorsPerBlock), gd_block); + memcpy(buf, gd_block + (group % myGroupDescriptorsPerBlock), + sizeof(ext2_group_desc_t)); + delete[] gd_block; + return 0; +} + +/* write the group descriptor for a given group number */ +int Ext2fs::writeGroupDescriptor(u32_t group, ext2_group_desc_t *buf) +{ + if (group >= myNumGroups) + return -1; + ext2_group_desc_t *gd_block = + new ext2_group_desc_t[myGroupDescriptorsPerBlock]; + u32_t block_num = mySuper.s_first_data_block + 1 + + (group / myGroupDescriptorsPerBlock); + readBlock(block_num, gd_block); + memcpy(gd_block + (group % myGroupDescriptorsPerBlock), buf, + sizeof(ext2_group_desc_t)); + writeBlock(block_num, gd_block); + delete[] gd_block; + return 0; +} + +/* read a data block from the block device */ +int Ext2fs::readBlock(u32_t blockNum, void *buf) +{ + return block_read(DEV_MAJOR(myDevice), DEV_MINOR(myDevice), + blockNum << (mySuper.s_log_block_size + 1), + 2 << mySuper.s_log_block_size, + buf); +} + +/* write a data block to the block device */ +int Ext2fs::writeBlock(u32_t blockNum, void *buf) +{ + return block_write(DEV_MAJOR(myDevice), DEV_MINOR(myDevice), + blockNum << (mySuper.s_log_block_size + 1), + 2 << mySuper.s_log_block_size, + buf); +} + +/* check the status of an inode (1-based inode number) + * -1: invalid inode number + * 0: free inode + * 1: allocated (used) inode + */ +int Ext2fs::inodeStatus(u32_t inum) +{ + if (inum < 1 || inum > mySuper.s_inodes_count) + return -1; /* invalid inode number */ + inum--; /* turn inode number into a 0-based index */ + u32_t group = inum / mySuper.s_inodes_per_group; + u32_t index = inum % mySuper.s_inodes_per_group; + ext2_group_desc_t group_desc; + readGroupDescriptor(group, &group_desc); + u8_t *bitmap_block = new u8_t[1024 << mySuper.s_log_block_size]; + readBlock(group_desc.bg_inode_bitmap + + (index >> (13 + mySuper.s_log_block_size)), bitmap_block); + u32_t bitmap_index = index % (8192 << mySuper.s_log_block_size); + int inode_status = (bitmap_block[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1; + delete[] bitmap_block; + return inode_status; +} + +/* check the status of a block + * -1: invalid block number + * 0: free block + * 1: allocated (used) block + */ +int Ext2fs::blockStatus(u32_t bnum) +{ + if (bnum < mySuper.s_first_data_block) + return 1; + if (bnum >= mySuper.s_blocks_count) + return -1; /* invalid inode number */ + bnum -= mySuper.s_first_data_block; + u32_t group = bnum / mySuper.s_blocks_per_group; + u32_t index = bnum % mySuper.s_blocks_per_group; + ext2_group_desc_t group_desc; + readGroupDescriptor(group, &group_desc); + u8_t *bitmap_block = new u8_t[1024 << mySuper.s_log_block_size]; + readBlock(group_desc.bg_block_bitmap + + (index >> (13 + mySuper.s_log_block_size)), bitmap_block); + u32_t bitmap_index = index % (8192 << mySuper.s_log_block_size); + int block_status = (bitmap_block[bitmap_index >> 3] >> (bitmap_index & 0x7)) & 1; + delete[] bitmap_block; + return block_status; +} + +/* allocate an inode, return number (0 on failure) */ +u32_t Ext2fs::allocInode() +{ + ext2_group_desc_t gd; + for (unsigned int bg = 0; bg < myNumGroups; bg++) + { + readGroupDescriptor(bg, &gd); + if (gd.bg_free_inodes_count) + { + u32_t index = allocFromBitmap(gd.bg_inode_bitmap, + mySuper.s_inodes_per_group); + if (index == 0xFFFFFFFF) + return 0; + gd.bg_free_inodes_count--; + writeGroupDescriptor(bg, &gd); + mySuper.s_free_inodes_count--; + mySuperDirty = 1; + return (bg * mySuper.s_inodes_per_group) + index + 1; + } + } + return 0; +} + +/* allocate a block, return number (0 on failure) */ +u32_t Ext2fs::allocBlock() +{ + ext2_group_desc_t gd; + for (unsigned int bg = 0; bg < myNumGroups; bg++) + { + readGroupDescriptor(bg, &gd); + if (gd.bg_free_blocks_count) + { + u32_t index = allocFromBitmap(gd.bg_block_bitmap, + mySuper.s_blocks_per_group); + if (index == 0xFFFFFFFF) + return 0; + gd.bg_free_blocks_count--; + writeGroupDescriptor(bg, &gd); + mySuper.s_free_blocks_count--; + mySuperDirty = 1; + return (bg * mySuper.s_blocks_per_group) + index + + mySuper.s_first_data_block; + } + } + return 0; +} + +/* free an inode, return error code */ +int Ext2fs::freeInode(u32_t inum) +{ + if (inum < 11 || inum > mySuper.s_inodes_count) + return -1; + if (inodeStatus(inum) != 1) + return -2; + inum--; /* now 0-based */ + ext2_group_desc_t gd; + u32_t group_num = inum / mySuper.s_inodes_per_group; + readGroupDescriptor(group_num, &gd); + freeFromBitmap(gd.bg_inode_bitmap, inum % mySuper.s_inodes_per_group); + gd.bg_free_inodes_count++; + mySuper.s_free_inodes_count++; + mySuperDirty = 1; + writeGroupDescriptor(group_num, &gd); + return 0; +} + +/* free a block, return error code */ +int Ext2fs::freeBlock(u32_t bnum) +{ + if (bnum < mySuper.s_first_data_block || bnum >= mySuper.s_blocks_count) + return -1; + if (blockStatus(bnum) != 1) + return -2; + bnum -= mySuper.s_first_data_block; /* now 0-based */ + ext2_group_desc_t gd; + u32_t group_num = bnum / mySuper.s_blocks_per_group; + readGroupDescriptor(group_num, &gd); + freeFromBitmap(gd.bg_block_bitmap, bnum % mySuper.s_blocks_per_group); + gd.bg_free_blocks_count++; + mySuper.s_free_blocks_count++; + mySuperDirty = 1; + writeGroupDescriptor(group_num, &gd); + return 0; +} + +/* allocate a node from a bitmap, return the index, 0xFFFFFFFF on failure */ +u32_t Ext2fs::allocFromBitmap(u32_t blockNum, u32_t maxBits) +{ + u8_t *block = new u8_t[1024 << mySuper.s_log_block_size]; + u8_t *blockPtr = block; + u32_t maxBytes = (maxBits + 7) >> 3; + readBlock(blockNum, block); + for (u32_t idx = 0; idx < maxBytes; idx++) + { + if (*blockPtr != 0xFF) + { + for (u32_t bit = 0; bit < 8; bit++) + { + if ( !((*blockPtr) & (1 << bit)) ) + { + u32_t nodeIndex = (idx << 3) + bit; + if (nodeIndex < maxBits) + { + *blockPtr |= (1 << bit); + writeBlock(blockNum, block); + return nodeIndex; + } + return 0xFFFFFFFF; + } + } + break; + } + blockPtr++; + } + delete[] block; + return 0xFFFFFFFF; +} + +/* free a node from a bitmap */ +void Ext2fs::freeFromBitmap(u32_t blockNum, u32_t node) +{ + u8_t *block = new u8_t[1024 << mySuper.s_log_block_size]; + readBlock(blockNum, block); + u8_t *blockPtr = block + (node >> 3); + *blockPtr &= ((1 << (node & 0x7)) ^ 0xFF); + writeBlock(blockNum, block); + delete[] block; +} + +/* this function is called when a file is opened for writing and truncates + * the inode. the function notifies any file handles open on this inode that + * the inode was truncated + */ +void Ext2fs::notifyTruncatedFiles(u32_t inum) +{ + // TODO: notify open files +} + +/* unlink an inode: + * decrement i_links_count + * if it is zero, free the inode + * if not, write the inode back + */ +void Ext2fs::unlink(u32_t inum) +{ + ext2_inode_t inode; + readInode(inum, &inode); + inode.i_links_count--; + if (inode.i_links_count) + { + writeInode(inum, &inode); + return; + } + freeBlocksFromInode(inum); + freeInode(inum); +} + +int Ext2fs::attemptRemoveDir(u32_t inum) +{ + vfs_dir_entry_t dentry, dentry2; + OpenDirectory *od = openDirectory(inum, VFS_MODE_READ); + if (od->read(&dentry)) + { + delete od; + return -1; + } + if (od->read(&dentry2)) + { + delete od; + return -1; + } + if (!od->read(&dentry)) + { + delete od; + return -1; + } + delete od; + unlink(dentry.inode); + unlink(dentry2.inode); +} + +void Ext2fs::freeBlocksFromInode(u32_t inum) +{ + +} + diff --git a/kernel/fs/ext2/ext2.h b/kernel/fs/ext2/ext2.h index 8d06dc0..6663b4a 100644 --- a/kernel/fs/ext2/ext2.h +++ b/kernel/fs/ext2/ext2.h @@ -117,7 +117,7 @@ typedef struct u32_t i_dtime; // Deletion time u16_t i_gid; // Group ID u16_t i_links_count; // Links count - u32_t i_blocks; // Blocks count + u32_t i_blocks; // Disk Blocks count (512) u32_t i_flags; // File flags u32_t i_reserved1; u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect) @@ -136,24 +136,36 @@ typedef struct u32_t inode; // inode number u16_t length; // directory entry length u8_t name_length; // name length - u8_t file_type; // File type + u8_t file_type; // File type (used???) char name[EXT2_NAME_LEN]; } ext2_dir_entry_t; #ifdef _HOS_CPP_ -#include "Ext2OpenDirectory.h" -#include "Ext2OpenFile.h" - int ext2_init(); FileSystem *ext2__mount_func(device_t dev); class Ext2fs : public FileSystem { protected: +/* my data members */ device_t myDevice; int mySuperDirty; ext2_super_block_t mySuper; + u32_t myNumGroups; + u32_t myGroupDescriptorBlocks; + u32_t myInodeTableBlocks; + u32_t myGroupDescriptorsPerBlock; + u32_t myInodesPerBlock; + +/* my functions */ + int readGroupDescriptor(u32_t group, ext2_group_desc_t *buf); + int writeGroupDescriptor(u32_t group, ext2_group_desc_t *buf); + int inodeStatus(u32_t inum); + int blockStatus(u32_t bnum); + u32_t allocFromBitmap(u32_t blockNum, u32_t max); + void freeFromBitmap(u32_t blockNum, u32_t node); + public: Ext2fs(ext2_super_block_t *super, device_t dev); ~Ext2fs(); @@ -162,9 +174,27 @@ public: u32_t totalInodes(); u32_t freeInodes(); u32_t getRootInodeNumber(); - OpenDirectory *openDirectory(u32_t inum); - OpenFile *openFile(u32_t inum); + OpenDirectory *openDirectory(u32_t inum, int mode); int stat(u32_t inum, vfs_stat_t *buf); + int readBlock(u32_t blockNum, void *buf); + int writeBlock(u32_t blockNum, void *buf); + int link_deref(u32_t inum, char *buf); + int readInode(u32_t inum, ext2_inode_t *buf); + int writeInode(u32_t inum, ext2_inode_t *buf); + void notifyTruncatedFiles(u32_t inum); + u32_t allocInode(); + u32_t allocBlock(); + int freeInode(u32_t inum); + int freeBlock(u32_t bnum); + void unlink(u32_t inum); + int attemptRemoveDir(u32_t inum); + void freeBlocksFromInode(u32_t inum); + + /* inlined functions */ + inline u32_t numGroups() { return myNumGroups; } + inline u32_t groupDescriptorBlocks() { return myGroupDescriptorBlocks; } + inline u32_t inodeTableBlocks() { return myInodeTableBlocks; } + inline ext2_super_block_t *getSuper() { return &mySuper; } }; #endif diff --git a/kernel/fs/ext2/ext2_working.c b/kernel/fs/ext2/ext2_working.c new file mode 100644 index 0000000..474d538 --- /dev/null +++ b/kernel/fs/ext2/ext2_working.c @@ -0,0 +1,332 @@ + + +// lookup a file name in a directory and store the directory entry for it +int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry) +{ + ext2_open_dir_t *dir = ext2_open_dir(mount, dir_inode); + if (!dir) + return -1; // bad directory inode number + ext2_dir_entry_t dentry; + while (!ext2_dir_read_entry(mount, dir, &dentry)) + { + char *dentryName = kcalloc(1, dentry.name_length + 1); + memcpy(dentryName, dentry.name, dentry.name_length); + int res = strcmp(fileName, dentryName); + kfree(dentryName); + if (!res) + { + *direntry = dentry; + ext2_close_dir(mount, dir); + return 0; + } + } + ext2_close_dir(mount, dir); + return -2; +} + +// open a directory by inode number for reading +ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number) +{ + ext2_open_dir_t *open_dir = New(ext2_open_dir_t); + ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number); + if (!open_inode) + { + kfree(open_dir); + return NULL; + } + if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_DIR) + { + ext2_close_inode(mount, open_inode); + kfree(open_dir); + return NULL; + } + open_dir->open_inode = open_inode; + open_dir->position = 0; + return open_dir; +} + +int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry) +{ + ext2_super_block_t *super = mount->super; + if (open_dir->position >= open_dir->open_inode->inode.i_size) + return -1; // EOF + u32_t dir_block = open_dir->position >> (10 + super->s_log_block_size); + char *block = kmalloc(2048 << super->s_log_block_size); + ext2_inode_seek(mount, open_dir->open_inode, dir_block); + if (ext2_read_inode_block(mount, open_dir->open_inode, block)) + ext2_read_inode_block(mount, open_dir->open_inode, block + (1024 << super->s_log_block_size)); + ext2_dir_entry_t *dir_entry = (ext2_dir_entry_t *)(block + open_dir->position % (1024 << super->s_log_block_size)); + if (!dir_entry->inode) + { + kfree(block); + return -2; // EOF + } + memcpy(dentry, dir_entry, min(dir_entry->length, sizeof(ext2_dir_entry_t))); + open_dir->position += dir_entry->length; + kfree(block); + return 0; +} + +int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir) +{ + ext2_close_inode(mount, open_dir->open_inode); + kfree(open_dir); + return 0; +} + + +// open an inode for reading +ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number) +{ + ext2_open_inode_t *open_inode = New(ext2_open_inode_t); + if ( ext2_read_inode(mount, inode_number, &(open_inode->inode)) ) + { + kfree(open_inode); + return NULL; + } + open_inode->block = 0; + open_inode->block_pointers = NULL; + open_inode->block_pointers_start = 0; + mount->refs++; + return open_inode; +} + + +// seek to a certain block of an open inode +int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number) +{ + ext2_super_block_t *super = mount->super; + if (open_inode->inode.i_size <= (block_number << (10 + super->s_log_block_size))) + return -1; // at or past EOF + open_inode->block = block_number; + return 0; +} + +// returns number of bytes read +int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block) +{ + ext2_super_block_t *super = mount->super; + if (open_inode->inode.i_size <= (open_inode->block << (10 + super->s_log_block_size))) + return 0; // at or past EOF + u32_t leftover_bytes = open_inode->inode.i_size - (open_inode->block << (10 + super->s_log_block_size)); + u32_t block_number = ext2_block_number(mount, open_inode); + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_number, super), + 2 << super->s_log_block_size, block); + open_inode->block++; + return min(leftover_bytes, 1024 << super->s_log_block_size); +} + + +// close an open inode +int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode) +{ + mount->refs--; + if (open_inode->block_pointers) + kfree(open_inode->block_pointers); // free the block pointers cache + kfree(open_inode); + return 0; +} + + +// transform open_inode->block (a relative block number) to an absolute block number for the filesystem +u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode) +{ + if (open_inode->block < 12) + return open_inode->inode.i_block[open_inode->block]; + ext2_super_block_t *super = mount->super; + int pointersPerBlock = 256 << super->s_log_block_size; + if (open_inode->block_pointers && // there is a block pointers cache block allocated + (open_inode->block >= open_inode->block_pointers_start) && // and the block number is in it + (open_inode->block < (open_inode->block_pointers_start + pointersPerBlock))) + return open_inode->block_pointers[open_inode->block - open_inode->block_pointers_start]; + u32_t rel_block = open_inode->block - 12; + if (!open_inode->block_pointers) + open_inode->block_pointers = kmalloc(pointersPerBlock << 2); + if (rel_block < pointersPerBlock) // indirect block in i_block[12] + { + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[12], super), + 2 << super->s_log_block_size, open_inode->block_pointers); + open_inode->block_pointers_start = 12; + return open_inode->block_pointers[rel_block]; + } + rel_block -= pointersPerBlock; + if (rel_block < (pointersPerBlock * pointersPerBlock)) // double-indirect block in i_block[13] + { + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[13], super), + 2 << super->s_log_block_size, open_inode->block_pointers); + u32_t real_block = open_inode->block_pointers[rel_block / pointersPerBlock]; + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(real_block, super), + 2 << super->s_log_block_size, open_inode->block_pointers); + open_inode->block_pointers_start = 12 + pointersPerBlock + rel_block - (rel_block % pointersPerBlock); + return open_inode->block_pointers[rel_block % pointersPerBlock]; + } + // this code shouldn't run unless we are dealing with a 65+mb file ... + rel_block -= pointersPerBlock * pointersPerBlock; + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(open_inode->inode.i_block[14], super), + 2 << super->s_log_block_size, open_inode->block_pointers); + u32_t index_1 = rel_block / (pointersPerBlock * pointersPerBlock); + u32_t leftover_1 = rel_block % (pointersPerBlock * pointersPerBlock); + u32_t block_1 = open_inode->block_pointers[index_1]; + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_1, super), + 2 << super->s_log_block_size, open_inode->block_pointers); + u32_t index_2 = leftover_1 / pointersPerBlock; + u32_t leftover_2 = leftover_1 % pointersPerBlock; + u32_t block_2 = open_inode->block_pointers[index_2]; + block_read(mount->major, mount->minor, ext2_FSToDiskBlock(block_2, super), + 2 << super->s_log_block_size, open_inode->block_pointers); + open_inode->block_pointers_start = 12 + (pointersPerBlock + 1) * pointersPerBlock + rel_block - (rel_block % pointersPerBlock); + return open_inode->block_pointers[leftover_2]; +} + + +int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size) +{ + ext2_inode_t inode; + if ( ext2_read_inode(mount, inode_number, &inode) ) + return -1; + ext2_super_block_t *super = mount->super; + int current_blocks = (inode.i_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size); + int new_blocks = (new_size + (1024 << super->s_log_block_size) - 1) >> (10 + super->s_log_block_size); + if ( new_blocks == current_blocks ) + return 0; + + // TODO: resize + u32_t block_size = 1024 << super->s_log_block_size; + u32_t pointers_per_block = block_size >> 2; + u32_t *pointer_cache1 = kmalloc(3 * block_size); + u32_t *pointer_cache2 = pointer_cache1 + pointers_per_block; + u32_t *pointer_cache3 = pointer_cache2 + pointers_per_block; + u32_t c1_start, c2_start, c3_start; + c1_start = c2_start = c3_start = 0; + while (new_blocks < current_blocks) // delete, decrease current_blocks + { + current_blocks--; + // now delete block number current_blocks + + } + + while (current_blocks < new_blocks) // add, increase current_blocks + { + } +} + + +/***************** VFS INTERFACE FUNCTIONS *******************/ + + + +// VFS interface function to open a directory +int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir) +{ + if (ext2_inode_status(mount, inode_number) != 1) + return -1; + ext2_open_dir_t *open_dir = ext2_open_dir(mount, inode_number); + if (!open_dir) + return -2; + dir->fs_data = open_dir; + return 0; +} + +// VFS interface function to read a directory entry from an open directory +int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry) +{ + ext2_dir_entry_t t_dentry; + int status = ext2_dir_read_entry(mount, dir->fs_data, &t_dentry); + if (status) + return status; + memcpy(dentry->name, t_dentry.name, t_dentry.name_length); + dentry->name[t_dentry.name_length] = 0; + dentry->inode_number = t_dentry.inode; + return 0; +} + +// VFS interface function to close an open directory +int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir) +{ + return ext2_close_dir(mount, dir->fs_data); +} + + +// VFS interface function to open a file for reading a byte at a time +int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file) +{ + if (ext2_inode_status(mount, inode_number) != 1) + return -1; + return 0; +} + +// VFS interface function to read a byte from an open file +int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file) +{ + return 0; +} + +// VFS interface function to close a byte-file +int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file) +{ + return 0; +} + + +// VFS interface function to open a file for reading 512-byte blocks at a time +int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file) +{ + if (ext2_inode_status(mount, inode_number) != 1) + return -1; + ext2_open_inode_t *open_inode = ext2_open_inode(mount, inode_number); + if (!open_inode) + return -2; + if ((open_inode->inode.i_mode & EXT2_I_MODE_TYPE_MASK) != EXT2_I_MODE_FILE) + { + ext2_close_inode(mount, open_inode); + return -3; + } + ext2__open_block_file_t *open_block_file = New(ext2__open_block_file_t); + open_block_file->open_inode = open_inode; + open_block_file->block = 0; + open_file->fs_data = open_block_file; + return 0; +} + +// VFS interface function to read a block from an open block file +// returns the number of bytes read +int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer) +{ + ext2_super_block_t *super = mount->super; + ext2__open_block_file_t *open_block_file = open_file->fs_data; + if (ext2_inode_seek(mount, open_block_file->open_inode, ext2_diskToFSBlock(open_block_file->block, super))) + return 0; // EOF + u8_t *block = kmalloc(1024 << super->s_log_block_size); + u32_t file_position_read = (1024 << super->s_log_block_size) * open_block_file->open_inode->block; + u32_t file_position_want = open_block_file->block << 9; + u32_t data_offset = file_position_want - file_position_read; + int bytes_read = ext2_read_inode_block(mount, open_block_file->open_inode, block); + if (bytes_read <= data_offset) + { + kfree(block); + return 0; // EOF + } + memcpy(buffer, block + data_offset, min(512, bytes_read - data_offset)); + kfree(block); + open_block_file->block++; + return min(512, bytes_read - data_offset); +} + +// VFS interface function to seek to a certain block number of an open block file +int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number) +{ + ext2__open_block_file_t *open_block_file = open_file->fs_data; + return ext2_inode_seek(mount, open_block_file->open_inode, ext2_FSToDiskBlock(block_number, mount->super)); +} + +// VFS interface function to close an open block file +int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file) +{ + ext2__open_block_file_t *open_block_file = open_file->fs_data; + ext2_close_inode(mount, open_block_file->open_inode); + kfree(open_block_file); + return 0; +} + + + diff --git a/kernel/fs/ext2/ext2_working.h b/kernel/fs/ext2/ext2_working.h new file mode 100644 index 0000000..f51249d --- /dev/null +++ b/kernel/fs/ext2/ext2_working.h @@ -0,0 +1,241 @@ +// ext2.h +// Author: Josh Holtrop +// Date: 08/22/04 +// Modified: 12/24/04 + +#ifndef __HOS_EXT2_H__ +#define __HOS_EXT2_H__ __HOS_EXT2_H__ + +#include "hos_defines.h" +#include "fs/devices.h" +#include "fs/vfs.h" + +#define EXT2_MAGIC 0xEF53 +#define EXT2_NAME_LEN 255 + +#define EXT2_I_MODE_ATTR_MASK 0x0FFF +#define EXT2_I_MODE_OX 0x0001 +#define EXT2_I_MODE_OW 0x0002 +#define EXT2_I_MODE_OR 0x0004 +#define EXT2_I_MODE_GX 0x0008 +#define EXT2_I_MODE_GW 0x0010 +#define EXT2_I_MODE_GR 0x0020 +#define EXT2_I_MODE_UX 0x0040 +#define EXT2_I_MODE_UW 0x0080 +#define EXT2_I_MODE_UR 0x0100 +#define EXT2_I_MODE_STICKY 0x0200 +#define EXT2_I_MODE_SGID 0x0400 +#define EXT2_I_MODE_SUID 0x0800 + +#define EXT2_I_MODE_TYPE_MASK 0xF000 +#define EXT2_I_MODE_FIFO 0x1000 +#define EXT2_I_MODE_CHAR 0x2000 +#define EXT2_I_MODE_DIR 0x4000 +#define EXT2_I_MODE_BLOCK 0x6000 +#define EXT2_I_MODE_FILE 0x8000 +#define EXT2_I_MODE_SYM 0xA000 +#define EXT2_I_MODE_SOCK 0xC000 + +#define EXT2_I_FLAGS_SEC_DEL 0x01 +#define EXT2_I_FLAGS_UNDELETE 0x02 +#define EXT2_I_FLAGS_COMPRESS 0x04 +#define EXT2_I_FLAGS_SYNC 0x08 +#define EXT2_I_FLAGS_IMMUTABLE 0x10 +#define EXT2_I_FLAGS_APPEND 0x20 +#define EXT2_I_FLAGS_NODUMP 0x40 + +#define EXT2_INODE_BAD_BLOCKS 1 +#define EXT2_INODE_ROOT 2 +#define EXT2_INODE_ACL_INDEX 3 +#define EXT2_INODE_ACL_DATA 4 +#define EXT2_INODE_BOOT_LOADER 5 +#define EXT2_INODE_UNDELETE_DIR 6 +#define EXT2_INODE_AVAIL 11 + +#define EXT2_FT_UNKNOWN 0 +#define EXT2_FT_FILE 1 +#define EXT2_FT_DIR 2 +#define EXT2_FT_CHAR 3 +#define EXT2_FT_BLOCK 4 +#define EXT2_FT_FIFO 5 +#define EXT2_FT_SOCK 6 +#define EXT2_FT_SYMLINK 7 +#define EXT2_FT_MAX 8 + +typedef struct +{ + u32_t s_inodes_count; /* Inodes count */ + u32_t s_blocks_count; /* Blocks count */ + u32_t s_r_blocks_count; /* Reserved blocks count */ + u32_t s_free_blocks_count; /* Free blocks count */ + u32_t s_free_inodes_count; /* Free inodes count */ + u32_t s_first_data_block; /* First Data Block */ + u32_t s_log_block_size; /* Block size: 0->1024, 1->2048, 2->4096 */ + int s_log_frag_size; /* Fragment size */ + u32_t s_blocks_per_group; /* # Blocks per group */ + u32_t s_frags_per_group; /* # Fragments per group */ + u32_t s_inodes_per_group; /* # Inodes per group */ + u32_t s_mtime; /* Mount time */ + u32_t s_wtime; /* Write time */ + u16_t s_mnt_count; /* Mount count */ + short s_max_mnt_count; /* Maximal mount count */ + u16_t s_magic; /* Magic signature */ + u16_t s_state; /* File system state */ + u16_t s_errors; /* Behaviour when detecting errors */ + u16_t s_minor_rev_level; /* minor revision level */ + u32_t s_lastcheck; /* time of last check */ + u32_t s_checkinterval; /* max. time between checks */ + u32_t s_creator_os; /* OS */ + u32_t s_rev_level; /* Revision level */ + u16_t s_def_resuid; /* Default uid for reserved blocks */ + u16_t s_def_resgid; /* Default gid for reserved blocks */ + + u32_t s_reserved[235]; +} ext2_super_block_t; + +typedef struct +{ + u32_t bg_block_bitmap; // Blocks bitmap block + u32_t bg_inode_bitmap; // Inode bitmap block + u32_t bg_inode_table; // Inode table block + u16_t bg_free_blocks_count; // Free blocks count + u16_t bg_free_inodes_count; // Free Inodes count + u16_t bg_used_dirs_count; // Directories count + u16_t bg_pad1; + u32_t bg_reserved[3]; +} ext2_group_desc_t; + +typedef struct +{ + u16_t i_mode; // File mode + u16_t i_uid; // Owner UID + u32_t i_size; // Size in bytes + u32_t i_atime; // Access time + u32_t i_ctime; // Creation time + u32_t i_mtime; // Modification time + u32_t i_dtime; // Deletion time + u16_t i_gid; // Group ID + u16_t i_links_count; // Links count + u32_t i_blocks; // Blocks count + u32_t i_flags; // File flags + u32_t i_reserved1; + u32_t i_block[15]; // Pointers to blocks (12 direct, single, double, triple indirect) + u32_t i_version; // File version (for NFS) + u32_t i_file_acl; // File ACL + u32_t i_dir_acl; // Directory ACL + u32_t i_faddr; // Fragment address + u8_t i_frag; // Fragment number + u8_t i_fsize; // Fragment size + u16_t i_pad1; + u32_t i_reserved2[2]; +} ext2_inode_t; + +typedef struct +{ + u32_t inode; // inode number + u16_t length; // directory entry length + u8_t name_length; // name length + u8_t file_type; // File type + char name[EXT2_NAME_LEN]; +} ext2_dir_entry_t; + +typedef struct +{ + ext2_inode_t inode; + u32_t block; + u32_t *block_pointers; + u32_t block_pointers_start; +} ext2_open_inode_t; + +typedef struct +{ + ext2_open_inode_t *open_inode; + u32_t position; +} ext2_open_dir_t; + +typedef struct +{ + ext2_open_inode_t *open_inode; + u32_t position; + u32_t buffer_start; + u32_t buffer_bytes; + u8_t *buffer; +} ext2__open_file_t; + +typedef struct +{ + ext2_open_inode_t *open_inode; + u32_t block; +} ext2__open_block_file_t; + +static inline u32_t ext2_diskToFSBlock(u32_t block, ext2_super_block_t *super) +{ + // convert # of disk blocks to # of filesystem blocks + return block >> (super->s_log_block_size + 1); +} + +static inline u32_t ext2_FSToDiskBlock(u32_t block, ext2_super_block_t *super) +{ + // convert # of filesystem blocks to # of disk blocks + return block << (super->s_log_block_size + 1); +} + + +int ext2_init(int fsID); +int ext2_read_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat); +int ext2_write_inode(vfs_mount_t *mount, u32_t inode, ext2_inode_t *dat); +ext2_group_desc_t ext2_get_group_desc(vfs_mount_t *mount, u32_t group); +void ext2_write_group_desc(vfs_mount_t *mount, u32_t group_num, ext2_group_desc_t *gd); +ext2_open_inode_t *ext2_open_inode(vfs_mount_t *mount, u32_t inode_number); +int ext2_close_inode(vfs_mount_t *mount, ext2_open_inode_t *open_inode); +int ext2_read_inode_block(vfs_mount_t *mount, ext2_open_inode_t *open_inode, void *block); +u32_t ext2_block_number(vfs_mount_t *mount, ext2_open_inode_t *open_inode); +int ext2_inode_seek(vfs_mount_t *mount, ext2_open_inode_t *open_inode, u32_t block_number); + +int ext2_inode_status(vfs_mount_t *mount, u32_t inode_number); +int ext2_block_status(vfs_mount_t *mount, u32_t block_number); + +u32_t ext2_alloc_inode(vfs_mount_t *mount); +int ext2_free_inode(vfs_mount_t *mount, u32_t inode_number); +u32_t ext2_alloc_block(vfs_mount_t *mount); +int ext2_free_block(vfs_mount_t *mount, u32_t block_number); + +u32_t ext2_reserve_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t bitmap_size); +int ext2_free_node(vfs_mount_t *mount, u32_t bitmap_block_num, u32_t node_number); +int ext2_num_block_groups(ext2_super_block_t *super); +void ext2_write_super(vfs_mount_t *mount); + +int ext2_resize_inode(vfs_mount_t *mount, u32_t inode_number, u32_t new_size); + +ext2_open_dir_t *ext2_open_dir(vfs_mount_t *mount, u32_t inode_number); +int ext2_dir_read_entry(vfs_mount_t *mount, ext2_open_dir_t *open_dir, ext2_dir_entry_t *dentry); +int ext2_close_dir(vfs_mount_t *mount, ext2_open_dir_t *open_dir); +int ext2_dir_lookup(vfs_mount_t *mount, u32_t dir_inode, char *fileName, ext2_dir_entry_t *direntry); + + +void *ext2_mount_super(major_t major, minor_t minor); +int ext2_umount_super(vfs_mount_t *mount); +int ext2_stat(vfs_mount_t *mount, u32_t inode_number, vfs_stat_t *stat); +u32_t ext2__get_root_dir_inode(vfs_mount_t *mount); +int ext2__link_deref(vfs_mount_t *mount, u32_t link_inode, char *link); +int ext2__free_inodes(vfs_mount_t *mount); +int ext2__total_inodes(vfs_mount_t *mount); +int ext2__free_blocks(vfs_mount_t *mount); +int ext2__total_blocks(vfs_mount_t *mount); + + +int ext2__open_dir(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *dir); +int ext2__read_dir(vfs_mount_t *mount, vfs_open_file_t *dir, vfs_dir_entry_t *dentry); +int ext2__close_dir(vfs_mount_t *mount, vfs_open_file_t *dir); + +int ext2__open_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file); +int ext2__read_file(vfs_mount_t *mount, vfs_open_file_t *open_file); +int ext2__close_file(vfs_mount_t *mount, vfs_open_file_t *open_file); + +int ext2__open_block_file(vfs_mount_t *mount, u32_t inode_number, vfs_open_file_t *open_file); +int ext2__read_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file, void *buffer); +int ext2__block_file_seek(vfs_mount_t *mount, vfs_open_file_t *open_file, u32_t block_number); +int ext2__close_block_file(vfs_mount_t *mount, vfs_open_file_t *open_file); + +#endif + diff --git a/kernel/fs/sysfs/sysfs.cpp b/kernel/fs/sysfs/sysfs.cpp index baa0f75..3ff960e 100644 --- a/kernel/fs/sysfs/sysfs.cpp +++ b/kernel/fs/sysfs/sysfs.cpp @@ -4,8 +4,6 @@ // Date: 06/27/05 // Modified: 06/27/05 -#define _HOS_CPP_ _HOS_CPP_ - extern "C" { #include "display/kout.h" } diff --git a/kernel/fs/sysfs/sysfs_entry.cpp b/kernel/fs/sysfs/sysfs_entry.cpp index 2d9bf7f..780b0f4 100644 --- a/kernel/fs/sysfs/sysfs_entry.cpp +++ b/kernel/fs/sysfs/sysfs_entry.cpp @@ -4,8 +4,6 @@ // Date: 06/27/05 // Modified: 06/27/05 -#define _HOS_CPP_ _HOS_CPP_ - #include "sysfs_entry.h" #include "lang/string.h" diff --git a/kernel/fs/vfs.cpp b/kernel/fs/vfs.cpp index 46ca940..8467845 100644 --- a/kernel/fs/vfs.cpp +++ b/kernel/fs/vfs.cpp @@ -4,8 +4,6 @@ // Date: 05/10/05 // Modified: 12/26/05 -#define _HOS_CPP_ _HOS_CPP_ - extern "C" { #include "hos_defines.h" #include "display/kout.h" @@ -26,13 +24,15 @@ extern "C" { FileSystem *vfs_attempt_mount(device_t device, char *fsType); mount_func_t vfs_get_mount_func(const string & fsName); inode_num_t vfs_get_inode(const string & path); +inode_num_t vfs_get_dir_inode(const string & path); inode_num_t vfs_get_inode_rel(const string & path, inode_num_t start_dir); inode_num_t vfs_get_dir_entry_inode(inode_num_t dir, const string & fname); int vfs_stat_inode(inode_num_t inum, vfs_stat_t *statptr); +int vfs_link_deref_inode(inode_num_t inum, char *link); VFSMount *vfs_get_mount(u32_t mt_id); vector vfs_split_dirs(const string & path); -OpenDirectory *vfs_open_directory_inode(inode_num_t inum); -OpenFile *vfs_open_file_inode(inode_num_t inum); +OpenDirectory *vfs_open_directory_inode(inode_num_t inum, int mode); +OpenFile *vfs_open_file_inode(inode_num_t inum, int mode); void vfs_close_directory_real(OpenDirectory *o); void vfs_close_file_real(OpenFile *o); inode_num_t vfs_get_real_inode(inode_num_t inum); @@ -140,23 +140,33 @@ int vfs_stat(char *name, vfs_stat_t *buff) { string sname = string(name); inode_num_t inum; - if ((inum = vfs_get_inode(sname)) == 0) + if ((inum = vfs_get_inode(sname)) == 0ULL) return -502; return vfs_stat_inode(inum, buff); } +/* dereference a symbolic link */ +int vfs_link_deref(char *name, char *buff) +{ + string sname = string(name); + inode_num_t inum; + if ((inum = vfs_get_inode(sname)) == 0ULL) + return -502; + return vfs_link_deref_inode(inum, buff); +} + void *vfs_open_dir(char *name) { string sname(name); inode_num_t inum = vfs_get_inode(sname); - return (void *) vfs_open_directory_inode(inum); + return (void *) vfs_open_directory_inode(inum, VFS_MODE_READ); } -void *vfs_open_file(char *name) +void *vfs_open_file(char *name, int mode) { string sname(name); inode_num_t inum = vfs_get_inode(sname); - return (void *) vfs_open_file_inode(inum); + return (void *) vfs_open_file_inode(inum, mode); } void vfs_close_dir(void *o) @@ -175,12 +185,6 @@ int vfs_read_dir(void *o, vfs_dir_entry_t *dirent) return odir->read(dirent); } -int vfs_write_dir(void *o, vfs_dir_entry_t *dirent) -{ - OpenDirectory *odir = (OpenDirectory *) o; - return odir->write(dirent); -} - int vfs_seek_dir(void *o, int pos, int mode) { OpenDirectory *odir = (OpenDirectory *) o; @@ -238,6 +242,19 @@ inode_num_t vfs_get_inode(const string & path) return vfs_get_inode_rel(path, 0ULL); } +/* Just get the inode of the directory containing the file */ +inode_num_t vfs_get_dir_inode(const string & path) +{ + vector paths = vfs_split_dirs(path); + string dirPath(""); + for (unsigned int i = 0; i < paths.size()-1; i++) + { + dirPath += "/"; + dirPath += paths[i]; + } + return vfs_get_inode_rel(dirPath, 0ULL); +} + /* Trace file name to inode starting from this directory (recursive) */ inode_num_t vfs_get_inode_rel(const string & path, inode_num_t start_dir) { @@ -257,7 +274,7 @@ inode_num_t vfs_get_inode_rel(const string & path, inode_num_t start_dir) /* return the inode of a directory entry in the directory pointed to by dir */ inode_num_t vfs_get_dir_entry_inode(inode_num_t dir, const string & fname) { - OpenDirectory *odir = vfs_open_directory_inode(dir); + OpenDirectory *odir = vfs_open_directory_inode(dir, VFS_MODE_READ); if (odir == NULL) return 0ULL; vfs_dir_entry_t dir_ent; @@ -337,24 +354,34 @@ int vfs_stat_inode(inode_num_t inum, vfs_stat_t *statptr) return mt->myFS->stat((u32_t)inum, statptr); } +/* FS function: dereference a link by inode number, return error code */ +int vfs_link_deref_inode(inode_num_t inum, char *link) +{ + inum = vfs_get_real_inode(inum); + VFSMount *mt = vfs_get_mount(inum >> 32); + if (mt == NULL) + return -501; + return mt->myFS->link_deref((u32_t)inum, link); +} + /* FS function: open a directory based on the inode number */ -OpenDirectory *vfs_open_directory_inode(inode_num_t inum) +OpenDirectory *vfs_open_directory_inode(inode_num_t inum, int mode) { inum = vfs_get_real_inode(inum); VFSMount *mt = vfs_get_mount(inum >> 32); if (mt == NULL) return NULL; - return mt->myFS->openDirectory((u32_t)inum); + return mt->myFS->openDirectory((u32_t)inum, mode); } /* FS function: open a file based on the inode number */ -OpenFile *vfs_open_file_inode(inode_num_t inum) +OpenFile *vfs_open_file_inode(inode_num_t inum, int mode) { inum = vfs_get_real_inode(inum); VFSMount *mt = vfs_get_mount(inum >> 32); if (mt == NULL) return NULL; - return mt->myFS->openFile((u32_t)inum); + return mt->myFS->openFile((u32_t)inum, mode); } /* FS function: close a directory */ diff --git a/kernel/fs/vfs.h b/kernel/fs/vfs.h index 3ebe25c..9198a54 100644 --- a/kernel/fs/vfs.h +++ b/kernel/fs/vfs.h @@ -32,11 +32,19 @@ #define EOF 0x100 #define VFS_MAX_FILENAME 255 +#define VFS_MAX_PATH_LENGTH 1024 #define SEEK_ABSOLUTE 0 #define SEEK_RELATIVE 1 #define SEEK_END 2 +#define VFS_MODE_RW_MASK 0x1 +#define VFS_MODE_READ 0x0 +#define VFS_MODE_WRITE 0x1 +#define VFS_MODE_WRITE_MASK 0x2 +#define VFS_MODE_TRUNCATE 0x0 +#define VFS_MODE_APPEND 0x2 + #include "hos_defines.h" #include "devices.h" @@ -82,13 +90,13 @@ int vfs_init(); int vfs_mount(device_t device, char *fsType, char *mountPoint); int vfs_umount(device_t dev); int vfs_stat(char *name, vfs_stat_t *buff); +int vfs_link_deref(char *name, char *buff); int vfs_get_mount_info(unsigned int mountNum, vfs_mount_info_t *infoptr); void *vfs_open_dir(char *name); -void *vfs_open_file(char *name); +void *vfs_open_file(char *name, int mode); void vfs_close_dir(void *o); void vfs_close_file(void *o); int vfs_read_dir(void *o, vfs_dir_entry_t *dirent); -int vfs_write_dir(void *o, vfs_dir_entry_t *dirent); int vfs_seek_dir(void *o, int pos, int mode); int vfs_read_file(void *o); int vfs_read_file_block(void *o, void *buf, u32_t num); diff --git a/kernel/kernel.c b/kernel/kernel.c index 95e672b..ae979ee 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -159,12 +159,12 @@ void k_init() } */ } - vfs_mount_info_t mt_info; - vfs_get_mount_info(0, &mt_info); - kprintf("%s, %s, %d, %d, %d, %d\n", mt_info.fs, mt_info.mountPoint, mt_info.totalBlocks, mt_info.freeBlocks, mt_info.totalInodes, mt_info.freeInodes); +// vfs_mount_info_t mt_info; +// vfs_get_mount_info(0, &mt_info); +// kprintf("%s, %s, %d, %d, %d, %d\n", mt_info.fs, mt_info.mountPoint, mt_info.totalBlocks, mt_info.freeBlocks, mt_info.totalInodes, mt_info.freeInodes); void *root = vfs_open_dir("///"); - char name[256]; + char name[VFS_MAX_PATH_LENGTH]; if (root) { vfs_dir_entry_t dentry; @@ -194,8 +194,7 @@ void k_init() if (fstat.type == VFS_FT_SYMLINK) { char *link = kmalloc(4096); - //vfs_link_deref(dentry.inode, link); - strcpy(link, "[a link]"); + vfs_link_deref(name, link); kprintf(" -> %s", link); kfree(link); } diff --git a/kernel/proc/hash.cpp b/kernel/proc/hash.cpp index 01e7f00..62c9b57 100644 --- a/kernel/proc/hash.cpp +++ b/kernel/proc/hash.cpp @@ -4,8 +4,6 @@ // Modified: 08/28/05 // Implements a basic hash table (u32_t -> void*) -#define __HOS_CPP__ - #include "hos_defines.h" #include "hash.h" #include "lang/vector.h" diff --git a/kernel/proc/proc.cpp b/kernel/proc/proc.cpp index 52b582c..f19a893 100644 --- a/kernel/proc/proc.cpp +++ b/kernel/proc/proc.cpp @@ -3,8 +3,6 @@ // Date; 08/18/05 // Modified: 08/18/05 -#define __HOS_CPP__ - extern "C" { #include "hos_defines.h" diff --git a/kernel/proc/proc.h b/kernel/proc/proc.h index 282f28b..84c2af5 100644 --- a/kernel/proc/proc.h +++ b/kernel/proc/proc.h @@ -6,7 +6,7 @@ #ifndef __HOS_PROC_H__ #define __HOS_PROC_H__ __HOS_PROC_H__ -#ifdef __HOS_CPP__ +#ifdef _HOS_CPP_ extern "C" { #endif @@ -81,7 +81,7 @@ void copy_into_address_space(u32_t dest_addr, process_t *p); void zero_address_space(u32_t dest_addr, u32_t pages, process_t *p); -#ifdef __HOS_CPP__ +#ifdef _HOS_CPP_ } #endif diff --git a/kernel/sys/pci.cpp b/kernel/sys/pci.cpp index 2d77e40..56bfdbb 100644 --- a/kernel/sys/pci.cpp +++ b/kernel/sys/pci.cpp @@ -3,8 +3,6 @@ // Date: 07/13/05 // Modified: 07/17/05 -#define _HOS_CPP_ - extern "C" { #include "hos_defines.h" #include "display/kout.h"