Skip to content

Instantly share code, notes, and snippets.

@mlhaufe
Last active August 29, 2015 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mlhaufe/99c18766acdb2807d5cc to your computer and use it in GitHub Desktop.
Save mlhaufe/99c18766acdb2807d5cc to your computer and use it in GitHub Desktop.
Tiny File System
#ifdef _WIN32
#define _CRT_SECURE_NO_DEPRECATE
#endif
#define BLOCK_COUNT 16
#include <cctype>
#include <fstream>
#include <iostream>
//#include <pthread.h>
#include <sstream>
#include <sys/stat.h>
#include <vector>
#include <map>
using namespace std;
typedef unsigned char byte;
FILE* tfsDisk;
//TODO: string or block number?
string workingDir;
//TODO: lock function that will lock a given block (range?) or wait until it can lock those blocks
//a mutex for each block on the disk
//static pthread_mutex_t mutexes[BLOCK_COUNT] = { P99_DUPL(BLOCK_COUNT, PTHREAD_MUTEX_INITIALIZER) };
//<http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html>
//TODO: instead of structs, use a function :: (block) -> desired info?
struct rootDirectory {
vector<bool> hasFreeSpace; //[bits 0-3] 0x00 if free space list is empty, 0x0F if non-empty
vector<bool> freeSpaceBlockStart; //[bits 4-7] first block of free space list, or 0xF if empty
vector<byte> contents; //[bytes 1-10] file and folder names
vector<bool> descriptors; //[bytes 11-15] 10 nibbles each representing a block number for a file/dir descriptor
};
struct directory{
vector<bool> parentDirectory; //[bits 0-3] block containing parent directory
vector<bool> thisBlock; //[bits 4-7] block in which this directory is contained
vector<byte> contents; //[bytes 1-10] file and folder names
vector<bool> descriptors; //[bytes 11-15] 10 nibbles each representing a block number for a file/dir descriptor
};
struct smallFile {
byte fileSize; //[byte 0]
vector<byte> data0_6; //[byte 1-7] Data bytes 0-6
vector<byte> data7_14;//[byte 8-15] Data bytes 7-14
};
struct bigFile {
byte fileSize; // [byte 0]
vector<bool> dataBlocks; // [byte 1-7] 14 nibbles. each pointing to a data block containing file data
vector<byte> data0_7; //[byte 8-15] Data bytes 0-7
};
bool isValidPath(string& filePath) {
FILE* file = fopen(filePath.c_str(), "r");
if (file != NULL) {
fclose(file);
return true;
} else {
cerr << "Invalid file path" << endl;
return false;
}
}
bool isValidTfsPath(string& tfsPath) {
//TODO
cout << "isValidTfsPath not implemented" << endl;
return true;
}
byte* loadFile(string& filePath) {
ifstream file(filePath);
file.seekg(0, ios::end);
size_t len = 16*2;
char * result = new char[len];
file.seekg(0, ios::beg);
file.read(result, len);
file.close();
return (byte *) result;
}
vector<string> parseCommand() {
vector<string> tokens;
char inputBuffer[256];
cin.getline(inputBuffer, sizeof(inputBuffer));
string inputString = inputBuffer;
string Buffer;
stringstream ss(inputString);
while(ss >> Buffer)
tokens.push_back(Buffer);
return tokens;
}
bool validArgCount(vector<string> tokens, int size) {
if(tokens.size() == size)
return true;
cerr << "Invalid number of arguments" << endl;
return false;
}
bool diskAvailable() {
if(tfsDisk)
return true;
cerr << "A disk has not been loaded" << endl;
return false;
}
void cmd_import(vector<string> args){
if(validArgCount(args,3) && diskAvailable() && isValidPath(args[1]) && isValidTfsPath(args[2])) {
//TODO
cout << "not implemented" << endl;
}
}
void cmd_export(vector<string> args){
if(validArgCount(args,3) && diskAvailable() && isValidPath(args[1]) && isValidTfsPath(args[2])) {
//TODO
cout << "not implemented" << endl;
}
}
void cmd_ls(vector<string> args){
if(validArgCount(args,1) && diskAvailable()) {
//TODO
cout << "not implemented" << endl;
}
}
void cmd_cd(vector<string> args){
if(diskAvailable()) {
if(args.size() == 1) {
//TODO: change the current working directory to the root directory
cout << "not implemented" << endl;
} else if(args.size() == 2){
string tfsPath = args[1];
if(isValidTfsPath(tfsPath)){
//TODO: change working directory
//need another mutex to lock the working director var.
//what blocks need to be locked?
cout << "not implemented" << endl;
}
} else {
validArgCount(args,2);
}
}
}
void cmd_display(vector<string> args) {
if(validArgCount(args,1) && diskAvailable()) {
cout << "not implemented" << endl;
//TODO:
/*
lock disk
print
0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 //root directory
1 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
3 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // directory takes a whole block
4 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // small file takes a whole block
6 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 // large file takes a whole block + 1-14 blocks
7 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
8 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
9 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
A | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
B | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
C | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
D | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
F | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
unlock disk
*/
}
}
void cmd_open(vector<string> args){
if(validArgCount(args,2) && isValidPath(args[1])) {
//TODO
cout << "not implemented" << endl;
}
}
void cmd_create(vector<string> args){
if(validArgCount(args,2) && isValidPath(args[1])) {
//TODO
cout << "not implemented" << endl;
}
}
void cmd_exit(vector<string> args){
if(validArgCount(args,1)) {
//TODO
// wait for mutexes to unlock
// close file
// exit program
cout << "not implemented" << endl;
}
}
void cmd_mkdir(vector<string> args){
if(validArgCount(args,2) && diskAvailable() && isValidTfsPath(args[1])) {
//TODO
cout << "not implemented" << endl;
}
}
void cmd_rm(vector<string> args){
if(validArgCount(args,2) && diskAvailable() && isValidTfsPath(args[1])) {
//TODO
cout << "not implemented" << endl;
}
}
void mountDisk(int argc, char *argv[]) {
if(argc == 1) {
tfsDisk = 0;
} else if(argc == 2) {
vector<string> cmd;
cmd.push_back("open");
cmd.push_back(argv[1]);
cmd_open(cmd);
} else {
cerr << "usage: " << argv[0] << " [TFS-disk path]" << endl;
exit(EXIT_FAILURE);
}
}
/*
byte * loadDisk(int argc, char *argv[]) {
byte * tfsDisk;
if(argc == 1) {
tfsDisk = new byte[16*2];
} else if(argc == 2) {
string path(argv[1]);
if(!validPath(path)) {
cerr << "Invalid TFS-Disk";
exit(EXIT_FAILURE);
} else {
tfsDisk = loadFile(path);
}
} else {
cerr << "usage: " << argv[0] << " [TFS-disk path]";
exit(EXIT_FAILURE);
}
return tfsDisk;
}*/
typedef void (*function)(vector<string>); //function pointer type
typedef map<string,function> commandMap;
int main(int argc, char *argv[]) {
commandMap cmdMap;
cmdMap.insert(make_pair("import",&cmd_import));
cmdMap.insert(make_pair("export",&cmd_export));
cmdMap.insert(make_pair("ls",&cmd_ls));
cmdMap.insert(make_pair("cd",&cmd_cd));
cmdMap.insert(make_pair("display",&cmd_display));
cmdMap.insert(make_pair("open",&cmd_open));
cmdMap.insert(make_pair("create",&cmd_create));
cmdMap.insert(make_pair("exit",&cmd_exit));
cmdMap.insert(make_pair("mkdir",&cmd_mkdir));
cmdMap.insert(make_pair("rm",&cmd_rm));
mountDisk(argc,argv);
workingDir = "";
//TODO: reset mutex array
while(true) {
cout << "TFS " << "<dir>" << ": ";
vector<string> tokens = parseCommand();
if(tokens.size() == 0 || tokens.size() > 3) {
cerr << "Invalid command" << endl;
} else {
//TODO: create a new thread for each command?
//https://stackoverflow.com/questions/13203307/variable-number-of-threads-c
string cmd = tokens[0];
if(cmdMap.count(cmd)){
commandMap::const_iterator iter = cmdMap.find(cmd);
(*iter->second)(tokens);
} else {
cerr << "Invalid command" << endl;
}
}
}
return 0;
}
04425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E2500000004425248450000000000001E25000000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment