Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "LLFS.h"
- #include <iostream>
- #define BLOCK_SIZE 512
- #define BLOCK_COUNT 4096
- namespace Filesystem {
- void format(char *disk) {
- std::cout << "Formatting llfs disk '" << disk << "'\n";
- char *data = (char *) malloc(BLOCK_SIZE * BLOCK_COUNT);
- memset(data, 0, BLOCK_SIZE * BLOCK_COUNT);
- superblock_t *superblock = (superblock_t *) data;
- superblock->type = 0x53464C4C;
- superblock->file_count = 1;
- superblock->inode_count = 1;
- printf(" Marking all blocks as available except superblock and inode blocks\n");
- // mark all blocks as available, except the first 10, and the inode blocks
- char *free_blocks = (char *) data + 512;
- memset(free_blocks, 0xFF, 512);
- for (int i = 0; i < 4096; i++) {
- if (i < 10 || (i % 256) == 255) {
- free_blocks[i / 8] &= ~(1 << (i % 8));
- }
- }
- printf(" Marking all inodes as available\n");
- char *free_inodes = (char *) data + 1024;
- memset(free_inodes, 0xFF, 32);
- printf(" Allocating first inode for root directory\n");
- free_inodes[0] &= ~(1);
- inode_t *rootInode = (inode_t *) data + (255 * 16);
- rootInode->file_size = 512;
- rootInode->file_type = FileType::DIR;
- rootInode->blocks[0] = 10;
- printf(" Allocating first block for root directory\n");
- free_blocks[1] &= ~(1 << (2));
- char *dir = data + 10 * 512;
- strncpy(dir + 1, ".", 30);
- strncpy(dir + 33, "..", 30);
- for (int i = 2; i < 16; i++) {
- dir[i*32] = (unsigned char) 0xFF;
- }
- std::FILE *fdisk = fopen(disk, "w+");
- fwrite(data, 1, 512 * 4096, fdisk);
- fclose(fdisk);
- free(data);
- }
- LLFS *mount(char *disk) {
- std::FILE *fdisk = fopen(disk, "r+");
- LLFS *fs = new LLFS(fdisk);
- return fs;
- }
- void unmount(LLFS *fs) {
- fs->sync();
- }
- LLFS::LLFS(std::FILE *fdisk) : disk(fdisk) {
- superblock = (superblock_t *) malloc(512);
- free_blocks = (char *) malloc(512);
- free_inodes = (char *) malloc(32);
- fseek(disk, 0, SEEK_SET);
- fread(superblock, 1, 512, disk);
- fread(free_blocks, 1, 512, disk);
- fread(free_inodes, 1, 32, disk);
- for (int i = 0; i < 32; i++) {
- inode_block_cache[i] = nullptr;
- }
- open_files_size = 32;
- open_files_index = 0;
- open_files = (File**) malloc(sizeof(File *) * open_files_size);
- static_cache_size = 0;
- static_cache_index = 0;
- static_cache = nullptr;
- dynamic_cache_size = 32;
- dynamic_cache_index = 0;
- dynamic_cache = (BlockCacheEntry **) malloc(sizeof(BlockCacheEntry*) * dynamic_cache_size);
- root = new File(this, nullptr, "/", "/", 0, getInode(0), true);
- }
- /*LLFS::~LLFS() {
- sync();
- fclose(disk);
- delete superblock;
- delete free_blocks;
- delete free_inodes;
- for (int i = 0; i < 32; i++) {
- if (inode_block_cache[i] != nullptr) {
- delete inode_block_cache[i];
- }
- }
- for (int i = 0; i < open_files_index; i++) {
- delete open_files[i];
- }
- delete root;
- delete open_files;
- delete[] inode_block_cache;
- }*/
- File *LLFS::open(char *path) {
- if (strcmp("/", path) == 0) {
- return root;
- }
- for (int i = 0; i < open_files_index; i++) {
- if (strcmp(open_files[i]->getName(), path) == 0) {
- std::cout << "File already open\n";
- return nullptr;
- }
- }
- int len = strlen(path);
- char part[50];
- File *parent = root;
- int o = 0;
- for (int i = 1; i < len; i++) {
- char next = path[i];
- if (next == '/') {
- part[o] = '\0';
- parent = parent->getChildDir(part);
- o = 0;
- } else {
- part[o++] = next;
- }
- }
- part[o] = '\0';
- if (o == 0) {
- return parent;
- }
- File *file = parent->getChild(part);
- open_files[open_files_index++] = file;
- return file;
- }
- void LLFS::close(File *file) {
- bool found = false;
- for (int i = 0; i < open_files_index; i++) {
- if (found) {
- open_files[i - 1] = open_files[i];
- } else {
- if (open_files[i] == file) {
- found = true;
- }
- }
- }
- if (found) {
- open_files_index--;
- }
- delete file;
- }
- inode_t *LLFS::getInode(int number) {
- int inode_block = number / 16;
- if (inode_block_cache[inode_block] == nullptr) {
- std::cout << "Loading inode block " << inode_block << "\n";
- char *inode_block_data = (char *) malloc(512);
- fseek(disk, (inode_block * 256 + 255) * 512, SEEK_SET);
- fread(inode_block_data, 1, 512, disk);
- inode_block_cache[inode_block] = inode_block_data;
- }
- std::cout << "getting inode " << number << "\n";
- inode_t *inode = (inode_t *) (inode_block_cache[inode_block] + (number % 16) * 32);
- return inode;
- }
- unsigned int LLFS::createInode() {
- int number = -1;
- // TODO continue from same point each time
- for (int i = 0; i < 32; i++) {
- unsigned char next = free_inodes[i];
- if (next != 0) {
- int o;
- for (o = 0; o < 8; o++) {
- if (((next >> o) & 1) == 1) {
- number = i * 8 + o;
- break;
- }
- }
- break;
- }
- }
- if (number == -1) {
- printf("Error: no free inodes for allocation");
- return NULL;
- }
- free_inodes[number / 8] &= ~(1 << (number % 8));
- printf("Allocating inode %d\n", number);
- superblock->inode_count++;
- return number;
- }
- BlockCacheEntry *LLFS::allocateBlock() {
- int number = -1;
- // TODO continue from same point each time
- for (int i = 0; i < 512; i++) {
- unsigned char next = free_blocks[i];
- if (next != 0) {
- int o;
- for (o = 0; o < 8; o++) {
- if (((next >> o) & 1) == 1) {
- number = i * 8 + o;
- break;
- }
- }
- break;
- }
- }
- if (number == -1) {
- printf("Error: no free blocks for allocation");
- return nullptr;
- }
- free_blocks[number / 8] &= ~(1 << (number % 8));
- printf("Allocating block %d\n", number);
- return getBlock(number);
- }
- void LLFS::sync() {
- fseek(disk, 0, SEEK_SET);
- fwrite(superblock, 1, 512, disk);
- fwrite(free_blocks, 1, 512, disk);
- fwrite(free_inodes, 1, 32, disk);
- // if we crash here then we just have to notice that an inode/block is ununsed when we walk the tree
- for (int i = 0; i < 32; i++) {
- if (inode_block_cache[i] != nullptr) {
- std::cout << "Saving inode block " << i << "\n";
- fseek(disk, (i * 256 + 255) * 512, SEEK_SET);
- fwrite(inode_block_cache[i], 1, 512, disk);
- }
- }
- // if we crash below here then we lost data but not consistency
- for (int i = 0; i < dynamic_cache_index; i++) {
- BlockCacheEntry *entry = dynamic_cache[i];
- if (entry->modified) {
- fseek(disk, entry->number * 512, SEEK_SET);
- fwrite(entry->block, 1, 512, disk);
- }
- delete entry;
- dynamic_cache[i] = nullptr;
- }
- dynamic_cache_index = 0;
- }
- BlockCacheEntry *LLFS::getBlock(int number) {
- if (static_cache_index > 0) {
- }
- if (dynamic_cache_index > 0) {
- for (int i = 0; i < dynamic_cache_index; i++) {
- BlockCacheEntry *entry = dynamic_cache[i];
- if (entry->number == number) {
- std::cout << "Fetched block " << number << " from dynamic cache\n";
- return entry;
- }
- }
- }
- if (dynamic_cache_index == dynamic_cache_size) {
- std::cout << "Dynamic cache full, syncing to disk\n";
- sync();
- }
- std::cout << "Loading block " << number << " from disk\n";
- char *block = (char*) malloc(512);
- fseek(disk, number*512, SEEK_SET);
- fread(block, 1, 512, disk);
- BlockCacheEntry *entry = new BlockCacheEntry(number, block);
- dynamic_cache[dynamic_cache_index++] = entry;
- return entry;
- }
- std::FILE *LLFS::getDisk() {
- return disk;
- }
- void LLFS::releaseBlock(int num) {
- free_blocks[num/8] |= (1 << (num % 8));
- std::cout << "Releasing block " << num << "\n";
- }
- void LLFS::releaseInode(int num) {
- free_inodes[num / 8] |= (1 << (num % 8));
- int inode_block = num / 16;
- if (inode_block_cache[inode_block] == nullptr) {
- std::cout << "Loading inode block " << inode_block << "\n";
- char *inode_block_data = (char *) malloc(512);
- fseek(disk, (inode_block * 256 + 255) * 512, SEEK_SET);
- fread(inode_block_data, 1, 512, disk);
- inode_block_cache[inode_block] = inode_block_data;
- }
- memset(inode_block_cache[inode_block] + (num % 16) * 32, 0, 32);
- std::cout << "Releasing inode " << num << "\n";
- }
- File::File(LLFS *fs, File *parent, char *name, char *path, int inode_number, inode_t *in, bool isDir) :
- fs(fs), parent(parent), file_name(name), file_path(path), inode(in), isDir(isDir), inode_number(inode_number) {
- std::cout << "Creating file '" << path << " \n";
- created = inode != nullptr;
- seek_pos = 0;
- if (isDir) {
- entries = (DirectoryEntry**) malloc(sizeof(DirectoryEntry*) * 32);
- entries_size = 32;
- entries_index = 0;
- if (created) {
- BlockCacheEntry *data = fs->getBlock(inode->blocks[0]);
- char *block = data->block;
- for (int i = 0; i < 16; i++) {
- unsigned char inode = block[i * 32];
- if (inode != 0xFF) {
- char *fname = (char*) malloc(31);
- memset(fname, 0, 31);
- strncpy(fname, (char *) (block + i * 32 + 1), 30);
- DirectoryEntry *entry = new DirectoryEntry(inode, fname);
- std::cout << "Loaded dir entry " << fname << " for directory " << file_path << "\n";
- entries[entries_index++] = entry;
- }
- }
- }
- } else {
- entries = nullptr;
- entries_size = 0;
- entries_index = 0;
- }
- }
- char *File::getPath() {
- return file_path;
- }
- char *File::getName() {
- return file_name;
- }
- File *File::getParent() {
- return parent;
- }
- bool File::exists() {
- return created;
- }
- bool File::isFile() {
- return !isDir;
- }
- bool File::isDirectory() {
- return isDir;
- }
- File *File::getChild(char *name) {
- if (!isDir) {
- std::cout << "[Error: cannot get child of non-directory" << file_path << "]\n";
- return nullptr;
- }
- std::cout << "Getting child " << name << " from " << file_path << "\n";
- char *fpath = (char*) malloc(250);
- strcpy(fpath, file_path);
- strcat(fpath, name);
- char *fname = (char*)malloc(strlen(name+1));
- strcpy(fname, name);
- for (int i = 0; i < entries_index; i++) {
- if (strcmp(entries[i]->name, name) == 0) {
- return new File(fs, this, fname, fpath, entries[i]->inode, fs->getInode(entries[i]->inode), false);
- }
- }
- return new File(fs, this, fname, fpath, -1, nullptr, false);
- }
- File *File::getChildDir(char *name) {
- if (!isDir) {
- std::cout << "[Error: cannot get child of non-directory" << file_path << "]\n";
- return nullptr;
- }
- // TODO needs to call open
- std::cout << "Getting child directory " << name << " from " << file_path << "\n";
- char *fpath = (char*) malloc(250);
- strcpy(fpath, file_path);
- strcat(fpath, name);
- strcat(fpath, "/");
- char *fname = (char*) malloc(strlen(name + 1));
- strcpy(fname, name);
- for (int i = 0; i < entries_index; i++) {
- if (strcmp(entries[i]->name, name) == 0) {
- return new File(fs, this, fname, fpath, entries[i]->inode, fs->getInode(entries[i]->inode), true);
- }
- }
- return new File(fs, this, fname, fpath, -1, nullptr, true);
- }
- DirectoryEntry **File::getDirectoryContents() {
- return entries;
- }
- void File::create() {
- if (isDir) {
- std::cout << "Use mkdir instead\n";
- return;
- }
- if (created) {
- std::cout << "File already created\n";
- return;
- }
- created = true;
- inode_number = fs->createInode();
- std::cout << "Creating new file '" << file_path << "' " << inode_number << " \n";
- inode = fs->getInode(inode_number);
- inode->file_size = 0;
- inode->file_type = FileType::FILE;
- parent->addFile(this);
- }
- void File::addFile(File *child) {
- if (!isDir) {
- std::cout << "Can only add files to directories\n";
- return;
- }
- std::cout << "Adding file " << child->file_path << " to directory " << file_path << "\n";
- DirectoryEntry *entry = new DirectoryEntry(child->inode_number, child->file_name);
- entries[entries_index++] = entry;
- BlockCacheEntry *block = fs->getBlock(inode->blocks[0]);
- std::cout << "Saving directory contents of " << file_path << " to block " << inode->blocks[0] << "\n";
- block->modified = true;
- for (int i = 0; i < 16; i++) {
- if (i >= entries_index) {
- block->block[i * 32] = (unsigned char) 0xFF;
- } else {
- block->block[i * 32] = entries[i]->inode;
- strncpy((char*)(block->block + i * 32 + 1), entries[i]->name, 31);
- }
- }
- }
- void File::seek(int pos) {
- seek_pos = pos;
- std::cout << "Seeking file " << file_path << " to position " << pos << "\n";
- }
- void File::write(char *src, int len) {
- std::cout << "Writing " << len << " bytes to " << file_path << " at position " << seek_pos << "\n";
- int remaining = len;
- int offset = 0;
- while (remaining > 0) {
- int block_pos = seek_pos / 512;
- BlockCacheEntry *block = nullptr;
- if (inode->blocks[block_pos] == 0) {
- block = fs->allocateBlock();
- inode->blocks[block_pos] = block->number;
- } else {
- block = fs->getBlock(inode->blocks[block_pos]);
- }
- int subpos = seek_pos % 512;
- int sublen = 512 - subpos;
- if (remaining < sublen) {
- sublen = remaining;
- }
- memcpy(block->block + subpos, src + offset, sublen);
- block->modified = true;
- seek_pos += sublen;
- remaining -= sublen;
- offset += sublen;
- }
- if (seek_pos > inode->file_size) {
- inode->file_size = seek_pos;
- std::cout << "new file size is " << inode->file_size << "\n";
- }
- }
- int File::read(char *dest, int len) {
- if (seek_pos + len >= inode->file_size) {
- len = inode->file_size - seek_pos;
- }
- std::cout << "Reading " << len << " bytes from file " << file_path << " at position " << seek_pos << "\n";
- int remaining = len;
- int offset = 0;
- while (remaining > 0) {
- int block_pos = seek_pos / 512;
- BlockCacheEntry *block = nullptr;
- if (inode->blocks[block_pos] == 0) {
- block = fs->allocateBlock();
- inode->blocks[block_pos] = block->number;
- } else {
- block = fs->getBlock(inode->blocks[block_pos]);
- }
- int subpos = seek_pos % 512;
- int sublen = 512 - subpos;
- if (remaining < sublen) {
- sublen = remaining;
- }
- memcpy(dest + offset, block->block + subpos, sublen);
- seek_pos += sublen;
- offset += sublen;
- remaining -= sublen;
- }
- return len;
- }
- void File::mkdir() {
- if (!isDir) {
- std::cout << "Cannot make a directory in a file\n";
- return;
- }
- if (created) {
- std::cout << "Directory already created\n";
- return;
- }
- created = true;
- inode_number = fs->createInode();
- std::cout << "Creating new dir '" << file_path << "' " << inode_number << " \n";
- inode = fs->getInode(inode_number);
- inode->file_size = 512;
- inode->file_type = FileType::DIR;
- parent->addFile(this);
- entries = (DirectoryEntry**) malloc(sizeof(DirectoryEntry*) * 32);
- entries_size = 32;
- entries_index = 0;
- DirectoryEntry *self_dir = new DirectoryEntry(inode_number, ".");
- DirectoryEntry *parent_dir = new DirectoryEntry(parent->inode_number, "..");
- entries[entries_index++] = self_dir;
- entries[entries_index++] = parent_dir;
- BlockCacheEntry *data = fs->allocateBlock();
- inode->blocks[0] = data->number;
- std::cout << "Saving directory contents of " << file_path << " to block " << inode->blocks[0] << "\n";
- data->modified = true;
- for (int i = 0; i < 16; i++) {
- if (i >= entries_index) {
- data->block[i * 32] = (unsigned char) 0xFF;
- } else {
- data->block[i * 32] = entries[i]->inode;
- strncpy((char*) (data->block + i * 32 + 1), entries[i]->name, 31);
- }
- }
- }
- void File::remove() {
- if (parent == nullptr) {
- std::cout << "Cannot delete the root directory\n";
- }
- if (isDir) {
- std::cout << "Deleting directory " << file_path << "\n";
- for (int i = 0; i < entries_index; i++) {
- DirectoryEntry *entry = entries[i];
- inode_t *child_inode = fs->getInode(entry->inode);
- if (child_inode->file_type == FileType::DIR) {
- File *child_dir = getChildDir(entry->name);
- child_dir->remove();
- } else {
- File *child = getChild(entry->name);
- child->remove();
- }
- }
- } else {
- std::cout << "Deleting file " << file_path << "\n";
- }
- parent->removeFile(inode_number);
- for (int i = 0; i < 10; i++) {
- if (inode->blocks[i] != 0) {
- fs->releaseBlock(inode->blocks[i]);
- }
- }
- fs->releaseInode(inode_number);
- }
- void File::removeFile(int inode_num) {
- if (!isDir) {
- std::cout << "Can only remove files from directories\n";
- return;
- }
- bool found = false;
- DirectoryEntry *found_entry = nullptr;
- for (int i = 0; i < entries_index; i++) {
- if (found) {
- entries[i - 1] = entries[i];
- } else {
- if (entries[i]->inode == inode_num) {
- found = true;
- found_entry = entries[i];
- }
- }
- }
- if (found_entry == nullptr) {
- std::cout << "File with inode " << inode_num << " not found in directory " << file_path << "\n";
- return;
- }
- entries_index--;
- delete found_entry;
- BlockCacheEntry *block = fs->getBlock(inode->blocks[0]);
- std::cout << "Saving directory contents of " << file_path << " to block " << inode->blocks[0] << "\n";
- block->modified = true;
- for (int i = 0; i < 16; i++) {
- if (i >= entries_index) {
- block->block[i * 32] = (unsigned char) 0xFF;
- memset(block->block + i * 32 + 1, 0, 31);
- } else {
- block->block[i * 32] = entries[i]->inode;
- strncpy((char*) (block->block + i * 32 + 1), entries[i]->name, 31);
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement