// Bastard File System
// (C) 2007 Rene Schickbauer
//
// The Bastard File System (BFS) is a small virtual FS for Applications
// that would normally use Tarballs and/or Zipfiles but have to dynamically
// change its contents
//
// WARNING: This is still ALPHA QUALITY CODE! Use with care!
//
//
// Main header for BFS

#ifndef BFS_H
#define BFS_H

#include <stdio.h>
#include <stdlib.h>

#define BFSVERSION "BFS 1.0"

// MAXDATABLOCKS: Max. number of data blocks (102400 = 50MB incl. overhead)
#define MAXDATABLOCKS 102400

// MAXSUBDIRLEVEL: max dir-tree depth
#define MAXSUBDIRLEVEL 50

// DIRENTRY_PER_BLOCK = how much entries fit into 1 dirblock
#define DIRENTRY_PER_BLOCK 13

#define FILEBLOCK_DATASIZE 501

// MAXFILESPERDIR = max number of files per dir
#define MAXFILESPERDIR 1000

/* DESIGNES LIMITS:
    *) Every part of the filename is limited to 30 chars
    
*/
    
// This are "normal" defines, so we have no char-convert problem
#define BLOCKTYPE_FREE ' '
#define BLOCKTYPE_FILE 'f'
#define BLOCKTYPE_DIR 'd'
#define BLOCKTYPE_NONE 'n'



struct sBFS {
    FILE* fh ;
    char fname[1000];
    int numDataBlocks;
    int numHeadBlocks;
    char blocktype[MAXDATABLOCKS];
    char lastError[1000];
};

struct BLOCK_RAW {
    char data[512];
};

struct BLOCK_FREE {
	char blockType[1];
    char data[511];
};

struct BLOCK_FILE {
	char blockType[1];
    char prevBlock[4];
    char nextBlock[4];
    char dataLength[2];
    char data[FILEBLOCK_DATASIZE];
};

struct BLOCK_DIR_ENTRY {
    char type[1];  // DIRENTRY_*
    char name[31]; // 30 + \0 --> empty string == free slot
    char startblock[4];
};
    

struct BLOCK_DIR {
	char blockType[1];
    char prevBlock[4];
    char nextBlock[4];
    struct BLOCK_DIR_ENTRY entry[DIRENTRY_PER_BLOCK];
    char reserved[35];
};    
    
struct BLOCK_MAGIC {
    char IDSTRING [100];
    char numHeadBlocks[4];
    char numDataBlocks[4];
    char reserved[404];
};

struct BLOCK_HEADER {
    char blockType[512];
};

struct FILEDATA {
    int length;
    void* data;
};

struct DIRTREE_ELEMENT {
    char name[31];
    char type[1];
    int startblock;
};

struct DIRTREE {
    int elemcount;
    struct DIRTREE_ELEMENT element[MAXSUBDIRLEVEL];
};

struct DIRLIST_ELEMENT {
    char name[31];
    char type[1];
    int startblock;
    int numBlocks;
    int fileSize;
};

struct DIRLIST {
    int elemcount;
    struct DIRLIST_ELEMENT element[MAXFILESPERDIR];
};


// Functions
   // FS specific
sBFS* bfsGetNewHandle();
bool bfsCloseHandle(sBFS* handle);
bool bfsOpen(sBFS* handle, char* filename);
bool bfsClose(sBFS* handle);
bool bfsNew(sBFS* handle, char* filename, int blocks);
   // File handling
bool bfsReadFile(sBFS* handle, char* filename, FILEDATA* data);
bool bfsWriteFile(sBFS* handle, char* filename, FILEDATA* data);
bool bfsGetFileSize(sBFS* handle, char* filename, int *size);
bool bfsDeleteFile(sBFS* handle, char* filename);
   // Dir Handling
bool bfsMakeDir(sBFS* handle, char* dirname);
bool bfsRemoveDir(sBFS* handle, char* dirname);
bool bfsListDir(sBFS* handle, char* path, DIRLIST* list);
bool bfsDumpDirTree(sBFS* handle);
   // Maintainance functions
bool bfsDefrag(sBFS* handle);
bool bfsResize(sBFS* handle, int blocks);
bool bfsShrink(sBFS* handle);
    // Error Handling
char* getLastError(sBFS* handle);

#endif // BFS_H
