view src/fs.c @ 37:b2bb007e5789

The filesytem stuff actually does something now The code is still messy but for now, I shall focus on laundry (and after that, sleep) Once the user enters the filename, this now dumps the entire contents of the file to the screen. It would be nice to have this wait for the user to push enter or something, not sure how possible that is though...
author Jonathan Pevarnek <pevarnj@gmail.com>
date Fri, 08 Apr 2011 00:22:44 -0400
parents 3acc1f944c7b
children 4f8e3bb19646
line wrap: on
line source

#include <std.h>

struct SUPERBLOCK {
	u32 magic;              // == 0x42420374
	u32 root_inode;         // the disk block containing the root inode
	u32 nblocks;            // number of block on the disk
	u32 _pad[253];          // unused (should be '\0' filled)
};
typedef struct SUPERBLOCK Superblock;

struct INODE {
	u32 size;               // file length in bytes
	u32 _pad0;              // unused (should be 0)
	u64 ctime;              // creation time stamp
	u64 mtime;              // last modification time stamp
	u16 nblocks;            // number of data blocks in this file
	u16 _pad1;              // unused (should be 0)
	u32 _pad2;              // unused (should be 0)
	u32 blocks[248];        // file block ptrs
};
typedef struct INODE Inode;

struct DIRENTRY { //32 bytes
	char fname[28];
	u32 inode;
};
typedef struct DIRENTRY Direntry;

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

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

//Sets name to contain a filename entered by the user
//REQUIRES:   name 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;
}

//Finds the item within an array of filenames with the same name as fname
int fnameLookup(char *fname, const Direntry array[], int last)
{
	int i;
	for(i = 0; i < last; i++)
		if(!fnameCmp(fname, array[i].fname)) return i;
	return last;
}

void dumpText(char *text, int size)
{
	do {
		putline(text, (size > CON_LEN)?CON_LEN:size);
		size -= CON_LEN;
		text += CON_LEN;
	} while(size > 0);
}

void start(u64 __memsize)
{
	sPrint(""); //I have no idea why I would possibly need this...
	char buffer[256];
	int i;
	
	u32 dev = find_dev(0x100);
	Superblock sb;
	if(readFSBlock(dev, 1, &sb)) { //get the super block
		sPrint("ERROR\n");
		goto END;
	}
	Inode root;
	if(readFSBlock(dev, sb.root_inode, &root)) { //get the root inode
		sPrint("ERROR\n");
		goto END;
	}
	int nFiles = root.size/sizeof(Direntry);
		//calculate how many files (assume less than 32 for the moment)
		//TODO get rid of assumption
	Direntry direntries[32];
	if(readFSBlock(dev, root.blocks[0], direntries)) { //get the "first 32" files
		sPrint("ERROR\n");
		goto END;
	}

	while(1) {
		
		//Prints off the name of each file
		Direntry *dp;
		for(dp = direntries; dp - direntries < nFiles; dp++) {
			printFname(dp->fname), sPrint("\n");
		}
		char fname[28];
		sPrint("Please enter the file to read: ");
		getFname(fname);
		int file = fnameLookup(fname, direntries, nFiles);

		u32 fileLoc = direntries[file].inode;

		Inode fileToRead;
		if(readFSBlock(dev, fileLoc, &fileToRead)) {
			sPrint("ERROR\n");
			goto END;
		}

		u32 fileSize = fileToRead.size;
		const u32 origFileSize = fileSize;

		for(i = 0; i < fileToRead.nblocks; i++) {
			char text[1024];
			if(readFSBlock(dev, fileToRead.blocks[i], text)) {
				sPrint("ERROR\n");
				goto END;
			}
			dumpText(text, (fileSize > 1024)?1024:fileSize);
			fileSize -= 1024;
		}
	}


END:
	sPrint("DONE\n");
	for(;;) {
		char buffer[1];
		sGet(buffer, 0);
	}
}