summaryrefslogtreecommitdiff
path: root/fs/ext2.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext2.c')
-rw-r--r--fs/ext2.c302
1 files changed, 120 insertions, 182 deletions
diff --git a/fs/ext2.c b/fs/ext2.c
index d99fba7..a167213 100644
--- a/fs/ext2.c
+++ b/fs/ext2.c
@@ -10,6 +10,7 @@
#include "fs.h"
+// THE SUPERBLOCK
typedef struct ext2_superblock_struct
{
uint32_t inodes_count;
@@ -35,7 +36,7 @@ typedef struct ext2_superblock_struct
uint16_t gid_reserved;
}ext2_superblock;
-/* we dont use this yet
+/* we dont use this
typedef struct ext2_superblock_ext_struct
{
uint32_t first_inode;
@@ -61,6 +62,7 @@ typedef struct ext2_superblock_ext_struct
}ext2_superblock_ext;
*/
+// BLOCKGROUP DESCRIPTOR TABLE
typedef struct ext2_blockgroup_desc_struct
{
uint32_t addr_block_bitmap;
@@ -97,271 +99,207 @@ typedef struct ext2_inode_struct
uint32_t indirect2;
uint32_t indirect3;
uint32_t gen_num;
- uint32_t later1; // will be implemented later by the fooldriver
+ uint32_t acl;
uint32_t size_high;
uint32_t frag;
uint32_t os_spec2[3];
}ext2_inode;
-
-void ram_read(char *in,char *out,int size, int count)
+static ext2_superblock *ext2_check(uint32_t ext2_start_addr)
{
- for(int i=0;i<size*count;i++)
- {
- out[i]=in[i];
+ ext2_superblock *super=ext2_start_addr+1024;
+ if(super->ext2_sig!=0xef53){
+ kpanic("no ext2 signature found, where ram-image expected at addr: 8X%08X",ext2_start_addr+1024);
}
+ return super;
}
-int ext2_check(uint8_t *ram)
+void ext2_dump_info(uint32_t ext2_start_addr)
{
- ext2_superblock super;
-// ext2_superblock_ext super_ext;
- uint8_t *ptr=ram+1024;
- ram_read((char*)ptr,&super,sizeof(super),1);
-
- if(super.ext2_sig!=0xef53){
- klog("addr: 0x%08X",ram);
- kpanic("no ext2 signature found, where ram-image expected");
- }
- return 1;
+ ext2_superblock *super=ext2_check(ext2_start_addr);
+ klog("ext2 fs version %d.%d found",super->version_major, super->version_minor);
+ klog("block_size %d",1024<<super->block_size);
+ klog("blocks per group %d",super->blocks_per_group);
+ klog("inodes per group %d",super->inodes_per_group);
+ klog("free inodes: %d / %d",super->inodes_unalloc_count,super->inodes_count+super->inodes_unalloc_count);
+ klog("free blocks: %d / %d (%d reserved)",super->blocks_unalloc_count,super->blocks_count+super->blocks_unalloc_count,super->blocks_reserved_count);
}
-ext2_inode ext2_get_inode(uint8_t *ram,int inode_num)
+// inode numbers start a 1!
+ext2_inode *ext2_get_inode(uint32_t ext2_start_addr,uint32_t inode_num)
{
+ uint32_t ptr; //will temporarily hold adress of some structs
- // get basic shit from superblock!
- ext2_superblock super;
- ext2_blockgroup_desc desc;
- ext2_inode inode;
-
- uint8_t *ptr=ram+1024;
- ram_read((char*)ptr,&super,sizeof(super),1);
- if(super.ext2_sig!=0xef53)
- {
- klog("addr: 0x%08X",ram);
- kpanic("no ext2 signature found, where ram-image expected!");
- }
-
- int block_group=(inode_num-1)/super.inodes_per_group;
+ // check signature and get pointer to superblock.
+ ext2_superblock *super=ext2_check(ext2_start_addr);
- // get descrtptor for our blockgroup!
- //TODO: only correct for 1024bytes/block. read more than one!!!
- int block_size=1024;
- int descriptor_start_block=2;
+ // get blockgroup descriptor for the block group containing
+ // our inode.
+ int block_group=(inode_num-1)/super->inodes_per_group;
+ int descriptor_start_block=1024<<super->block_size==1024?2:1;
- ptr=ram+block_size*descriptor_start_block;
- ptr+=sizeof(desc)*block_group; // skip to our descriptor;
+ ptr=ext2_start_addr+(1024<<super->block_size)*descriptor_start_block;
+ ptr+=sizeof(ext2_blockgroup_desc)*block_group; // skip to descriptor for our inode's block
+ ext2_blockgroup_desc *desc=ptr;
- ram_read((char*)ptr,&desc,sizeof(desc),1); // read descriptor
-
- // read our inode;
- ptr=ram+block_size*desc.addr_inode_table;
- ptr+=128*((inode_num-1)%super.inodes_per_group);
-
- ram_read((char*)ptr,&inode,sizeof(inode),1); //get inode 2 (rood-directory)
+ // read the inode
+ ptr=ext2_start_addr+(1024<<super->block_size)*desc->addr_inode_table;
+ ptr+=128*((inode_num-1)%super->inodes_per_group);
+ ext2_inode *inode=ptr;
return inode;
-
}
-void* ext2_get_blockstart(void* start, uint32_t block_size, uint32_t block_idx)
+static void* ext2_get_blockstart(void* start, uint32_t block_size, uint32_t block_idx)
{
return (start+block_size*block_idx);
}
-void* ext2_get_indirectstart(void *start, uint32_t block_size, uint32_t indirect1_idx, uint32_t block_idx)
+static void* ext2_get_indirectstart(void *start, uint32_t block_size, uint32_t indirect1_idx, uint32_t block_idx)
{
uint32_t *indirect_ptr=ext2_get_blockstart(start,block_size,indirect1_idx);
void *ptr=ext2_get_blockstart(start,block_size,indirect_ptr[block_idx]);
return ptr;
}
-void* ext2_get_indirectstart_double(void *start, uint32_t block_size, uint32_t indirect2_idx, uint32_t block_idx)
+static void* ext2_get_indirectstart_double(void *start, uint32_t block_size, uint32_t indirect2_idx, uint32_t block_idx)
{
-
//doubly indirect list
uint32_t *dil=ext2_get_blockstart(start,block_size,indirect2_idx);
int indirect1_idx=block_idx/(block_size/4);
int idx=block_idx%(block_size/4);
- //klog("bl: %d : %d / %d",block_idx,indirect1_idx, idx);
return ext2_get_indirectstart(start,block_size,dil[indirect1_idx],idx);
}
-int ext2_inode_content(char *ram,int inode_nr,uint8_t *ramdest,int max)
+//
+uint32_t ext2_inode_blockstart(uint32_t ext2_start_addr,uint32_t inode_nr,uint32_t block)
{
- ext2_check((uint8_t *)ram);
- ext2_inode inode=ext2_get_inode((uint8_t*)ram,inode_nr);
-
- int pos=0;
- int block=0;
- int block_size=1024;
- int block_counter=0;
- uint8_t *ptr=ext2_get_blockstart(ram,block_size,inode.direct_pointer[0]);
- int sum=0;
- int count=0;
+ ext2_superblock *super=ext2_check(ext2_start_addr);
+ int block_size=1024<<super->block_size;
- klog("Loading %d.%d bytes",inode.size_high, inode.size_low);
+ ext2_inode *inode=ext2_get_inode(ext2_start_addr,inode_nr);
- if(inode.size_high>0)kpanic("inode with high.size unsupported, i am sorry.");
+ uint8_t *ptr=0;
- while(pos<inode.size_low) // TODO: use size high!
+ if(block<12)
{
- ramdest[pos]=*ptr;
-
- sum = (sum >> 1) + ((sum & 1) << 15);
- sum+=(int)*ptr;
- sum&=0xffff;
- count++;
-
- ptr++;
- block_counter++;
- pos++;
-
- if(block_counter>=block_size)
- {
- block++;
-
- if(block<12)
- {
- ptr=ext2_get_blockstart(ram,block_size,inode.direct_pointer[block]);
-
- }
- else if(block-12<block_size/4)
- {
- ptr=ext2_get_indirectstart(ram,block_size,inode.indirect1,block-12);
- }
-
- else if(block-12-block_size/4<1024/4*1024/4)
- {
- ptr=ext2_get_indirectstart_double(ram,block_size,inode.indirect2,block-12-block_size/4);
- }
- else
- {
- kpanic("Triple Indirect Block Pointers not supported yet, file is too big to load, sorry!");
- }
-
-
- block_counter=0;
- }
-
-
+ ptr=ext2_get_blockstart(ext2_start_addr,block_size,inode->direct_pointer[block]);
}
- klog("Fool Check Sum: 0x%08X for %d bytes",sum,count);
- return 1;
+ else if(block-12<block_size/4)
+ {
+ ptr=ext2_get_indirectstart(ext2_start_addr,block_size,inode->indirect1,block-12);
+ }
+
+ else if(block-12-block_size/4<1024/4*1024/4)
+ {
+ ptr=ext2_get_indirectstart_double(ext2_start_addr,block_size,inode->indirect2,block-12-block_size/4);
+ }
+
+ return ptr;
}
-int ext2_filename_to_inode_traverse(uint8_t *ram, char *path,int inode_start)
+static uint32_t ext2_filename_to_inode_traverse(uint32_t ext2_start_addr, char *path,uint32_t inode_start)
{
+ uint32_t len=0;
+ // true if final filename
bool final=false;
// skip leading slashes
while(*path=='/')path++;
char *first=path;
- while(*path!='/'&&*path!=0)path++;
- char *last=path;
+ // find end of dir or file name
+ while(path[len]!='/'&&path[len]!=0)len++;
- if(*path==0)final=true;
- else(*path=0);
+ // no more slashes
+ if(path[len]==0)final=true;
- klog("looking for %s '%s' in inode: %d",final?"file":"dir",first,inode_start);
+ //klog("looking for %s '%s' in inode: %d",final?"file":"dir",first,inode_start);
- fs_dirent dirs[25];
- int count= ext2_read_dir(ram, inode_start,dirs,25); // get dir
-
- for(int i=0;i<count;i++)
+ uint32_t pos=0;
+ while(1)
{
- if(!strcmp_l(first,dirs[i].name,0))
+ fs_dirent dirs;
+ uint32_t ret=ext2_read_dir(VMEM_EXT2_RAMIMAGE,inode_start, &dirs,&pos);
+ if(!ret)break;
+
+ if(!strcmp_l(first,dirs.name,len))
{
- klog("found: %s (%s)",first,dirs[i].type==FS_FILE_TYPE_DIR?"dir":"file");
- if(final)return dirs[i].inode;
- return ext2_filename_to_inode_traverse(ram,last+1,dirs[i].inode);
+ klog("found inode %d %s%s (in inode %d)",dirs.inode,dirs.name,dirs.type==FS_FILE_TYPE_DIR?"/ ":" ",inode_start);
+ if(final)return dirs.inode;
+ return ext2_filename_to_inode_traverse(ext2_start_addr,&path[len]+1,dirs.inode);
}
- //klog("no match: %s",dirs[i].name);
}
-
klog("file not found!");
- return -1;
-
-
-
+ return 0;
}
-int ext2_filename_to_inode(uint8_t *ram, char *path)
-{
+uint32_t ext2_filename_to_inode(uint32_t ext2_start_addr, char *path)
+{
if(!strcmp_l(path,"/",0))return 2; // root is inode 2 by definition
-
- char buf[256];
- for(int i=0;i<256;i++)
- {
- buf[i]=path[i];
- if(buf[i]==0)break;
- }
-
- return ext2_filename_to_inode_traverse(ram,buf,2);
+ return ext2_filename_to_inode_traverse(ext2_start_addr,path,2);
}
-int ext2_read_dir(uint8_t *ram, int inode_nr,fs_dirent *dirs,int max)
+uint32_t ext2_read_inode(uint32_t ext2_start_addr, int inode_nr, char *buf, uint32_t *pos, uint32_t max_size)
{
+ uint32_t count=0;
- klog("read_dir : max: %d",max);
- ext2_inode inode=ext2_get_inode(ram,inode_nr);
-
- char buf[256];
- int block_size=1024;
- uint8_t *ptr=ram+block_size*inode.direct_pointer[0]; //TODO: use other pointers in future!
-
- int pos=0;
- int c=0;
+ ext2_superblock *super=ext2_check(ext2_start_addr);
+ ext2_inode *inode=ext2_get_inode(ext2_start_addr,inode_nr);
+ uint32_t block_size=1024<<super->block_size;
- while(pos<inode.size_low) // use size high?
+ while((*pos)<inode->size_low)
{
- if(c==max)break;
+ if(count==max_size)return count;
- // read dir data
- ext2_dir dir;
- ram_read((char*)ptr,&dir,sizeof(dir),1);
+ // get ptr to pos
+ uint32_t block=(*pos)/block_size;
+ uint32_t ptr = ext2_inode_blockstart(ext2_start_addr,inode_nr,block)+((*pos)%block_size);
- // read name
- ptr+=sizeof(dir);
- ram_read((char*)ptr,&buf,sizeof(char),dir.name_length_low);
- ptr+=dir.name_length_low;
- buf[dir.name_length_low]=0;
+ buf[count]=*((char *)ptr);
- // increment memory pointer and position
- ptr+=dir.size-8-dir.name_length_low;
- pos+=dir.size;
+ *pos+=1;
+ count++;
+ }
- // copy data over to dirs
- dirs[c].inode=dir.inode;
+ return count;
- ext2_inode inode_current=ext2_get_inode(ram,dir.inode);
+}
- if(inode_current.permissions&0x4000)
- {
- dirs[c].type=FS_FILE_TYPE_DIR;
- }
- else
- {
- dirs[c].type=FS_FILE_TYPE_FILE;
- }
+int ext2_read_dir(uint32_t ext2_start_addr, int inode_nr, fs_dirent *dirs, uint32_t *pos)
+{
+ ext2_superblock *super=ext2_check(ext2_start_addr);
+ ext2_inode *inode=ext2_get_inode(ext2_start_addr,inode_nr);
+ uint32_t block_size=1024<<super->block_size;
- int i=0;
- do{
- dirs[c].name[i]=buf[i];
- i++;
- }while(buf[i-1]!=0);
+ while(*pos<inode->size_low)
+ {
+ // get ptr to pos
+ uint32_t block=(*pos)/block_size;
+ uint32_t ptr = ext2_inode_blockstart(ext2_start_addr,inode_nr,block)+((*pos)%block_size);
-// klog("name: %s\n",dirs[c].name);
+ //dir data
+ ext2_dir *dir=ptr;
- c++;
+ if(dir->inode) //otherwise skip
+ {
+ dirs->type=FS_FILE_TYPE_FILE;
+ ext2_inode *inode_current=ext2_get_inode(ext2_start_addr,dir->inode);
+ if(inode_current->permissions&0x4000)dirs->type=FS_FILE_TYPE_DIR;
+ memcpy(dirs->name,ptr+8,dir->name_length_low);
+ if(dir->name_length_low>255)dirs->name[255]=0;
+ dirs->name[dir->name_length_low]=0; // null temrinate
+ dirs->inode=dir->inode;
+
+ *pos+=dir->size;
+ return 1;
+ }
+ *pos+=dir->size;
}
-
- return c;
-
+ return 0;
}