Skip to content

Instantly share code, notes, and snippets.

@SharpCoder
Created June 28, 2016 16:02
Show Gist options
  • Select an option

  • Save SharpCoder/72ad665a0960369b8df9792c0dc54306 to your computer and use it in GitHub Desktop.

Select an option

Save SharpCoder/72ad665a0960369b8df9792c0dc54306 to your computer and use it in GitHub Desktop.
// *******************************
// 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment