// filesys.cpp // // Created by Kyle Westphal on 10/1/19. // #include "filesys.h" #include <sstream> #include <iostream> using namespace std; Filesys::Filesys(string disk, int numberOfBlocks, int blockSize):Sdisk(disk, numberOfBlocks, blockSize) { rootSize = getBlockSize()/13; fatSize = (4 * getNumberOfBlocks()) / getBlockSize() + 1; //getBlockSize()/4 + 1; string buffer; getBlock(1, buffer); if (buffer[0] == '#') { // no filesys cout << "No file system exits. Creating file system..." << endl; ostringstream outstream; /** Create Root Directory */ for (int i = 1; i <= rootSize; i++) { filename.push_back("xxxxxxxx"); firstBlock.push_back(0); } /** Create filesys */ fat.push_back(fatSize + 1); for (int i = 1; i <= fatSize; i++) { // to fatSize fat.push_back(-1); } for (int i = fatSize + 1; i < getNumberOfBlocks(); i++) { fat.push_back(i + 1); } fat[fat.size()-1] = 0; /** Write FS and Root to disk */ fsSynch(); cout << "File system created." << endl; } else { // read in filesys cout << "File system exits. Reading in file system..." << endl; istringstream instream; buffer.clear(); getBlock(1, buffer); /** Read in Root Directory */ instream.str(buffer); for (int i = 0; i < rootSize; i++) { string f; int b; instream >> f >> b; filename.push_back(f); firstBlock.push_back(b); } /** Read in FAT */ instream.str(""); for (int i = 2; i <= fatSize + 2; i++) { getBlock(i, buffer); instream.str(instream.str() + buffer); } for(int s; instream >> s;) { fat.push_back(s); } cout << "Complete." << endl; } } int Filesys::fsClose() { return 0; } int Filesys::fsSynch() { string buffer; ostringstream outstream; /** Root Directory */ for (int i = 0; i < rootSize; i++) { outstream << filename[i] << " " << firstBlock[i] << " "; } buffer = outstream.str(); vector<string> blocks = block(buffer, getBlockSize()); for (int i = 0; i < blocks.size(); i++) { putBlock(i + 1, blocks[i]); } outstream.str(""); /** Filesys */ for (int i = 0; i < fat.size(); i++) { outstream << fat[i] << " "; } buffer = outstream.str(); blocks = block(buffer, getBlockSize()); for (int i = 0; i < blocks.size(); i++) { putBlock(i + 2, blocks[i]); } return 0; // Success } int Filesys::newFile(string file) { for (int i = 0; i < rootSize; i++) { if (filename[i] == file) { return 0; } } for (int i = 0; i < rootSize; i++){ if (filename[i] == "xxxxxxxx") { filename[i] = file; fsSynch(); return 1; } } fsSynch(); return 0; } int Filesys::rmFile(string file) { for (int i = 0; i < rootSize; i++) { if(filename[i] == file) { if (firstBlock[i] != 0) { cout << "file is not empty" << endl; return 0; } else { filename[i] = "xxxxxxxx"; fsSynch(); return 1; } } } return 0; } int Filesys::getFirstBlock(string file) { for (int i = 0; i < rootSize; i++) { if (filename[i] == file) { return firstBlock[i]; } } return -1; } int Filesys::addBlock(string file, string buffer) { int first = getFirstBlock(file); if (first == -1) { return 0; } int allocate = fat[0]; if (allocate == 0) { // no free blocks return 0; } fat[0] = fat[fat[0]]; fat[allocate] = 0; if(first == 0) { // First block to be added to the file for (int i = 0; i < rootSize; i++) { if (filename[i] == file) { firstBlock[i] = allocate; fsSynch(); putBlock(allocate, buffer); return allocate; } } } else { // find the previous last block int block = first; while(block != 0) { if(fat[block] != 0) { block = fat[block]; } else break; } // update free list fat[block] = allocate; fsSynch(); putBlock(allocate, buffer); return allocate; } return allocate; } int Filesys::delBlock(string file, int blockNumber) { if (!checkBlock(file,blockNumber)) { return 0; } int deallocate = blockNumber; // check to see if block to be deleted is the first block if(blockNumber == getFirstBlock(file)) { for (int i = 0; i < filename.size(); i++) { // check to see if block to be deleted has subsequent blocks // if so, connect previous block to next block if(file == filename[i]) { if(nextBlock(file, blockNumber) != -1) { firstBlock[i] = nextBlock(file, blockNumber); } // if not, add blockNumber to free list else firstBlock[i] = fat[deallocate]; break; } } } // otherwise, delete the block and add the block to the free list else { int iBlock = getFirstBlock(file); while (fat[iBlock] != deallocate) { iBlock = fat[iBlock]; } fat[iBlock] = fat[deallocate]; } fat[deallocate] = fat[0]; fat[0] = deallocate; fsSynch(); return 1; } int Filesys::readBlock(string file, int blockNumber, string& buffer) { if (checkBlock(file, blockNumber)) { getBlock(blockNumber, buffer); return 1; } else return 0; } int Filesys::writeBlock(string file, int blockNumber, string buffer) { if (checkBlock(file, blockNumber)) { putBlock(blockNumber, buffer); return 1; } else return 0; } int Filesys::nextBlock(string file, int blockNumber) { if(checkBlock(file, blockNumber)) { return fat[blockNumber]; } else return -1; } bool Filesys::checkBlock(string file, int blockNumber) { int iBlock = getFirstBlock(file); while(iBlock != 0) { if(iBlock == blockNumber) { return true; } iBlock = fat[iBlock]; } return false; } vector<string> Filesys::ls() { vector<string> fileList; for (int i = 0; i < filename.size(); i++) { if (filename[i] != "xxxxxxxx") { fileList.push_back(filename[i]); } } return fileList; }