changeset 91:8479bfdeb375

merge
author Jonathan Pevarnek <pevarnj@gmail.com>
date Thu, 12 May 2011 13:25:58 -0400
parents 5e5bc76f0cdc (diff) f9ae64d35e81 (current diff)
children effa07f3c157
files
diffstat 23 files changed, 1509 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Thu May 12 13:23:21 2011 -0400
+++ b/.hgignore	Thu May 12 13:25:58 2011 -0400
@@ -3,6 +3,12 @@
 \.rto$
 ^ipl/ipl_ccws\.S$
 ^sarpn$
+^dynamic$
+^testFS$
 ^loader\.bin$
 ^cscope\.out$
 \.swp$
+
+^hercules/curDisk\.img$
+
+^changes
--- a/Makefile	Thu May 12 13:23:21 2011 -0400
+++ b/Makefile	Thu May 12 13:25:58 2011 -0400
@@ -11,9 +11,11 @@
 CXXFLAGS=$(CFLAGS)
 LDFLAGS=-m elf64_s390
 
-BINS=sarpn
+BINS=sarpn dynamic testFS
 
-sarpn_OBJS=src/init.o arch/arch.a
+sarpn_OBJS=src/sarpn.o src/std.o src/stack.o src/operations.o src/math.o arch/arch.a
+dynamic_OBJS=src/dynamic.o src/std.o src/stack.o arch/arch.a
+testFS_OBJS=src/testFS.o src/std.o src/fs.o arch/arch.a
 
 ARCH_OBJS=arch/io.o arch/cons.o arch/ebcdic.o arch/fba.o arch/ioint.o \
 	  arch/svc.o arch/svcint.o
@@ -26,15 +28,22 @@
 
 clean:
 	rm -f $(sarpn_OBJS)
+	rm -f $(dynamic_OBJS)
+	rm -f $(testFS_OBJS)
 	rm -f $(ARCH_OBJS)
 	rm -f $(BINS)
 	rm -f loader.bin ipl/*.o ipl/*.rto ipl/ipl_ccws.S cscope.out
 
 tags:
 	cscope -R -b
+	ctags -R
 
 sarpn: $(sarpn_OBJS)
 	$(LD) $(LDFLAGS) -T scripts/linker.script -o $@ $^
+dynamic: $(dynamic_OBJS)
+	$(LD) $(LDFLAGS) -T scripts/linker.script -o $@ $^
+testFS: $(testFS_OBJS)
+	$(LD) $(LDFLAGS) -T scripts/linker.script -o $@ $^
 
 arch/arch.a: $(ARCH_OBJS)
 	$(AR) rc $@ $^
@@ -79,3 +88,19 @@
 
 ipl/%.o: ipl/%.S
 	$(AS) -m64 -o $@ $<
+
+depend:
+	makedepend -I include src/*.c
+
+# DO NOT DELETE
+
+src/dynamic.o: include/std.h include/die.h include/operations.h
+src/dynamic.o: include/stack.h
+src/fs.o: include/fs.h include/std.h include/die.h include/error.h
+src/fs.o: include/tod.h
+src/operations.o: include/operations.h include/std.h include/die.h
+src/operations.o: include/stack.h include/math.h
+src/sarpn.o: include/std.h include/die.h include/operations.h include/stack.h
+src/stack.o: include/stack.h include/std.h include/die.h
+src/std.o: include/std.h include/die.h
+src/testFS.o: include/std.h include/die.h include/fs.h include/error.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hercules/dynamic.cnf	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,20 @@
+CPUSERIAL 314359        # CPU serial number
+CPUMODEL  2097          # CPU model number
+MAINSIZE  128           # Main storage size in megabytes
+XPNDSIZE  0             # Expanded storage size in megabytes
+CNSLPORT  3270          # TCP port number to which consoles connect
+NUMCPU    1             # Number of CPUs
+#OSTAILOR  QUIET         # OS tailoring
+OSTAILOR  NULL          # OS tailoring
+PANRATE   SLOW          # Panel refresh rate
+
+# .-----------------------Device number
+# |     .-----------------Device type
+# |     |       .---------File name and parameters
+# |     |       |
+# V     V       V
+#---    ----    --------------------
+0009	3215	
+000C    3505	../loader.bin ../dynamic ebcdic multifile eof
+
+0100	9336	disk.img
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hercules/fs.cnf	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,20 @@
+CPUSERIAL 314359        # CPU serial number
+CPUMODEL  2097          # CPU model number
+MAINSIZE  128           # Main storage size in megabytes
+XPNDSIZE  0             # Expanded storage size in megabytes
+CNSLPORT  3270          # TCP port number to which consoles connect
+NUMCPU    1             # Number of CPUs
+#OSTAILOR  QUIET         # OS tailoring
+OSTAILOR  NULL          # OS tailoring
+PANRATE   SLOW          # Panel refresh rate
+
+# .-----------------------Device number
+# |     .-----------------Device type
+# |     |       .---------File name and parameters
+# |     |       |
+# V     V       V
+#---    ----    --------------------
+0009	3215	
+000C    3505	../loader.bin ../testFS ebcdic multifile eof
+
+0100	9336	curDisk.img
--- a/hercules/herc.cnf	Thu May 12 13:23:21 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-CPUSERIAL 314359        # CPU serial number
-CPUMODEL  2097          # CPU model number
-MAINSIZE  128           # Main storage size in megabytes
-XPNDSIZE  0             # Expanded storage size in megabytes
-CNSLPORT  3270          # TCP port number to which consoles connect
-NUMCPU    1             # Number of CPUs
-#OSTAILOR  QUIET         # OS tailoring
-OSTAILOR  NULL          # OS tailoring
-PANRATE   SLOW          # Panel refresh rate
-
-# .-----------------------Device number
-# |     .-----------------Device type
-# |     |       .---------File name and parameters
-# |     |       |
-# V     V       V
-#---    ----    --------------------
-0009	3215	
-000C    3505	../loader.bin ../sarpn ebcdic multifile eof
-
-0100	9336	disk.img
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hercules/sarpn.cnf	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,20 @@
+CPUSERIAL 314359        # CPU serial number
+CPUMODEL  2097          # CPU model number
+MAINSIZE  128           # Main storage size in megabytes
+XPNDSIZE  0             # Expanded storage size in megabytes
+CNSLPORT  3270          # TCP port number to which consoles connect
+NUMCPU    1             # Number of CPUs
+#OSTAILOR  QUIET         # OS tailoring
+OSTAILOR  NULL          # OS tailoring
+PANRATE   SLOW          # Panel refresh rate
+
+# .-----------------------Device number
+# |     .-----------------Device type
+# |     |       .---------File name and parameters
+# |     |       |
+# V     V       V
+#---    ----    --------------------
+0009	3215	
+000C    3505	../loader.bin ../sarpn ebcdic multifile eof
+
+0100	9336	disk.img
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/error.h	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,40 @@
+#ifndef __ERROR_H
+#define __ERROR_H
+
+#define mkError(mod,code,sev) (((mod) << 12) | ((code) << 2) | (sev))
+#define isError(code) (((code) & 3) == ERROR)
+#define errCode(code) (((code) >> 2) & 1023)
+#define makeWarn(code) (isError(code)?((((code) >> 2) << 2) | WARN):code) //convert an error into a warning
+
+//Severities
+#define INFO 0
+#define WARN 1
+#define ERROR 2
+
+//Modules
+#define MODFS 1 //stuff in the file system
+#define MODTOD 2 //Time of date
+
+#define NOERROR 0 //General error code for not an error
+
+//Codes: filesystem
+#define ALLOCFAIL 1 //a general code for a malloc failing
+#define OUTOFRANGE 2 //
+#define MUGGLE 3 //The magic code in the superblock was not set correctly
+#define BLKREADFAIL 4 //failure for reading a filesystem block
+#define NOTFILE 5
+#define BLKWRITEFAIL 6 //failure to write a filesystem block
+#define SIZETOOLARGE 7 //the user requested a size that is too large to be set for a file
+#define NOTINCACHE 8
+#define DISKFULL 9 //every block on the disk is currently set to be in use
+#define EXISTS 10 //the user tried to create a file that already exists
+
+//Codes: Time of date
+#define UPTIME 1 //the actual time of date was not set in the system
+#define INVALID 2
+
+
+typedef u32 ErrCode;
+
+#endif //__ERROR_H
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/fs.h	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,66 @@
+#include <std.h>
+#include <error.h>
+
+#ifndef __FS_H
+#define __FS_H
+
+#define CACHESPACE 1 //percentage of heap to use for the FS Cache
+#define FNAMELEN 28 //How long the filenames are
+#define FSBLKSIZE 1024
+#define DSKBLKSIZE 512
+#define MAXBLOCKS 248
+#define FSMAGICNUM 0x42420374
+#define DEPBLK (FSBLKSIZE / sizeof(Direntry)) //director entries per block
+
+#define ERR_FSBLKREADFAIL mkError(MODFS, BLKREADFAIL, ERROR)
+
+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[MAXBLOCKS];  // file block ptrs
+};
+typedef struct INODE Inode;
+
+struct FSBLK {
+	u8 blocks[FSBLKSIZE];
+};
+typedef struct FSBLK FSBlk;
+
+struct DSKBLK {
+	u8 blocks[DSKBLKSIZE];
+};
+typedef struct DSKBLK DskBlk;
+
+struct DIRENTRY { //32 bytes
+	char fname[FNAMELEN];
+	u32 inode;
+};
+typedef struct DIRENTRY Direntry;
+
+ErrCode init_fs(u32 devnum, u64 __memsize);
+ErrCode getFInfo(u32 n, void* de);
+ErrCode lookupFile(char *fname, u32 *fid);
+ErrCode makeFile(char *fname, u32 *fid);
+ErrCode deleteFile(u32 fid);
+ErrCode fileAppend(u32 fid, void *data, u32 length);
+ErrCode fileWrite(u32 fid, void *data, u32 length, u32 offset);
+ErrCode getFileSize(u32 fid, u32 *size);
+ErrCode getFileData(u32 fid, void *ptr);
+void printFname(char *name);
+void getFname(char *fname);
+int fnameCmp(const char *a, const char *b);
+
+#endif //__FS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/math.h	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,14 @@
+#ifndef __MATH_H
+#define __MATH_H
+
+double iPow(double base, int exponent);
+double exp(double exp);
+double log(double num);
+double pow(double base, double exponent);
+
+double math_add(double first, double sec);
+double math_sub(double first, double sec);
+double math_mult(double first, double sec);
+double math_div(double first, double sec);
+
+#endif //__MATH_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/operations.h	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,26 @@
+#ifndef __OPERATIONS_H
+#define __OPERATIONS_H
+
+#include <std.h>
+#include <stack.h>
+
+enum Operation {PRINT, ADD, SUB, MULT, DIV, POW, DUP, DROP, LOG, EXP, SWAP, MAXOP};
+extern const char operationNames[MAXOP][10];
+extern void (*operation[MAXOP])(Stack*);
+
+void op_math1(Stack *stack, eltType (*mathop)(eltType));
+void op_math2(Stack *stack, eltType (*mathop)(eltType, eltType));
+
+void op_print(Stack *stack);
+void op_add(Stack *stack);
+void op_sub(Stack *stack);
+void op_mult(Stack *stack);
+void op_div(Stack *stack);
+void op_pow(Stack *stack);
+void op_dup(Stack *stack);
+void op_drop(Stack *stack);
+void op_log(Stack *stack);
+void op_exp(Stack *stack);
+void op_swap(Stack *stack);
+
+#endif //__OPERATIONS_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/stack.h	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,25 @@
+#ifndef __STACK_H
+#define __STACK_H
+
+typedef double eltType;
+
+struct STACKELT {
+	eltType elt;
+	struct STACKELT *next;
+};
+typedef struct STACKELT StackElt;
+
+struct STACK {
+	StackElt* top;
+	unsigned int size;
+};
+typedef struct STACK Stack;
+
+short pop(Stack *stack, eltType *value);
+//pop returns 0 on success and -1 on failure.  If the function call is
+//successful, *value will be the value removed from the stack
+void push(Stack *stack, eltType val);
+Stack* stack_init();
+void stack_destroy(Stack *stack);
+
+#endif //__STACK_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/include/std.h	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,52 @@
+#include <die.h>
+
+#ifndef __STD_H
+#define __STD_H
+
+#define assert(x) do { if(!(x)) die(); } while (0)
+
+//min and max function definitions
+#define __fxn(TYPE) \
+	static inline TYPE Max_##TYPE(TYPE a, TYPE b) { return (a>b) ? a : b; } \
+	static inline TYPE Min_##TYPE(TYPE a, TYPE b) { return (a>b) ? b : a; } 
+	__fxn(int)
+	__fxn(u64)
+	__fxn(u32)
+#undef __fxn
+
+void init_all(u64 __memsize);
+
+double abs(double num);
+
+char* ftoa(double x, char *a, unsigned int prec);
+char* itoa(long long n, char *a, unsigned short base);
+s64 atoi(char *a);
+double atof(char *a);
+
+void sPrint(char *a);
+char* sGet(char *a, unsigned int n);
+
+void strcpy(char *dest, const char *src);
+int strcmp(const char *a, const char *b);
+
+char* append(char *dest, char *src);
+
+void* memcpy(void *destination, const void *source, size_t num);
+
+//MALLOC CODE
+
+struct header{
+	struct header *next;
+	size_t size;
+};
+typedef struct header Header;
+
+typedef Header blockUnit;
+
+void malloc_init(size_t memSize);
+void* malloc(size_t size);
+void free(void *ptr);
+void printHeader(Header* head);
+void printMem();
+
+#endif
--- a/include/system.h	Thu May 12 13:23:21 2011 -0400
+++ b/include/system.h	Thu May 12 13:25:58 2011 -0400
@@ -5,6 +5,14 @@
 #define CON_DEV 0x0009
 
 #define NULL	((void*) 0)
+#define CON_LEN 132
+#define HEAP_START 0x200000
+
+#define INF __builtin_inff()
+#define NAN __builtin_nanf("")
+
+typedef unsigned long long size_t;
+typedef unsigned long long intptr_t;
 
 typedef unsigned long long u64;
 typedef signed long long s64;
--- a/include/tod.h	Thu May 12 13:23:21 2011 -0400
+++ b/include/tod.h	Thu May 12 13:25:58 2011 -0400
@@ -56,9 +56,10 @@
  *                 *tod == 0 is the instant the system powered on
  *   2 or 3 on failure, value of *tod is unpredictable
  */
-static inline int get_tod(u64 *tod)
+static inline ErrCode get_tod(u64 *tod)
 {
 	int cc;
+	ErrCode ret = 0;
 
 	asm volatile(
 		"stck	%0\n"
@@ -71,8 +72,20 @@
 	: /* clobber */
 	  "cc"
 	);
+	switch(cc) {
+		case 0:
+			ret = 0;
+			break;
+		case 1:
+			ret = mkError(MODTOD, UPTIME, WARN);
+			break;
+		case 2:
+		case 3:
+			ret = mkError(MODTOD, INVALID, ERROR);
+			break;
+	}
 
-	return cc;
+	return ret;
 }
 
 #endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/dynamic.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,74 @@
+/*
+ * This is where everything starts
+ */
+
+#include <std.h>
+#include <operations.h>
+#include <stack.h>
+
+void dumpBuffer(char *a, int b)
+{
+	int i;
+	for(i = 0; i < b; i++) {
+		int foo = (int) a[i];
+		char c[10];
+		itoa(foo, c, 16);
+		sPrint(c);
+		sPrint(" ");
+		if(!((i + 1)%20)) sPrint("\n");
+	}
+}
+
+void start(u64 __memsize)
+{
+	init_all(__memsize);
+	size_t n;
+	char *buffer;
+	char input[30];
+
+	while(0) {
+		sPrint("How long do you want the string? ");
+		n = atoi(sGet(input, 30));
+		buffer = (char*) malloc(n);
+		if (!buffer) { //allocation failed, too large
+			sPrint("ERROR\n");
+			break;
+		}
+//		size_t i;
+//		for (i = 0; i < n - 1; i++)
+//			buffer[i]='a'; //I need to make rand...
+//		buffer[n - 1]='\0';
+//		sPrint(buffer), sPrint("\n");
+//		dumpBuffer(buffer, n);
+		sPrint(append(itoa((unsigned long)buffer, input, 16), "\n"));
+		free(buffer);
+	}
+
+	printMem();
+
+	Stack *stack = stack_init();
+
+	for(n = 0; n < 1000; n++) {
+		push(stack, n);
+	}
+	stack_destroy(stack);
+
+
+	printMem();
+	void *a = malloc(1223);
+	void *b = malloc(352);
+	void *c = malloc(3539);
+	void *d = malloc(325);
+	printMem();
+	free(b);
+	printMem();
+	b = malloc(400);
+	printMem();
+	sPrint("DONE\n");
+	free(a);
+	free(c);
+	free(d);
+
+	for(;;)
+		sGet(input, 0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/fs.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,425 @@
+#include <fs.h>
+#include <std.h>
+#include <tod.h>
+#include <error.h>
+
+static void* readFSBlock(u32 blkno);
+static ErrCode writeFSBlock(u32 blkno, void *ptr);
+static ErrCode sync(u32 blkno);
+static ErrCode getBlockData(u32 blkno, void* ptr);
+static ErrCode setFileSize(u32 fid, size_t size);
+static ErrCode isBlockAt(u32 block, short *b);
+static ErrCode setBlockAt(u32 block, short isBlock);
+static ErrCode nextFreeBlock(u32 start, u32 *loc);
+static u32 getCacheLoc(u32 blkno);
+static u32 cacheAdd(u32 blkno);
+static ErrCode setTod(Inode *inPtr);
+
+static u32 DevID;
+static u32 CacheCap; //how many blocks the cache can hold
+static u32 CacheSize; //the current number of items in the cache
+static FSBlk *FS_Cache = NULL; //A pointer to the actual cache
+static u32 *CacheLocs; //what location each block points to
+static u32 CacheNext; //the next location to toss a cached block into
+static u32 rootLoc;
+static u32 MaxBlocks;
+
+ErrCode init_fs(u32 devnum, u64 __memsize)
+{
+	//Create the cache
+	CacheCap = ((__memsize/100)/FSBLKSIZE)*CACHESPACE;
+	//number of blocks to store in the cache
+	FS_Cache = malloc(CacheCap*FSBLKSIZE);
+	if(!FS_Cache) return mkError(MODFS, ALLOCFAIL, ERROR);
+	CacheLocs = malloc(CacheCap);
+	if(!CacheLocs) return mkError(MODFS, ALLOCFAIL, ERROR);
+	CacheSize = 0;
+	CacheNext = 0;
+
+	DevID = find_dev(0x100);
+	Superblock *sb;
+	sb = readFSBlock(1);
+	if(!sb) return ERR_FSBLKREADFAIL;
+	if(sb->magic != FSMAGICNUM) return mkError(MODFS, MUGGLE, ERROR);
+	MaxBlocks = sb->nblocks;
+	rootLoc = sb->root_inode;
+
+	return 0;
+}
+
+ErrCode getFInfo(u32 n, void* de)
+{
+	Inode *root = readFSBlock(rootLoc);
+	if(!root) return ERR_FSBLKREADFAIL;
+	if(n >= root->size/DEPBLK) return mkError(MODFS, OUTOFRANGE, WARN);
+	Direntry *dp = readFSBlock(root->blocks[n/DEPBLK]);
+	if(!dp) return ERR_FSBLKREADFAIL;
+	memcpy(de, dp + n%DEPBLK, sizeof(Direntry));
+	return 0;
+}
+
+//This sets *fid to be equal to the fileid of the file with name fname
+ErrCode lookupFile(char *fname, u32 *fid)
+{
+	size_t i;
+	for(i = 0; 1; i++) {
+		Direntry de;
+		ErrCode err = getFInfo(i, &de);
+		if(err == mkError(MODFS, OUTOFRANGE, WARN)) break; //have iterated through all files
+		else if(isError(err)) return err; //propogate error
+		if(!fnameCmp(fname, de.fname)) {
+			*fid = de.inode;
+			return 0;
+		}
+	}
+	return mkError(MODFS, NOTFILE, ERROR);
+}
+
+//makes an empty file with name fname, sets fid to the fid for the new file
+//If the file already exists, an error is returned but fid will be set to the
+//fid of that file
+ErrCode makeFile(char *fname, u32 *fid)
+{
+	ErrCode err;
+	if(!isError(err = lookupFile(fname, fid)))
+		return mkError(MODFS, EXISTS, ERROR); //the file should not exist
+	if(err != mkError(MODFS, NOTFILE, ERROR)) return err;
+	if(isError(err = nextFreeBlock(0, fid))) return err;
+
+	Inode nin;
+	nin.size = 0;
+	nin.nblocks = 0;
+	if(isError(err = setTod(&nin))) return err;
+	nin.ctime = nin.mtime;
+	nin._pad0 = nin._pad1 = nin._pad2 = 0; //I am not sure if this is needed...
+	if(isError(err = writeFSBlock(*fid, &nin))) return err;
+
+	Direntry de;
+	de.inode = *fid;
+	memcpy(de.fname, fname, FNAMELEN);
+	if(isError(err = fileAppend(rootLoc, &de, sizeof(Direntry)))) return err;
+
+	return 0;
+}
+
+ErrCode deleteFile(u32 fid)
+{
+	ErrCode err;
+	if(isError(err = setFileSize(fid, 0))) return err;
+	Direntry de;
+	u32 fileNo;
+	for(fileNo = 0; 1; fileNo++) {
+		if(isError(err = getFInfo(fileNo, &de))) return err;
+		else if(err == mkError(MODFS, OUTOFRANGE, WARN)) return mkError(MODFS, NOTFILE, ERROR);
+		if(de.inode == fid) break;
+	}
+	Inode *root = readFSBlock(rootLoc);
+	if(!root) return ERR_FSBLKREADFAIL;
+	u32 rootSize = root->size;
+	u32 numDE = rootSize/sizeof(Direntry);
+	u32 toBlkNo = root->blocks[fileNo/DEPBLK]; //block that the DE used to occupy
+	u32 endBlkNo = root->blocks[numDE/DEPBLK]; //block for the last DE
+	Direntry *td = readFSBlock(root->blocks[fileNo/DEPBLK]);
+	if(!td) return ERR_FSBLKREADFAIL;
+	td += fileNo%DEPBLK;
+	Direntry *end = readFSBlock(endBlkNo);
+		//this will fail if there is only space for one item in cache and the 2 DEs
+		//are in different blocks.  There will be no indication of failure
+	if(!end) return ERR_FSBLKREADFAIL;
+	end += numDE%DEPBLK;
+	*td = *end;
+	if(isError(err = setFileSize(rootLoc, rootSize - sizeof(Direntry)))) return err;
+	if(isError(err = sync(toBlkNo))) return err; //end does not need to be synchronized
+	return 0;
+}
+
+ErrCode fileAppend(u32 fid, void *data, u32 length)
+{
+	ErrCode err;
+	u32 fileSize;
+	if(isError(err = getFileSize(fid, &fileSize))) return err;
+	if(isError(err = fileWrite(fid, data, length, fileSize))) return err;
+	return 0;
+}
+
+ErrCode fileWrite(u32 fid, void *data, u32 length, u32 offset)
+{
+	ErrCode err, ret = 0;
+	Inode *iptr = readFSBlock(fid);
+	if(!iptr) return ERR_FSBLKREADFAIL;
+	u32 oldSize = iptr->size;
+	u32 dataStop = offset + length;
+	if(dataStop > oldSize) {
+		if(isError(err = setFileSize(fid, dataStop))) return err;
+	}
+
+	Inode in;
+	if(isError(err = getBlockData(fid, &in))) return err;
+
+	u32 currPos = offset;
+	while(currPos < dataStop) {
+		u32 currBlock = in.blocks[currPos/FSBLKSIZE];
+		void *ptr = readFSBlock(currBlock);
+		if(!ptr) return ERR_FSBLKREADFAIL;
+		u32 tcOS = currPos%FSBLKSIZE; //the current offset for the block
+		u32 tcSize = Min_u32(dataStop - currPos, FSBLKSIZE); //assume 0 offset
+		tcSize = (tcSize + tcOS > FSBLKSIZE)?FSBLKSIZE - tcOS:tcSize; //take into account the offset
+		memcpy(ptr + tcOS, data, tcSize);
+		if(isError(err = sync(currBlock))) return err;
+		data += tcSize;
+		currPos += tcSize;
+	}
+
+	if(isError(err = setTod(&in))) ret = makeWarn(err);
+	if(isError(err = writeFSBlock(fid, &in))) return err;
+	return ret;
+}
+
+//PRECON:  fid is a valid file id
+//This sets *size equal to the size of the file
+ErrCode getFileSize(u32 fid, u32 *size)
+{
+	Inode *ptr = readFSBlock(fid);
+	if(!ptr) return ERR_FSBLKREADFAIL;
+	*size = ptr->size;
+	return 0;
+}
+
+//PRECON:  ptr points to a large enough location to hold all the data in file
+//         fid
+ErrCode getFileData(u32 fid, void *ptr)
+{
+	ErrCode ret = 0, err;
+	int i;
+	Inode in;
+	if(isError(err = getBlockData(fid, &in))) {
+		ret = err;
+		goto end;
+	}
+
+	u32 size = in.size;
+	for(i = 0; i < in.nblocks; i++) {
+		Inode *filePtr = readFSBlock(in.blocks[i]);
+		if(!filePtr) {
+			ret = ERR_FSBLKREADFAIL;
+			goto end;
+		}
+		memcpy(ptr, filePtr, Min_u32(size, FSBLKSIZE));
+		ptr += FSBLKSIZE;
+		size -= FSBLKSIZE;
+	}
+
+end:
+	return ret;
+}
+
+void printFname(char *name)
+{
+	putline(name, 28);
+}
+
+//PRECON:  fname points to a location 28 characters long
+//Sets fname to contain a filename entered by the user
+void getFname(char *fname)
+{
+	int chars = getline(fname, FNAMELEN);
+	for(;chars < FNAMELEN; chars++) {
+		fname[chars] = ' ';
+	}
+}
+
+//Checks whether two file names are equal
+int fnameCmp(const char *a, const char *b)
+{
+	int i;
+	for(i = 0; i < FNAMELEN; i++, a++, b++) {
+		if(*a - *b) return *a - *b;
+	}
+	return 0;
+}
+
+//XXX HELPER FUNCTIONS XXX
+
+//returns a pointer pointing to a location where the data from blkno will be
+//stored
+static void* readFSBlock(u32 blkno)
+{
+	u32 cacheLoc = getCacheLoc(blkno); //Do not reload if in cache
+	if(cacheLoc == CacheCap) { //It was not found in the cache
+		cacheLoc = cacheAdd(blkno);
+		FSBlk *nextFSB = FS_Cache + cacheLoc;
+		DskBlk *nextDSKB = (DskBlk *) nextFSB; //block to put data in
+		if(fba_read_blk(DevID, blkno*2, nextDSKB)) return NULL;
+		if(fba_read_blk(DevID, blkno*2 + 1, nextDSKB + 1)) return NULL;
+	}
+	return (void *)(FS_Cache + cacheLoc);
+}
+
+//Writes 1024 bytes from *ptr to data block blkno
+static ErrCode writeFSBlock(u32 blkno, void *ptr)
+{
+	u32 cacheLoc = getCacheLoc(blkno);
+	ErrCode err;
+	if(cacheLoc == CacheCap)
+		cacheLoc = cacheAdd(blkno); //need room in cache for data
+	FSBlk *nextFSB = FS_Cache + cacheLoc; //TODO abstraction levels?
+	memcpy(nextFSB, ptr, FSBLKSIZE); //copy the data to the cache
+	DskBlk *nextDSKB = (DskBlk *) nextFSB; //where to get the data from
+	if(isError(err = fba_write_blk(DevID, blkno*2, nextDSKB))) return err;
+	//load from the cache to the disk
+	if(isError(err = fba_write_blk(DevID, blkno*2 + 1, nextDSKB + 1))) return err;
+	short ib;
+	if(isError(err = isBlockAt(blkno, &ib))) return err;
+	if(!ib) {
+		if(isError(err = setBlockAt(blkno, 1))) return makeWarn(err);
+	}
+	return 0;
+}
+
+//updates the data in block blkno based upon the data in the cache.  If block
+//blkno is not in the cache, returns non-zero
+static ErrCode sync(u32 blkno)
+{
+	u32 cacheLoc = getCacheLoc(blkno);
+	if(cacheLoc == CacheCap) return mkError(MODFS, NOTINCACHE, ERROR);
+	FSBlk *nextFSB = FS_Cache + cacheLoc;
+	DskBlk *nextDSKB = (DskBlk *) nextFSB; //where to get the data from
+	if(fba_write_blk(DevID, blkno*2, nextDSKB)) return mkError(MODFS, BLKWRITEFAIL, ERROR);
+	if(fba_write_blk(DevID, blkno*2 + 1, nextDSKB + 1)) return mkError(MODFS, BLKWRITEFAIL, ERROR);
+	return 0;
+}
+
+static ErrCode getBlockData(u32 blkno, void* ptr)
+{
+	Inode *temp = readFSBlock(blkno);
+	if(!temp) return ERR_FSBLKREADFAIL;
+	memcpy(ptr, temp, FSBLKSIZE);
+	return 0;
+}
+
+//sets the file to have a size equal to size.  The data will be preserved if
+//the file is currently larger than that or will be jibberish if the file is
+//currently smaller
+static ErrCode setFileSize(u32 fid, size_t size) //TODO clean
+{
+	ErrCode ret = 0, err;
+	unsigned int i;
+	u16 neededBlocks = (size + FSBLKSIZE - 1)/FSBLKSIZE;
+	if(neededBlocks > MAXBLOCKS) {
+		ret = mkError(MODFS, SIZETOOLARGE, ERROR);
+		goto end;
+	}
+	Inode in;
+	if(isError(err = getBlockData(fid, &in))) {
+		ret = err;
+		goto end;
+	}
+
+	if(in.nblocks >= neededBlocks) { //get rid of some blocks
+		for(i = neededBlocks; i < in.nblocks; i++) { //if it is equal, will skip this loop
+			if(isError(err = setBlockAt(in.blocks[i], 0))) {
+				ret = err;
+				goto end;
+			}
+		}
+	} else { //there are fewer blocks
+		for(i = in.nblocks; i < neededBlocks; i++) {
+			u32 prevLoc = (i)?in.blocks[i - 1]:fid;
+			if(isError(err = nextFreeBlock(prevLoc, &in.blocks[i]))) {
+				ret = err;
+				goto end;
+			}
+			if(isError(err = setBlockAt(in.blocks[i], 1))) {
+				ret = err;
+				goto end;
+			}
+		}
+	}
+	in.nblocks = neededBlocks;
+	in.size = size;
+	if(isError(err = setTod(&in))) {
+		ret = makeWarn(err);
+	}
+	if(isError(err = writeFSBlock(fid, &in))) {
+		ret = err;
+		goto end;
+	}
+
+end:
+	return ret;
+}
+
+static ErrCode isBlockAt(u32 block, short *b)
+{
+	u32 inBlock = block/(8*FSBLKSIZE) + 2; //which block the bit is in
+	u32 blockSpot = (block%(8*FSBLKSIZE))/8; //which u8 the bit is in
+	u32 spotSpot = 7 - block%8; //which bit the bit is
+	u8 *ptr = readFSBlock(inBlock);
+	if(!ptr) return ERR_FSBLKREADFAIL;
+	*b = (ptr[blockSpot] >> spotSpot) & 1;
+	return 0;
+}
+
+//sets the block table to indicate whether there is a block at block
+static ErrCode setBlockAt(u32 block, short isBlock)
+{
+	u32 inBlock = block/(8*FSBLKSIZE) + 2; //which block the bit is in
+	u32 blockSpot = (block%(8*FSBLKSIZE))/8; //which u8 the bit is in
+	u32 spotSpot = 7 - block%8; //which bit the bit is
+	u8 *ptr = readFSBlock(inBlock);
+	if(!ptr) return ERR_FSBLKREADFAIL;
+	if(isBlock) ptr[blockSpot] |= 1 << spotSpot;
+	else ptr[blockSpot] &= ~(1 << spotSpot);
+	ErrCode err;
+	if(isError(err = sync(inBlock))) return err;
+	return 0;
+}
+
+static ErrCode nextFreeBlock(u32 start, u32 *loc)
+{
+	u32 i;
+	ErrCode err;
+	for(i = start; i < MaxBlocks; i++) {
+		short ib;
+		if(isError(err = isBlockAt(i, &ib))) return err;
+		if(!ib) {
+			*loc = i;
+			return 0;
+		}
+	}
+	return mkError(MODFS, DISKFULL, ERROR);
+}
+
+//TODO ErrCode?
+static u32 getCacheLoc(u32 blkno)
+{
+	int i;
+	for(i = 0; i < CacheSize; i++) {
+		if(CacheLocs[i] == blkno) return i;
+	}
+	return CacheCap;
+}
+
+//PRECON:   block blkno is not already in the cache
+//Returns the location in the cache where the data is
+//sets aside space in the cache for some item.  NOTE: this does not read the
+//current contents of the disk to the cache
+static u32 cacheAdd(u32 blkno)
+{
+	u32 ret = CacheNext;
+	CacheLocs[CacheNext] = blkno;
+	if(CacheSize != CacheCap) CacheSize += 1;
+	if(CacheNext != CacheCap - 1) CacheNext += 1;
+	else CacheNext = 0;
+	return ret;
+}
+
+//TODO consider what to do in other places if this returns a warning/error
+static ErrCode setTod(Inode *inPtr)
+{
+	u64 tod;
+	ErrCode ret;
+	ret = get_tod(&tod);
+	inPtr->mtime = tod >> 12;
+	return ret;
+}
--- a/src/init.c	Thu May 12 13:23:21 2011 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,13 +0,0 @@
-/*
- * This is where everything starts
- */
-void start(u64 __memsize)
-{
-	init_io_int();
-	init_console();
-
-	putline("Hello\n", 6);
-
-	for(;;)
-		;
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/math.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,84 @@
+double iPow(double base, int exponent)
+{
+	double ans = 1;
+	short isNeg = 0;
+	if(exponent < 0) {
+		isNeg = 1;
+		exponent *= -1;
+	}
+	while(exponent > 0) {
+		if(exponent%2) {
+			exponent -= 1;
+			ans *= base;
+		} else {
+			exponent /= 2;
+			base *= base;
+		}
+	}
+	return isNeg ? 1/ans : ans;
+}
+
+double exp(double exp)
+{
+	unsigned int i; //a counter for the loop
+	double ans = 1;
+	double prev = -1;
+	double term = 1;
+	short isNeg = 0;
+	if(exp < 0) {
+		isNeg = 1;
+		exp *= -1;
+	}
+	for(i = 1; ans - prev; i++) {
+		prev = ans;
+		term *= exp/i;
+		ans += term;
+	}
+	return isNeg ? 1/ans : ans;
+}
+
+double log(double num)
+{
+	unsigned int denom = 1;
+	double euler = 2.71828182845904;
+	double ans = 0;
+	double prev = -1;
+	double term = -1;
+	while(num <= -1 || num >= 1) {
+		num /= euler;
+		ans += 1;
+	}
+	for(; ans - prev; denom++) {
+		prev = ans;
+		term *= (-1*(num - 1));
+		ans += term/denom;
+	}
+	return ans;
+}
+
+double pow(double base, double exponent)
+{
+	if(exponent == (int) exponent)
+		return iPow(base, (int) exponent);
+	return exp(exponent*log(base));
+}
+
+double math_add(double first, double sec)
+{
+	return first + sec;
+}
+
+double math_sub(double first, double sec)
+{
+	return first - sec;
+}
+
+double math_mult(double first, double sec)
+{
+	return first*sec;
+}
+
+double math_div(double first, double sec)
+{
+	return first/sec;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/operations.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,113 @@
+#include <operations.h>
+#include <std.h>
+#include <stack.h>
+#include <math.h>
+
+const char operationNames[MAXOP][10] = {".", "+", "-", "*", "/", "**", "dup", "drop", "log", "exp", "swap"};
+void (*operation[MAXOP])(Stack*) = {op_print, op_add, op_sub, op_mult,
+	op_div, op_pow, op_dup, op_drop, op_log, op_exp, op_swap};
+
+static void error_unk()
+{
+	sPrint("ERROR: CAUSE UNKNOWN\n");
+}
+
+static void error_small()
+{
+	sPrint("ERROR: STACK TOO SMALL\n");
+}
+
+void op_math1(Stack *stack, eltType (*mathop)(eltType))
+{
+	if(stack->size >= 1) {
+		eltType val;
+		if(pop(stack, &val)) error_unk();
+		else push(stack, mathop(val));
+	} else error_small();
+}
+
+void op_math2(Stack *stack, eltType (*mathop)(eltType, eltType))
+{
+	if(stack->size >= 2) {
+		eltType val1, val2;
+		if(pop(stack, &val2) || pop(stack, &val1)) error_unk();
+		else push(stack, mathop(val1, val2));
+	} else error_small();
+}
+
+void op_print(Stack *stack)
+{
+	if(stack->size >= 1) {
+		char output[30];
+		eltType val;
+		if(pop(stack, &val)) error_unk();
+		else sPrint(append(ftoa(val, output, 10), "\n"));
+	} else error_small();
+}
+
+void op_add(Stack *stack)
+{
+	op_math2(stack, math_add);
+}
+
+void op_sub(Stack *stack)
+{
+	op_math2(stack, math_sub);
+}
+
+void op_mult(Stack *stack)
+{
+	op_math2(stack, math_mult);
+}
+
+void op_div(Stack *stack)
+{
+	op_math2(stack, math_div);
+}
+
+void op_pow(Stack *stack)
+{
+	op_math2(stack, pow);
+}
+
+void op_dup(Stack *stack)
+{
+	if(stack->size >= 1) {
+		eltType val;
+		if(pop(stack, &val)) error_unk();
+		else {
+			push(stack, val);
+			push(stack, val);
+		}
+	} else error_small();
+}
+
+void op_drop(Stack *stack)
+{
+	if(stack->size >= 1) {
+		eltType val;
+		pop(stack, &val);
+	} else error_small();
+}
+
+void op_log(Stack *stack)
+{
+	op_math1(stack, log);
+}
+
+void op_exp(Stack *stack)
+{
+	op_math1(stack, exp);
+}
+
+void op_swap(Stack *stack)
+{
+	if(stack->size >= 2) {
+		eltType val1, val2;
+		if(pop(stack, &val2) || pop(stack, &val1)) error_unk();
+		else {
+			push(stack, val2);
+			push(stack, val1);
+		}
+	} else error_small();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/sarpn.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,37 @@
+/*
+ * This is where everything starts
+ */
+
+#include <std.h>
+#include <operations.h>
+#include <stack.h>
+
+int arrayLookup(char *text, const char array[][10], int last)
+{
+	int i;
+	for(i = 0; i < last; i++)
+		if(!strcmp(array[i], text)) return i;
+	return last;
+}
+
+void start(u64 __memsize)
+{
+	init_all(__memsize);
+
+	Stack *stack = stack_init();
+	while(1) {
+		int opVal;
+		char input[30];
+		sPrint("Please enter an operation or value: ");
+		opVal = arrayLookup(sGet(input, 30), operationNames, MAXOP);
+		if(opVal != MAXOP) {
+			(*operation[opVal]) (stack); //call the function array
+		} else {
+			push(stack, atof(input));
+		}
+	}
+	stack_destroy(stack);
+
+	for(;;)
+		;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/stack.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,40 @@
+#include <stack.h>
+#include <std.h>
+
+short pop(Stack *stack, eltType *value)
+{
+	if(stack->top == NULL) {
+		return -1; //failure
+	} else {
+		StackElt *tip = stack->top;
+		*value = tip->elt;
+		stack->top = tip->next;
+		free(tip);
+		stack->size--;
+		return 0; //success
+	}
+}
+
+void push(Stack *stack, eltType val)
+{
+	StackElt *new = malloc(sizeof(StackElt));
+	new->elt = val;
+	new->next = stack->top;
+	stack->top = new;
+	stack->size++;
+}
+
+Stack* stack_init()
+{
+	Stack *new = malloc(sizeof(Stack));
+	new->top = NULL;
+	return new;
+}
+
+void stack_destroy(Stack *stack)
+{
+	eltType *val = malloc(sizeof(eltType));
+	while(stack->top) pop(stack, val);
+	free(stack);
+	free(val);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/std.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,253 @@
+#include <std.h>
+
+void init_all(u64 __memsize)
+{
+	init_io_int();
+	init_console();
+	malloc_init(__memsize - HEAP_START);
+}
+
+double abs(double num)
+{
+	if(num < 0) return num*-1;
+	else return num;
+}
+
+char* itoa(s64 n, char *a, unsigned short base)
+{
+	char *ret = a;
+	if(n < 0) {
+		*a++ = '-';
+		n *= -1;
+	}
+	char *b = a;
+	if(!n) *b++ = '0';
+	for(; n; b++) {
+		int temp = n%base;
+		if(temp < 10) *b = '0' + temp;
+		else *b = 'a' + temp - 10;
+		n = n/base;
+	}
+	*b-- = '\0';
+	for(; a < b; a++, b--) { //reverse
+		char temp = *b;
+		*b = *a;
+		*a = temp;
+	}
+	return ret;
+}
+
+char* ftoa(double x, char *a, unsigned int prec)
+{
+	char *ret = a;
+	if(x == INF || x == -INF) {
+		strcpy(a, "INF");
+	} else if(x != x) { //NAN != NAN
+		strcpy(a, "NAN");
+	} else {
+		s64 n = (s64) x; //integer part
+		double d = abs(x - (double) n); //fractional part;
+		itoa(n, a, 10);
+		if(prec) { //only do the decimal part if decimal parts were asked for
+			while(*a && *++a); //get to the null character from itoa
+			int i; //counter variable for the for loop
+			*a++ = '.'; //put the decimal in place
+			for(i = 0; i < prec; i++) {
+				d *= 10; //the integer part is the decimal digit
+				*a++ = ((int) d) + '0'; //add the integer part of d to the string
+				d -= (int) d; //chop off the integer part
+			} a--; //move back to the last digit
+			while(*a != '.') {
+				if(*a == '0') {
+					a--;
+					continue;
+				} else if(*a > '0' && *a <= '9') {
+					a++;
+					break;
+				} else {
+					sPrint("ERROR: SOMETHING IS VERY WRONG\n");
+					break;
+				}
+			}
+			*a = '\0';
+		}
+	}
+	return ret;
+}
+
+s64 atoi(char *a)
+{
+	short neg = 0;
+	s64 n = 0;
+	if(*a == '-') {
+		neg = 1;
+		a++;
+	} else if(*a == '+') a++;
+	while(*a >= '0' && *a <= '9')
+		n = n*10 + (*a++ - '0');
+	if(neg) n *= -1;
+	return n;
+}
+
+double atof(char *a)
+{
+	s64 n = atoi(a);
+	double x = 0;
+	double dec = .1;
+	short neg = 0;
+	if(*a == '-') {
+		neg = 1;
+		a++;
+	}
+	while(*a != '.') {
+		if(!(*a >= '0' && *a <= '9') && *a != '-') return n;
+		a++;
+	} a++; //a will be immediately after the decimal point
+	while(*a >= '0' && *a <= '9') { //goes through the decimal part
+		x += (*a - '0')*dec;
+		dec *= .1;
+		a++;
+	}
+	if(neg) x*=-1;
+	return n + x;
+}
+
+void sPrint(char *a)
+{
+	char *b = a;
+	while(*b && *++b);
+	do {
+		putline(a, (b - a > CON_LEN)?CON_LEN:(b - a));
+		a += CON_LEN;
+	} while(a < b);
+}
+
+void strcpy(char *dest, const char *src)
+{
+	while((*dest++ = *src++));
+}
+
+int strcmp(const char *a, const char *b)
+{
+	while(1) {
+		if(*a - *b) return *a - *b;
+		if(*a == '\0') return 0;
+		a++;
+		b++;
+	}
+	return -1;
+}
+
+char* sGet(char *a, unsigned int n)
+{
+	int length = getline(a, n);
+	a[(length < n)?length:n - 1] = '\0';
+	return a;
+}
+
+char* append(char *dest, char *src)
+{
+	char *ret = dest;
+	while(*dest&& *++dest); //get to null in first string
+	while((*dest++ = *src++));
+	return ret;
+}
+
+void* memcpy(void *destination, const void *source, size_t num)
+{
+	int i;
+	const u8 *from = source;
+	u8 *to = destination;
+	for(i = 0; i < num; i++)
+		to[i] = from[i];
+	return destination;
+}
+
+
+
+//DYNAMIC MEMORY
+
+static Header base;
+static Header *allocp = NULL; //the location of the last known free block
+
+void malloc_init(size_t memSize)
+{
+	allocp = &base;
+	allocp->size = 0;
+	allocp->next = (void*)HEAP_START;
+	allocp->next->next = &base;
+	allocp->next->size = memSize/sizeof(blockUnit);
+	if((sizeof(blockUnit)%sizeof(u64))) {
+		sPrint("WARNING: MEMORY NOT 8-BYTE ALIGNED\n");
+		char foo[40];
+		sPrint(append("MEMORY BLOCK SIZE IS: ", append(itoa(sizeof(Header), foo, 10), "\n")));
+	}
+}
+
+void* malloc(size_t size)
+{
+	if(allocp == NULL) return NULL;
+	size_t nUnits = ((size + sizeof(Header)) + sizeof(blockUnit) - 1)/sizeof(blockUnit);
+	Header *prev = allocp;
+	Header *cur, *temp;
+	for(cur = prev->next;; prev = cur, cur = cur->next) {
+		if(cur->size >= nUnits) {
+			if(cur->size == nUnits) {
+				prev->next = cur->next;
+			} else {
+				temp = cur + nUnits; //This requires sizeof(blockUnit) == sizeof(Header).  TODO fix
+				temp->size = cur->size - nUnits;
+				temp->next = cur->next;
+				prev->next = temp;
+				cur->size = nUnits;
+			}
+			allocp = prev;
+			return (void*)(cur + 1);
+		} else if(cur == allocp) { //We went back to the start...
+			return NULL;
+		}
+	}
+}
+
+void free(void *ptr)
+{
+	Header *toFree = (Header *)ptr - 1;
+	Header *scan;
+	for(scan = allocp; !(toFree > scan && toFree < scan->next); scan = scan->next)
+		if(scan->next < scan && (toFree > scan || toFree < scan->next)) break;
+	toFree->next = scan->next;
+	scan->next = toFree;
+	if(scan + scan->size == toFree) {
+		scan->size += toFree->size;
+		scan->next = toFree->next;
+		toFree = scan;
+	}
+	if(toFree + toFree->size == toFree->next) {
+		toFree->size += toFree->next->size;
+		toFree->next = toFree->next->next;
+	}
+}
+
+void printHeader(Header* head)
+{
+	char buffer[20];
+	sPrint("Memory address is: ");
+	sPrint(itoa((intptr_t)head, buffer, 16));
+	sPrint("\n");
+	sPrint("The size of the block is: ");
+	sPrint(itoa(head->size, buffer, 10));
+	sPrint("\n");
+	sPrint("Next memory address is: ");
+	sPrint(itoa((intptr_t)head->next, buffer, 16));
+	sPrint("\n\n");
+}
+
+void printMem()
+{
+	Header *cur = allocp;
+	do {
+		printHeader(cur);
+		cur = cur->next;
+	} while(cur != allocp);
+	sPrint("PRINTOUT DONE\n\n");
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testFS.c	Thu May 12 13:25:58 2011 -0400
@@ -0,0 +1,144 @@
+#include <std.h>
+#include <fs.h>
+#include <error.h>
+
+void dumpText(char *text, int size)
+{
+	do {
+		putline(text, (size > CON_LEN)?CON_LEN:size);
+		size -= CON_LEN;
+		text += CON_LEN;
+	} while(size > 0);
+}
+
+u32 listFiles()
+{
+	size_t i;
+	for(i = 0; 1; i++) {
+		Direntry de;
+		ErrCode err = getFInfo(i, &de);
+		if(err == mkError(MODFS, OUTOFRANGE, WARN)) break;
+		else if(isError(err)) return err;
+		printFname(de.fname), sPrint("\n");
+	}
+	return 0;
+}
+
+void start(u64 __memsize)
+{
+	init_all(__memsize);
+	char buffer[256];
+	if(isError(init_fs(0x100, __memsize))) goto END;
+
+	while(1) {
+		sPrint("Please select a mode:\n0: show file text\n1: make new file\n2: Append to file\n3: Delete File\n");
+		sPrint("3: Delete File\n4: Write to file\n");
+		sGet(buffer, 30);
+		int mode = atoi(buffer);
+		switch(mode) {
+			case 0:
+				{
+					if(isError(listFiles())) sPrint("WARNING: ERROR IN READING FILE NAMES\n");
+					char fname[28];
+					sPrint("Please enter the file to read: ");
+					getFname(fname);
+					u32 fid;
+					ErrCode err = lookupFile(fname, &fid);
+					if(isError(err)) {
+						if(errCode(err) == NOTFILE) sPrint("ERROR: Invalid file name\n");
+						continue;
+					}
+					u32 fileSize;
+					if(isError(getFileSize(fid, &fileSize))) continue;
+					char *text = malloc(fileSize);
+					if(!text) continue;
+					if(isError(getFileData(fid, text))) {
+						free(text);
+						continue;
+					}
+					dumpText(text, fileSize);
+					free(text);
+				}
+				break;
+			case 1:
+				{
+					char fname[28];
+					sPrint("Please enter a name for the new file: ");
+					getFname(fname);
+					u32 dummy; //I do not care about the fid personally
+					if(isError(makeFile(fname, &dummy))) {
+						sPrint("ERROR\n");
+						continue;
+					}
+				}
+				break;
+			case 2:
+				{
+					if(isError(listFiles())) sPrint("WARNING: ERROR IN READING FILE NAMES\n");
+					char fname[28];
+					sPrint("Please enter the file to write to: ");
+					getFname(fname);
+					u32 fid;
+					ErrCode err = lookupFile(fname, &fid);
+					if(isError(err)) {
+						if(errCode(err) == NOTFILE) sPrint("ERROR: Invalid file name\n");
+						continue;
+					}
+					sPrint("Please enter the text to append to the file: ");
+					u32 size = getline(buffer, CON_LEN);
+					if(isError(fileAppend(fid, buffer, size))) {
+						sPrint("ERROR\n");
+						continue;
+					}
+				}
+				break;
+			case 3:
+				{
+					if(isError(listFiles())) sPrint("WARNING: ERROR IN READING FILE NAMES\n");
+					char fname[28];
+					sPrint("Please enter the file to delete: ");
+					getFname(fname);
+					u32 fid;
+					ErrCode err = lookupFile(fname, &fid);
+					if(isError(err)) {
+						if(errCode(err) == NOTFILE) sPrint("ERROR: Invalid file name\n");
+						continue;
+					}
+					if(isError(deleteFile(fid))) {
+						sPrint("ERROR\n");
+						continue;
+					}
+				}
+				break;
+			case 4:
+				{
+					if(isError(listFiles())) sPrint("WARNING: ERROR IN READING FILE NAMES\n");
+					char fname[28];
+					sPrint("Please enter the file to write text to: ");
+					getFname(fname);
+					u32 fid;
+					ErrCode err = lookupFile(fname, &fid);
+					if(isError(err)) {
+						if(errCode(err) == NOTFILE) sPrint("ERROR: Invalid file name\n");
+						continue;
+					}
+					sPrint("Please enter the offset for the text: ");
+					sGet(buffer, 30);
+					unsigned int offset = atoi(buffer);
+					sPrint("Please enter the text to append to the file: ");
+					u32 size = getline(buffer, CON_LEN);
+					if(isError(fileWrite(fid, buffer, size, offset))) {
+						sPrint("ERROR\n");
+						continue;
+					}
+				}
+				break;
+		}
+	}
+
+END:
+	sPrint("DONE\n");
+	for(;;) {
+		sGet(buffer, 0);
+	}
+}