Import backup from 2005-12-30
This commit is contained in:
parent
761e3f0483
commit
712337c485
1
initrd/link
Symbolic link
1
initrd/link
Symbolic link
@ -0,0 +1 @@
|
||||
test_file
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -3,8 +3,6 @@
|
||||
// Date: 08/20/04
|
||||
// Modified: 05/11/05
|
||||
|
||||
#define _HOS_CPP_ _HOS_CPP_
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "functions.h"
|
||||
|
@ -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"
|
||||
|
@ -3,8 +3,6 @@
|
||||
// Date: 08/02/04
|
||||
// Modified: 05/11/05
|
||||
|
||||
#define _HOS_CPP_ _HOS_CPP_
|
||||
|
||||
extern "C"
|
||||
{
|
||||
#include "hos_defines.h"
|
||||
|
@ -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"
|
||||
|
@ -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;}
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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
|
||||
|
@ -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; }
|
||||
|
@ -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,
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "lang/string.h"
|
||||
#include "devices.h"
|
||||
#include "FileSystem.h"
|
||||
#include "fs/vfs.h"
|
||||
|
||||
class VFSMount
|
||||
{
|
||||
|
147
kernel/fs/ext2/Ext2BlockCache.cpp
Normal file
147
kernel/fs/ext2/Ext2BlockCache.cpp
Normal file
@ -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];
|
||||
}
|
34
kernel/fs/ext2/Ext2BlockCache.h
Normal file
34
kernel/fs/ext2/Ext2BlockCache.h
Normal file
@ -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
|
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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 */
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
};
|
||||
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
332
kernel/fs/ext2/ext2_working.c
Normal file
332
kernel/fs/ext2/ext2_working.c
Normal file
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
241
kernel/fs/ext2/ext2_working.h
Normal file
241
kernel/fs/ext2/ext2_working.h
Normal file
@ -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
|
||||
|
@ -4,8 +4,6 @@
|
||||
// Date: 06/27/05
|
||||
// Modified: 06/27/05
|
||||
|
||||
#define _HOS_CPP_ _HOS_CPP_
|
||||
|
||||
extern "C" {
|
||||
#include "display/kout.h"
|
||||
}
|
||||
|
@ -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"
|
||||
|
||||
|
@ -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<string> 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<string> 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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -3,8 +3,6 @@
|
||||
// Date; 08/18/05
|
||||
// Modified: 08/18/05
|
||||
|
||||
#define __HOS_CPP__
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "hos_defines.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
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user