view src/fs.c @ 54:39fcefab46ed

Modified the init_fs function to take advantage of dynamic memory init_fs (renamed) now takes advantage of dynamic memory and allocates space for exactly as many direntries as it needs to keep track of TODO redo caching to Jeff's far superior idea
author Jonathan Pevarnek <pevarnj@gmail.com>
date Sat, 09 Apr 2011 21:55:59 -0400
parents b22b6a83cf04
children 25be3895c62a
line wrap: on
line source

#include <fs.h>
#include <std.h>

static int loadToCache(u32 fid);
static int readFSBlock(u32 dev, u32 blkno, void *fsBlock);

static u32 DevID;
static Direntry *Direntries = NULL;
static int NFiles;

static u32 CacheID = 0;
static Inode Cached;

int init_fs(u32 devnum)
{
	DevID = find_dev(0x100);
	Superblock sb; //the superblock
	if(readFSBlock(DevID, 1, &sb)) return -1;
	Inode rootINode;
	if(readFSBlock(DevID, sb.root_inode, &rootINode)) return -1;
	NFiles = rootINode.size/sizeof(Direntry);
	Direntries = malloc(rootINode.size);
	if(getFData(sb.root_inode, Direntries)) return -1;
	return 0;
}

void listFiles()
{
	Direntry *dp;
	for(dp = Direntries; dp - Direntries < NFiles; dp++)
		printFname(dp->fname), putline("\n", 1);
}

u32 lookupFile(char *fname)
{
	Direntry *dp;
	for(dp = Direntries; dp - Direntries < NFiles; dp++) {
		if(!fnameCmp(fname, dp->fname)) {
			return dp->inode;
		}
	}
	return 0;
}

//REQUIRES:   Valid loadable fid
//This sets *size equal to the size of the file.  Will return 0 an success
int getFSize(u32 fid, u32 *size)
{
	if(loadToCache(fid)) return -1;
	*size = Cached.size;
	return 0;
}

//REQUIRES:   ptr is large enough to hold everything
int getFData(u32 fid, void *ptr)
{
	int i;
	loadToCache(fid);
	u32 size = Cached.size;
	u16 nBlocks = Cached.nblocks;
	for(i = 0; i < nBlocks; i++) {
		if(size >= 1024) {
			if(readFSBlock(DevID, Cached.blocks[i], ptr)) return -1;
			ptr += 1024;
			size -= 1024;
		} else {
			u8 *point = ptr;
			u8 buffer[1024];
			if(readFSBlock(DevID, Cached.blocks[i], buffer)) return -1;
			for(i = 0; i < size; i++, point++) {
				*point = buffer[i];
			}
			break; //it should do this anyways but...
		}
	}
	return 0;
}

short isBlockAt(u32 block)
{ //TODO reconsider return value
	u32 inBlock = block/0x2000 + 2; //which block the bit is in
	u32 blockSpot = (block%0x2000)/8; //which u8 the bit is in
	u32 spotSpot = 7 - block%8; //which bit the bit is
	u8 buffer[1024];
	if(readFSBlock(DevID, inBlock, buffer)) return -1; //TODO should this be optimized and only read one block?
	return (buffer[blockSpot] >> spotSpot) & 1;
}

void printFname(char *name)
{
	putline(name, 28);
}

//Sets name to contain a filename entered by the user
//REQUIRES:   fname is 28 characters long
void getFname(char *fname)
{
	int chars = getline(fname, 28);
	for(;chars < 28; chars++) {
		fname[chars] = ' ';
	}
}

//Checks whether two file names are equal
int fnameCmp(const char *a, const char *b)
{
	int i;
	for(i = 0; i < 28; i++, a++, b++) {
		if(*a - *b) return *a - *b;
	}
	return 0;
}

static int loadToCache(u32 fid)
{
	if(CacheID == fid) return 0;
	if(readFSBlock(DevID, fid, &Cached)) return -1;
	CacheID = fid;
	return 0;
}

//REQUIRES:   fsBlock points to an object with size at least 1024
//EFFECTS:    Sets fsBlock to be equal
static int readFSBlock(u32 dev, u32 blkno, void *fsBlock)
{
	//assert(isBlockAt(blkno)); //DO NOT UNCOMMENT
	if(fba_read_blk(dev, blkno*2, fsBlock)) return 1;
	if(fba_read_blk(dev, blkno*2 + 1, fsBlock + 512)) return 1;
	return 0;
}