-
-
Save SharpCoder/7be9cef9b448a368a5ad to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ******************************* | |
| // FILE: fs.h | |
| // AUTHOR: SharpCoder | |
| // DATE: 2015-03-31 | |
| // ABOUT: This is the primary raspberry pi file system that I | |
| // designed myself. It's meant to be short and sweet. | |
| // Probably not something I'd use in real life. | |
| // | |
| // LICENSE: Provided "AS IS". USE AT YOUR OWN RISK. | |
| // ******************************* | |
| #ifndef __PIFS_H_ | |
| #define __PIFS_H_ | |
| // Basic includes | |
| #include "conf.h" | |
| #include "io.h" | |
| #include "../libs/mem.h" | |
| #include "../libs/math.h" | |
| // Define the structures used by the filesystem. | |
| class file { | |
| public: | |
| uint32 pos; | |
| uint32 len; | |
| bool locked; | |
| char* name; | |
| List<uint32> blocks; | |
| file() { | |
| this->pos = 0; | |
| this->len = 0; | |
| this->locked = false; | |
| } | |
| }; | |
| typedef file FILE; | |
| class dir { | |
| public: | |
| List<file*> files; | |
| List<dir*> subs; | |
| char* name; | |
| dir() { | |
| this->name = (char*)"\0"; | |
| } | |
| }; | |
| // Define the function signatures. | |
| void fs_init(); | |
| int f_open(file*& f, const char* path); | |
| int f_write(file* f, const void* buf, uint32 bytes); | |
| int f_read(file* f, void* buf, uint32 bytes); | |
| int f_close(file* f); | |
| int f_seek(file* f, uint32 bytes); | |
| int f_truncate( file* f ); | |
| int f_putc(file* f, char c); | |
| int f_puts(file* f, char* c); | |
| bool f_eof(file* f); | |
| uint32 nextBlock(void); | |
| // Initialize some base directories. | |
| dir* root = new dir(); | |
| dir* working = root; | |
| // An array of nodes that have been allocated. | |
| bool blocks[MAX_NODES]; | |
| // Define some helper functions | |
| uint32 nextBlock() { | |
| for ( uint32 i = 0; i < MAX_NODES; i++ ) | |
| if ( !blocks[i] ) { | |
| blocks[i] = true; | |
| return i; | |
| } | |
| return 0; | |
| } | |
| // Define the functions | |
| void fs_init() { | |
| // Clear out the nodes. | |
| for ( int i = 0; i < MAX_NODES; i++ ) | |
| blocks[i] = false; | |
| // Create 20 blocks of file memory. | |
| f_mkfs(PAGE_SIZE * MAX_NODES); | |
| } | |
| // Helper method | |
| bool strcmp(char* ptr1, char* ptr2 ) { | |
| int index = 0; | |
| while ( *(ptr1 + index) != '\0' && *(ptr2 + index) != '\0' && index < 255 ) { | |
| if ( *(ptr1 + index) != *(ptr2 + index) ) | |
| return false; | |
| index++; | |
| } | |
| if ( *(ptr1+index) == '\0' || *(ptr2+index) == '\0' ) | |
| if( *(ptr1+index) != *(ptr2+index)) | |
| return false; | |
| return true; | |
| } | |
| int f_open(file*& f, char* name) {; | |
| // Look for the file in our working directory. | |
| //for (int i = 0; i < working->files.getLength(); i++ ) { | |
| /*if (strcmp(working->files.getAt(i).name,name)) { | |
| f = working.files.getAt(i); | |
| f->pos = 0; | |
| f->locked = true; | |
| return 1; | |
| }*/ | |
| //} | |
| // This is for creating a new file. | |
| f = new file(); | |
| f->name = name; | |
| f->pos = 0; | |
| f->blocks.add( nextBlock() ); | |
| f->locked = true; | |
| // Add this file to our working directory. | |
| working->files.add(f); | |
| // Now we would want to serialize this ish, presumably. | |
| return 1; | |
| } | |
| int f_write(file* f, void* buf, uint32 bytes) { | |
| int max = (f->pos + bytes) / PAGE_SIZE; | |
| int allocated = f->blocks.getLength(); | |
| if ( max - allocated + 1 > 0 ) { | |
| for ( int i = 0; i < max - allocated + 1; i++ ) { | |
| f->blocks.add(nextBlock()); | |
| } | |
| } | |
| // Iterate over the blocks. | |
| uint32 written = 0; | |
| if ( max == 0 ) { | |
| // Write a single page. | |
| writeBlock( 0, f->blocks.getAt(0), buf, bytes, f->pos ); | |
| written += bytes; | |
| } else { | |
| // Otherwise, we're writing multiple pages of dat. | |
| // So we need to normalize everything. | |
| int blockIndex = 0; | |
| if ( f->pos > PAGE_SIZE ) { | |
| // We're not even starting at the first block. | |
| blockIndex = f->pos / PAGE_SIZE; | |
| } | |
| // Now we have the starting block, we need to iterate over | |
| // the remaining data and write. | |
| for ( int i = blockIndex; i < allocated; i++ ) { | |
| // calculate the offset within this block. | |
| uint32 offset = f->pos - (f->pos / PAGE_SIZE); | |
| // Check if we're writing less than a page. | |
| if ( i == allocated ) { | |
| writeBlock( 0, i, buf, bytes - written, offset); | |
| written += (bytes - written); | |
| } else { | |
| writeBlock( 0, i, buf, PAGE_SIZE, offset ); | |
| written += PAGE_SIZE; | |
| } | |
| } | |
| } | |
| // Update the position. | |
| f->pos += written; | |
| f->len += written; | |
| // Return the success result. | |
| return 1; | |
| } | |
| int f_read(file* f, void* buf, uint32 bytes) { | |
| // If they try to read more bytes than the file has, | |
| // adjust the read position. | |
| if ( bytes > f->len ) | |
| bytes = f->len; | |
| // Figure out how many pages of data we can read. | |
| int allocated = f->blocks.getLength(); | |
| // If they try to read more bytes than are allocated. | |
| if ( bytes > allocated * PAGE_SIZE ) return -1; | |
| // Determine how many pages we need to read. | |
| int pages = (bytes / PAGE_SIZE) + 1; | |
| // Iterate over the pages, and read them. | |
| uint32 read = 0; | |
| for ( int index = 0; index < pages; index++ ) { | |
| // Get the block. | |
| int block = f->blocks.getAt(index); | |
| if ( index == pages ) { | |
| // We just need to read one page. | |
| readBlock(0, block, buf, bytes - read); | |
| read += bytes - read; | |
| } else { | |
| // We're just reading in the whole page. | |
| readBlock(0, block, buf, PAGE_SIZE); | |
| read += PAGE_SIZE; | |
| } | |
| } | |
| // Return the success. | |
| return 1; | |
| } | |
| // Seek to the specified index. | |
| int f_seek(file* f, uint32 bytes) { | |
| f->pos = bytes; | |
| return 1; | |
| } | |
| // Truncate to the current position of the file. | |
| int f_truncate(file*f) { | |
| // Deallocate the memory if we can. | |
| uint32 dif = f->len - f->pos; | |
| if ( dif > PAGE_SIZE ) { | |
| // We need to actually deallocate some memory. | |
| int blocks = (dif / PAGE_SIZE) + 1; | |
| for ( int i = 0; i < blocks; i++ ) { | |
| f->blocks.pop(); | |
| } | |
| f->len = f->pos; | |
| } else { | |
| // We don't need to do anything special; | |
| f->len = f->pos; | |
| } | |
| return 1; | |
| } | |
| bool f_eof(file* f) { | |
| return f->pos == f->len; | |
| } | |
| int f_putc(file* f, char c) { | |
| char* ptr = &c; | |
| f_write(f, ptr, 1); | |
| return 1; | |
| } | |
| int f_puts(file* f, char* str) { | |
| // Get the length. | |
| uint32 len = 0; | |
| do { } while ( *(str + len++) != '\0' ); | |
| // Write the string. | |
| f_write( f, str, len); | |
| } | |
| int f_close(file* f) { | |
| // Not sure what we do to close a file. | |
| f->pos = 0; | |
| f->locked = false; | |
| syncDisk(); | |
| return 1; | |
| } | |
| int f_opendir(dir*& d, char* name) { | |
| // Check for the directory in the working directory. | |
| for ( int i = 0; i < working->subs.getLength(); i++ ) { | |
| if ( strcmp(working->subs.getAt(i)->name, name)) { | |
| d = working->subs.getAt(i); | |
| return 1; | |
| } | |
| } | |
| // Otherwise, we need to create the directory. | |
| d = new dir(); | |
| d->name = name; | |
| working->subs.add(d); | |
| return 1; | |
| } | |
| int f_closedir(dir* d) { | |
| syncDisk(); | |
| return 1; | |
| } | |
| dir* f_dirparent(dir* target, dir* work) { | |
| // Start at the root and find the parent. | |
| // iterate over the subs of the working. | |
| dir* pos; | |
| for ( int i = 0; i < work->subs.getLength(); i++ ) { | |
| if ( work->subs.getAt(i) == target ) | |
| return work; | |
| pos = f_dirparent(target, work->subs.getAt(i)); | |
| if ( pos != NULL ) | |
| return pos; | |
| } | |
| return NULL; | |
| } | |
| // This function will change the working directory based on | |
| // a fully qualified path string (must be null terminated). | |
| int f_chdir(char* path) { | |
| // Get the first item in the path, check if it's a forward slash. | |
| char f = path[0]; | |
| string* temp = new string(path); | |
| dir* new_working = working; | |
| // We might be going up a drive or executing in the current path. | |
| // So iterate over the characters. | |
| int start = 0; | |
| for ( int i = 0; i < temp->length; i++ ) { | |
| char c = temp->getAt(i); | |
| char peek = '\0'; | |
| if ( (i + 1) < temp->length ) | |
| peek = temp->getAt(i+1); | |
| // Check for directory up. | |
| if ( c == '.' && peek == '.' ) { | |
| // We need to go to the parent. | |
| new_working = f_dirparent(new_working, root); | |
| if ( new_working == NULL ) | |
| return -1; | |
| // Increment i to account for the peek. | |
| i++; | |
| } else if ( c == '.' && peek == '/' ) { | |
| // Pretty much do nothing special. | |
| i++; | |
| } else if ( c == '/' ) { | |
| // We have a directory to look for. | |
| char* target = temp->substr(start, i)->toString(); | |
| bool success = false; | |
| for ( int r = 0; r < new_working->subs.getLength(); r++ ) { | |
| if ( strcmp(new_working->subs.getAt(r)->name, target) ) { | |
| new_working = new_working->subs.getAt(r); | |
| success = true; | |
| } | |
| } | |
| start = i; | |
| if ( !success ) | |
| return -1; | |
| } | |
| } | |
| // Now look for the remaining item. | |
| char* target = temp->substr(start, temp->length)->toString(); | |
| for ( int r = 0; r < new_working->subs.getLength(); r++ ) { | |
| if (strcmp(new_working->subs.getAt(r)->name, target)) { | |
| new_working = new_working->subs.getAt(r); | |
| } | |
| } | |
| if ( new_working != NULL ) { | |
| working = new_working; | |
| return 1; | |
| } | |
| // Generic error condition. | |
| return -1; | |
| } | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ******************************* | |
| // FILE: io.h | |
| // AUTHOR: SharpCoder | |
| // DATE: 2015-03-31 | |
| // ABOUT: This is the disk IO header. It must be implemented | |
| // in order for the filesystem to work. | |
| // | |
| // LICENSE: Provided "AS IS". USE AT YOUR OWN RISK. | |
| // ******************************* | |
| #ifndef __PIFS_IO_H_ | |
| #define __PIFS_IO_H_ | |
| #include "conf.h" | |
| #include "../libs/mem.h" | |
| // These are the IO methods used to simulate writing to a disk. | |
| // For now, we will simply use memory. Since we're the kernel, | |
| // we can do that! | |
| int openDisk(int nbytes); | |
| int readBlock(int disk, int blocknr, void* buf, int bytes); | |
| int writeBlock(int disk, int blocknr, void* block, int bytes, uint32 foffset); | |
| void syncDisk(); | |
| // Create the disk | |
| char* disk_base; | |
| // Allocate some disk. | |
| int f_mkfs( int nbytes ) { | |
| // Wipe the memory. | |
| disk_base = (char*)malloc(nbytes); | |
| return 1; | |
| } | |
| int readBlock(int disk, int blocknr, void* buf, int bytes) { | |
| char* addr = (char*)disk_base; | |
| char* targ = (char*)buf; | |
| // Add the offset to the address. | |
| addr += blocknr * PAGE_SIZE; | |
| // Check for a buffer overflow type situation. | |
| if ( bytes > PAGE_SIZE ) return -1; | |
| for ( uint32 index = 0; index < bytes; index++ ) { | |
| *targ = *addr; | |
| targ++; | |
| addr++; | |
| } | |
| return 1; | |
| } | |
| int writeBlock(int disk, int blocknr, void* buf, int bytes, uint32 foffset) { | |
| char* addr = (char*)disk_base; | |
| char* orig = (char*)buf; | |
| // Add the offset to the address. | |
| addr += blocknr * PAGE_SIZE; | |
| addr += foffset; | |
| // Check for a buffer overflow type situation. | |
| if ( bytes > PAGE_SIZE ) return -1; | |
| for ( uint32 index = 0; index < bytes; index++ ) { | |
| *addr = *orig; | |
| orig++; | |
| addr++; | |
| } | |
| return 1; | |
| } | |
| void syncDisk() { | |
| } | |
| #endif |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment