//Author Lhz
#include<iostream>
#include<fstream>
#include<string>
#include<vector>

#define KB * (1 << 10)
#define MB * (1 << 20)
#define INODE * 32
#define BUF (char*)&
#define iMapCou 20 //inode位示图的大小
#define bMapCou 640 //块位示图的大小
#define MAX 4294967295 //unsigned int 的最大值
#define END -2333 //文件结束符

using namespace std;

//文件inode数据结构(32B)
typedef struct fileInode {

	char type;         //'F'表示常规文件,'D'表示目录文件,'R'表示根目录
	char linkCount;    //链接数
	short inodeNum;
	short psyAddr[13]; //文件块地址,0-9为直接指针,
	//10-11为一级地址,12为二级地址
	int length;        //文件长度(以KB为单位)
}fileInode;

//目录条目结构
typedef struct entryNode {

	string fileName;       //文件名
	short nameLength;      //文件名长度
	short inodeNum;        //inode号
}entryNode;

typedef struct dirInode {

	string dirName;
	vector<entryNode> entryQueue; //条目集
	char type;
	char totalEntryCount; //对应fileInode的链接数,代表条目数
	short inodeNum;
	short psyAddr[13]; //文件块地址,0-9为直接指针,
	//10-11为一级地址,12为二级地址
	int length;        //文件长度(以KB为单位)
}dirInode;

//超级块数据结构
typedef struct superBlock {

	short totalBlockCount;	//总可分配文件区块数
	short freeBlockCount;   //剩余空闲可分配文件区块数
	short totalInodeCount;  //总inode数  640
	short freeInodeCount;   //剩余可分配inode数
	short rootDir;          //根目录地址

	unsigned int iMap[20];  //inode位示图
	unsigned int bMap[640]; //文件区位示图

}superBlock;

superBlock SB;

vector<fileInode> fileQueue; //需修改的文件的inode集

vector<dirInode> dirQueue; //需修改的目录文件的inode集

string fileName = "os.dat"; //磁盘文件名

vector<string> path; //当前路径

dirInode* now = nullptr; //指向当前目录的指针

bool ReadSystem();
void Format();
void Init();
void SaveSuperBlock();
void SaveDirInode();
void SaveNormalDir(dirInode& dir);
void SaveRootDir(dirInode& dir);
void SaveFileInode();
void SaveData();
void InitSystem();
void Help();
void Run();
void SysShow();
void Ls();
void Mk();
void Arrange(int length, short& inodeNum, short psyAddr[13]);
short ArrangeInode();
void ArrangeBlock(int length, short psyAddr[13]);
void Set(unsigned int map[], int iIndex, int bIndex);
void Reset(unsigned int map[], int iIndex, int bIndex);
bool Test(unsigned int map[], int iIndex, int bIndex);
short SearchBit(unsigned int map[], int sum);
void Mkdir();
void Cat();
void GetFile(int  inodeNum);
void Link();
void Cd();
void GetDir(int inodeNum);
void Rm();
void RemoveFile(int inodeNum);
void Reclaim(int inodeNum, int length, short* psyAddr);
void ReclaimInode(int inodeNum);
void ReclaimBlock(int length, short psyAddr[13]);
void BitReclaimMachine(vector<short>& bitCollective);
void Rmdir();
void RemoveDir(int inodeNum);

bool ReadSystem() {

	fstream in;
	in.open(fileName, ios::in | ios::binary);

	if (!in.is_open()) {

		cout << "磁盘未挂载" << endl;
		cout << endl;
		return false;
	}

	//读取超级块数据
	in.seekg(0 KB, ios::beg);
	in.read(BUF SB, sizeof(SB));

	//读取根目录数据
	in.seekg(SB.rootDir KB, ios::beg);
	dirInode tmpDir;
	tmpDir.type = 'R';
	tmpDir.dirName = "\\";
	tmpDir.inodeNum = -1;
	in.read(BUF tmpDir.totalEntryCount, sizeof(char));

	for (int i = 0; i < tmpDir.totalEntryCount; ++i) {

		entryNode tmpEntry;
		short stringLength;
		in.read(BUF stringLength, sizeof(short));

		//分条读取条目
		char* temp = new char[stringLength];
		in.read(temp, stringLength);
		tmpEntry.fileName = temp;
		delete temp;

		tmpEntry.nameLength = tmpEntry.fileName.length();
		in.read(BUF tmpEntry.inodeNum, sizeof(short));
		tmpDir.entryQueue.push_back(tmpEntry);
	}
	path.push_back(tmpDir.dirName);
	dirQueue.push_back(tmpDir);
	for (auto& i : dirQueue)
		if (i.inodeNum == -1)
			now = &i;

	in.close();
	return true;
}

//挂载磁盘
void Format() {

	cout << "磁盘正在挂载......" << endl;
	cout << endl;

	fstream out;
	out.open(fileName, ios::out | ios::binary);

	if (!out.is_open()) {

		cout << "磁盘挂载失败" << endl;
		cout << endl;
		return;
	}

	//向文件中写入20MB个'0'
	char tmp = '0';
	for (int i = 0; i < 20 MB; i++)
		out.write((char*)&tmp, sizeof(char));

	out.close();
	return;
}

//初始化超级块暨根目录
void Init() {

	SB.rootDir = 21; //#21-#30为根目录区
	SB.totalBlockCount = 20449;
	SB.freeBlockCount = 20449;
	SB.totalInodeCount = 640;
	SB.freeInodeCount = 640;

	//初始化inode位图
	for (int i = 0; i < 20; i++) {

		SB.iMap[i] = 0;
	}

	//初始化文件位图
	for (int i = 0; i < 640; i++) {

		SB.bMap[i] = 0;
	}

	//初始化根目录的dirInode
	dirInode tmpDirInode;
	tmpDirInode.dirName = "\\";
	tmpDirInode.inodeNum = -1;
	tmpDirInode.totalEntryCount = (char)1;
	tmpDirInode.type = 'R';

	//向根目录中增加'.'条目
	entryNode tmpEntry;
	tmpEntry.fileName = ".";
	tmpEntry.inodeNum = -1;
	tmpEntry.nameLength = tmpEntry.fileName.length();;
	tmpDirInode.entryQueue.push_back(tmpEntry);

	dirQueue.push_back(tmpDirInode);
	path.push_back(tmpDirInode.dirName);
	for (auto& i : dirQueue)
		if (i.inodeNum == -1)
			now = &i;
	return;
}

//将超级块写入磁盘
void SaveSuperBlock() {

	fstream out;
	out.open(fileName, ios::out | ios::binary | ios::in);
	out.seekp(0, ios::beg);
	out.write(BUF SB, sizeof(SB));
	out.close();
	return;
}

//将inode写入磁盘
void SaveDirInode() {

	for (auto i : dirQueue) {

		if (i.type == 'R')
			SaveRootDir(i);
		else if (i.type == 'D')
			SaveNormalDir(i);
	}
	return;
}

//将普通目录写入磁盘
void SaveNormalDir(dirInode& dir) {

	fstream out;
	out.open(fileName, ios::out | ios::binary | ios::in);
	out.seekp(1 KB + dir.inodeNum INODE, ios::beg);
	out.write(BUF dir.type, sizeof(char));
	out.write(BUF dir.totalEntryCount, sizeof(char));
	out.write(BUF dir.inodeNum, sizeof(short));
	out.write(BUF dir.psyAddr, 13 * sizeof(short));
	out.write(BUF dir.length, sizeof(int));

	//一次简化的尝试,作了文件条目总长度不会超过4KB的假设
	int lengthSum = 0;
	int ptrIndex = 0;
	short end = END; //块结束标识符

	out.seekp((31 + dir.psyAddr[ptrIndex]) KB, ios::beg);

	for (auto& iter : dir.entryQueue) {

		short stringLength = sizeof(iter.fileName);
		if (lengthSum + stringLength + 3 * sizeof(short) > 1 KB) {

			out.write(BUF end, sizeof(short));
			out.seekp((31 + dir.psyAddr[++ptrIndex]) KB, ios::beg);
			lengthSum = 0;
		}

		out.write(BUF stringLength, sizeof(short));
		out.write(iter.fileName.data(), stringLength);
		out.write(BUF iter.inodeNum, sizeof(short));
		lengthSum += stringLength + 4;
	}

	out.close();
	return;
}


//将根目录写入磁盘
void SaveRootDir(dirInode& dir) {

	fstream out;
	out.open(fileName, ios::out | ios::binary | ios::in);
	out.seekp(SB.rootDir KB, ios::beg);
	out.write(BUF dir.totalEntryCount, sizeof(char));
	for (auto iter : dir.entryQueue) {

		short stringLength = sizeof(iter.fileName);
		out.write(BUF stringLength, sizeof(short));
		out.write(iter.fileName.data(), sizeof(iter.fileName));
		out.write(BUF iter.inodeNum, sizeof(short));
	}

	out.close();
	return;
}

//将文件写入磁盘
void SaveFileInode() {

	fstream out;
	out.open(fileName, ios::out | ios::binary | ios::in);

	for (auto file : fileQueue) {

		out.seekp(1 KB + file.inodeNum INODE, ios::beg);
		out.write(BUF file, sizeof(file));
	}
	out.close();
	return;
}

//将数据写入磁盘
void SaveData() {

	SaveSuperBlock();
	SaveDirInode();
	SaveFileInode();
	return;
}

//磁盘初始化
void InitSystem() {

	Format();
	Init();
	SaveData();
	return;
}

//显示文件系统信息
void SysShow() {
	cout << "总inode数:" << SB.totalInodeCount << endl
		<< "剩余inode数:" << SB.freeInodeCount << endl
		<< "总可用块数:" << SB.totalBlockCount << endl
		<< "剩余可用块数:" << SB.freeBlockCount << endl;
	return;
}

//显示目录信息
void Ls() {

	int index = 0;
	cout << "条目数:" << (int)now->totalEntryCount << endl;
	for (auto i : now->entryQueue) {
		cout << "条目" << ++index << ":" << endl
			<< "   名称:" << i.fileName << endl
			<< "   名称长度:" << i.nameLength << endl
			<< "   inode:" << i.inodeNum << endl;
	}
	return;
}

//创建文件
void Mk() {

	string fileName;
	int fileLength;

	cin >> fileName >> fileLength;

	for (auto i : now->entryQueue) {

		if (i.fileName == fileName) {

			cout << "文件已存在" << endl;
			return;
		}
	}

	//创建文件inode
	fileInode tmpFile;
	tmpFile.type = 'F';
	tmpFile.length = fileLength;
	tmpFile.linkCount = 1;
	Arrange(tmpFile.length, tmpFile.inodeNum, tmpFile.psyAddr);
	fileQueue.push_back(tmpFile);

	//向父目录中增加条目
	entryNode tmpEntry;
	tmpEntry.fileName = fileName;
	tmpEntry.inodeNum = tmpFile.inodeNum;
	tmpEntry.nameLength = fileName.length();
	now->entryQueue.push_back(tmpEntry);
	now->totalEntryCount++;

	return;
}

//分配inode与块
void Arrange(int length, short& inodeNum, short psyAddr[13]) {

	//此处存在一个问题:并没有考虑到需要分配一级指针和二级指针的情况
	if (length > SB.freeBlockCount) {

		cout << "磁盘空间不足" << endl;
		return;
	}

	if (SB.freeInodeCount == 0) {

		cout << "文件数已达到上限" << endl;
		return;
	}

	inodeNum = ArrangeInode();
	ArrangeBlock(length, psyAddr);
}

//分配块
void ArrangeBlock(int length, short psyAddr[13]) {

	//直接指针分配
	for (int i = 0; i < 10 && length; ++i, --length) {

		psyAddr[i] = SearchBit(SB.bMap, bMapCou);
		SB.freeBlockCount--;
	}

	//一级指针分配
	for (int i = 10; i < 12 && length; ++i) {

		psyAddr[i] = SearchBit(SB.bMap, bMapCou);
		SB.freeBlockCount--;
		fstream out;
		out.open(fileName, ios::in | ios::binary | ios::out);
		out.seekp((31 + psyAddr[i]) KB, ios::beg);

		int firstLength = (1 << 9);
		for (int j = 0; j < firstLength && length; ++j, --length) {

			short tmp = SearchBit(SB.bMap, bMapCou);
			SB.freeBlockCount--;
			out.write(BUF tmp, sizeof(short));
		}

		out.close();
	}

	//二级指针分配
	if (length > 0) {

		psyAddr[12] = SearchBit(SB.bMap, bMapCou);
		SB.freeBlockCount--;
		fstream out;
		out.open(fileName, ios::in | ios::binary | ios::out);
		for (int i = 0; i < (1 << 9) && length; ++i) {

			out.seekp((31 + psyAddr[12]) KB + i * sizeof(short), ios::beg);
			short tmp = SearchBit(SB.bMap, bMapCou);
			SB.freeBlockCount--;
			out.write(BUF tmp, sizeof(short));
			out.seekp((31 + tmp) KB, ios::beg);
			for (int j = 0; j < (1 << 9) && length; ++j, --length) {

				short tmp2 = SearchBit(SB.bMap, bMapCou);
				SB.freeBlockCount--;
				out.write(BUF tmp2, sizeof(short));
			}
		}
		out.close();
	}

	return;
}

//分配inode
short ArrangeInode() {

	SB.freeInodeCount--;
	return SearchBit(SB.iMap, iMapCou);
}

//查找空位
short SearchBit(unsigned int map[], int sum) {

	int iIndex = 0; //表示位图中的第几号unsigned int
	int bIndex = 0; //表示unsigned int中的第几位bit

	for (; iIndex < sum; ++iIndex) {
		if (map[iIndex] == MAX)
			continue;
		for (bIndex = 0; bIndex < 32; ++bIndex) {

			if (Test(map, iIndex, bIndex))
				continue;
			else {

				Set(map, iIndex, bIndex);
				return 32 * iIndex + bIndex;
			}
		}
	}
}

//检查位示图该位是否已被分配
bool Test(unsigned int map[], int iIndex, int bIndex) {

	return map[iIndex] & (1 << bIndex);
}

//将位示图某位置1
void Set(unsigned int map[], int iIndex, int bIndex) {

	map[iIndex] |= (1 << bIndex);
	return;
}

//将位示图某位取反
void Reset(unsigned int map[], int iIndex, int bIndex) {

	map[iIndex] &= ~(1 << bIndex);
	return;
}

//创建目录
void Mkdir() {

	string dirName;

	cin >> dirName;

	for (auto i : now->entryQueue) {

		if (i.fileName == dirName) {

			cout << "文件已存在" << endl;
			return;
		}
	}

	//创建目录文件
	dirInode tmpDir;
	tmpDir.type = 'D';
	tmpDir.dirName = dirName;
	tmpDir.totalEntryCount = 2;
	tmpDir.length = 4;
	Arrange(tmpDir.length, tmpDir.inodeNum, tmpDir.psyAddr);

	//向新建目录中增加"."条目
	entryNode tmpLocalEntry;
	tmpLocalEntry.fileName = ".";
	tmpLocalEntry.inodeNum = tmpDir.inodeNum;
	tmpLocalEntry.nameLength = tmpLocalEntry.fileName.length();
	tmpDir.entryQueue.push_back(tmpLocalEntry);

	//向新建目录中增加".."条目
	entryNode tmpPartenEntry;
	tmpPartenEntry.fileName = "..";
	tmpPartenEntry.inodeNum = now->inodeNum;
	tmpPartenEntry.nameLength = tmpPartenEntry.fileName.length();
	tmpDir.entryQueue.push_back(tmpPartenEntry);

	//向父目录中增加条目
	entryNode tmpEntry;
	tmpEntry.fileName = dirName;
	tmpEntry.inodeNum = tmpDir.inodeNum;
	tmpEntry.nameLength = dirName.length();
	now->entryQueue.push_back(tmpEntry);
	now->totalEntryCount++;

	//似乎是由于插入一个新节点后,出于空间不足的原因,
	//vector会更换位置,因此当前目录指针需要重新定位
	int partenInode = now->inodeNum;
	dirQueue.push_back(tmpDir);
	for (auto& i : dirQueue)
		if (i.inodeNum == partenInode) {
			now = &i;
			break;
		}

	return;
}

//查看文件
//该函数做了一个简化的假设,即不会打开任何目录文件
void Cat() {

	int inodeNum = -2;
	string fileName;
	cin >> fileName;

	//检查文件是否存在
	bool flag = false;
	for (auto i : now->entryQueue) {

		if (i.fileName == fileName) {

			inodeNum = i.inodeNum;
			flag = true;
			break;
		}
	}

	if (!flag) {

		cout << "文件不存在" << endl;
		return;
	}
	else {

		//获得文件信息并输出文件
		GetFile(inodeNum);
		for (auto i : fileQueue) {

			if (i.inodeNum == inodeNum) {

				cout << "文件名:" << fileName << endl
					<< "inode:" << i.inodeNum << endl
					<< "文件长度:" << i.length << " KB" << endl
					<< "链接数:" << (int)i.linkCount << endl;
				for (int j = 0; j < 13; j++) {

					if (j < 10)
						cout << "直接指针:" << i.psyAddr[j] << endl;
					else if (j < 12)
						cout << "一级指针" << i.psyAddr[j] << endl;
					else
						cout << "二级指针" << i.psyAddr[j] << endl;
				}
				break;
			}
		}
	}
	return;
}

//读取已存在的文件信息
void GetFile(int inodeNum) {

	for (auto i : fileQueue)
		if (i.inodeNum == inodeNum)
			return;

	fstream in;
	in.open(fileName, ios::in | ios::binary | ios::out);
	in.seekg(1 KB + inodeNum INODE, ios::beg);

	fileInode tmpFile;
	in.read(BUF tmpFile, sizeof(fileInode));

	fileQueue.push_back(tmpFile);
	in.close();
	return;
}

//创建链接文件
//一个简化的假设:用户不会尝试链接一个目录
void Link() {

	int inodeNum = -2;
	string newFileName, oldFileName;
	cin >> newFileName >> oldFileName;

	//检查文件是否存在
	bool flag = false;
	for (auto i : now->entryQueue) {

		if (i.fileName == oldFileName) {

			inodeNum = i.inodeNum;
			flag = true;
			break;
		}
	}

	if (!flag) {

		cout << "文件不存在" << endl;
		return;
	}
	else {

		//获取文件信息,并修改链接计数
		GetFile(inodeNum);
		for (auto& i : fileQueue) {

			if (i.inodeNum == inodeNum) {

				i.linkCount++;
				break;
			}
		}

		//创建链接条目,并将它添加到目录中
		//注意:为了简化,该链接只能链接当前目录下的文件
		entryNode linkEntry;
		linkEntry.fileName = newFileName;
		linkEntry.inodeNum = inodeNum;
		linkEntry.nameLength = linkEntry.fileName.length();
		now->entryQueue.push_back(linkEntry);
		now->totalEntryCount++;
	}
}

//同样是一次简化的尝试:假设用户不会做出任何非法操作
//并且跳转仅限于父目录和子目录
void Cd() {

	int inodeNum;
	string dirName;
	cin >> dirName;

	if (dirName == ".")
		return;

	//判断目录是否存在
	int flag = false;
	for (auto i : now->entryQueue) {

		if (i.fileName == dirName) {

			inodeNum = i.inodeNum;
			flag = true;
			break;
		}
	}

	if (!flag) {
		cout << "目录不存在" << endl;
		return;
	}
	else {

		//获取目录信息,并将当前目录指针指向新目录
		GetDir(inodeNum);
		for (auto& i : dirQueue)
			if (i.inodeNum == inodeNum)
				now = &i;

		//更新路径
		if (dirName == "..")
			path.pop_back();
		else {
			path.push_back(dirName);
			now->dirName = dirName;
		}
	}
}

//读取目录信息
void GetDir(int inodeNum) {

	for (auto i : dirQueue)
		if (i.inodeNum == inodeNum)
			return;

	dirInode tmpDir;

	//读取目录inode
	fstream in;
	in.open(fileName, ios::out | ios::binary | ios::in);
	in.seekg(1 KB + inodeNum INODE, ios::beg);
	in.read(BUF tmpDir.type, sizeof(char));
	in.read(BUF tmpDir.totalEntryCount, sizeof(char));
	in.read(BUF tmpDir.inodeNum, sizeof(short));
	in.read(BUF tmpDir.psyAddr, 13 * sizeof(short));
	in.read(BUF tmpDir.length, sizeof(int));

	//读取条目信息
	int index = 0;
	int lengthSum = 0;//用来记录块内偏移量
	in.seekg((31 + tmpDir.psyAddr[index]) KB, ios::beg);
	int tmp = (int)tmpDir.totalEntryCount;
	while (tmp--) {

		entryNode tmpEntry;
		short stringLength;
		//由于一些未知的原因,读取条目时会出现读取异常
		//在尝试了每次读取后重新跳转和一系列更改后,异常消失了
		//也许删掉它也没关系,但最好不要动它,异常原因是未知的......
		in.seekg((31 + tmpDir.psyAddr[index]) KB + lengthSum, ios::beg);
		in.read(BUF stringLength, sizeof(short));

		//检测是否已到文件尾
		//如果已到文件尾,则跳转到下一块并重新读取
		if (tmpEntry.nameLength == END) {

			lengthSum = 0;
			in.seekg((31 + tmpDir.psyAddr[++index]) KB, ios::beg);
			in.read(BUF stringLength, sizeof(short));
		}

		//读取条目名
		char* temp = new char[stringLength];
		in.read(temp, stringLength);
		tmpEntry.fileName = temp;
		delete temp;

		tmpEntry.nameLength = tmpEntry.fileName.length();
		in.read(BUF tmpEntry.inodeNum, sizeof(short));
		tmpDir.entryQueue.push_back(tmpEntry);

		lengthSum += stringLength + 4;
	}

	dirQueue.push_back(tmpDir);
	in.close();
	return;
}

//同样假设用户不会做出非法操作
void Rm() {

	int inodeNum;
	string fileName;
	cin >> fileName;

	//判断文件是否存在
	bool flag = false;
	for (auto i : now->entryQueue)
		if (i.fileName == fileName) {

			inodeNum = i.inodeNum;
			flag = true;
			break;
		}
	if (!flag) {

		cout << "文件不存在" << endl;
		return;
	}

	//删除文件
	RemoveFile(inodeNum);

	//删除条目
	for (auto iter = now->entryQueue.begin(); iter < now->entryQueue.end(); ++iter)
		if (iter->fileName == fileName) {

			now->entryQueue.erase(iter);
			now->totalEntryCount--;
			break;
		}

	return;
}

//删除文件
void RemoveFile(int inodeNum) {

	fileInode* tmpFile = nullptr;

	//将链接计数减一
	GetFile(inodeNum);
	for (auto& i : fileQueue)
		if (i.inodeNum == inodeNum) {
			i.linkCount--;
			tmpFile = &i;
			break;
		}

	if (tmpFile->linkCount > 0)
		return;

	Reclaim(inodeNum, tmpFile->length, tmpFile->psyAddr);

	for (auto iter = fileQueue.begin(); iter < fileQueue.end(); ++iter)
		if (iter->inodeNum == inodeNum) {

			fileQueue.erase(iter);
			break;
		}

	return;
}

//回收inode和block
void Reclaim(int inodeNum, int length, short* psyAddr) {

	ReclaimInode(inodeNum);
	ReclaimBlock(length, psyAddr);
}

//回收inode
void ReclaimInode(int inodeNum) {

	Reset(SB.iMap, inodeNum / 32, inodeNum % 32);
	SB.freeInodeCount++;
	return;
}

//回收block
void ReclaimBlock(int length, short psyAddr[13]) {

	vector<short> bitCollective;

	//回收直接指针块
	for (int i = 0; i < 10 && length; ++i, --length) {

		bitCollective.push_back(psyAddr[i]);
		SB.freeBlockCount++;
	}

	//回收一级指针块
	for (int i = 10; i < 12 && length; ++i) {

		bitCollective.push_back(psyAddr[i]);
		SB.freeBlockCount++;
		fstream in;
		in.open(fileName, ios::in | ios::binary | ios::out);
		in.seekg(31 + psyAddr[i] KB, ios::beg);

		//回收块内指针块
		int firstLength = (1 << 9);
		for (int j = 0; j < firstLength && length; ++j, --length) {

			short tmp;
			in.read(BUF tmp, sizeof(short));
			SB.freeBlockCount++;
			bitCollective.push_back(tmp);
		}

		in.close();
	}

	//回收二级指针块
	if (length > 0) {

		bitCollective.push_back(psyAddr[12]);
		SB.freeBlockCount++;
		fstream in;
		in.open(fileName, ios::in | ios::binary | ios::out);
		//回收一级指针块
		for (int i = 0; i < (1 << 9) && length; ++i) {

			int tmp1;
			in.seekg((31 + psyAddr[12]) KB + i * sizeof(short), ios::beg);
			in.read(BUF tmp1, sizeof(short));
			SB.freeBlockCount++;
			//回收块内指针块
			in.seekg((31 + tmp1) KB, ios::beg);
			for (int j = 0; j < (1 << 9) && length; ++j, --length) {

				short tmp2;
				in.read(BUF tmp2, ios::beg);
				bitCollective.push_back(tmp2);
				SB.freeBlockCount++;
			}
		}
		in.close();
	}

	BitReclaimMachine(bitCollective);
	return;
}

void BitReclaimMachine(vector<short>& bitCollective) {

	for (auto i : bitCollective)
		Reset(SB.bMap, i / 32, i % 32);

	return;
}

//删除目录条目
void Rmdir() {

	int inodeNum = -1;
	string dirName;
	cin >> dirName;

	//检查目录是否存在
	int flag = false;
	for (auto& i : now->entryQueue)
		if (i.fileName == dirName) {

			inodeNum = i.inodeNum;
			flag = true;
			break;
		}
	if (!flag) {

		cout << "目录不存在" << endl;
		return;
	}

	int partInodeNum = now->inodeNum;

	RemoveDir(inodeNum);

	//一次当前目录的重新定位
	for (auto& i : dirQueue)
		if (i.inodeNum == partInodeNum) {

			now = &i;
			break;
		}

	//删除当前目录内该目录条目
	for (auto i = now->entryQueue.begin(); i < now->entryQueue.end(); ++i)
		if (i->fileName == dirName) {

			now->totalEntryCount--;
			now->entryQueue.erase(i);
			break;
		}

	return;
}

//删除目录
void RemoveDir(int inodeNum) {

	dirInode* tmpDir = nullptr;

	//检查是否为删除根目录
	if (inodeNum == -1) {

		cout << "非法操作:删除根目录" << endl;
		return;
	}

	GetDir(inodeNum);

	for (auto& dir : dirQueue)
		if (dir.inodeNum == inodeNum) {

			tmpDir = &dir;
			break;
		}

	//删除目录内内容
	for (auto& ent : tmpDir->entryQueue) {

		//不能删除父目录
		//不能删除本目录,否则会死循环
		if (ent.fileName == ".." || ent.fileName == ".")
			continue;

		//判断条目所指是否为常规文件
		for (auto& iter : fileQueue)
			if (iter.inodeNum == ent.inodeNum) {

				RemoveFile(ent.inodeNum);
				break;
			}

		//判断条目所指是否为目录文件
		for (auto& iter : dirQueue)
			if (iter.inodeNum == ent.inodeNum) {

				RemoveDir(ent.inodeNum);
				break;
			}
	}

	//删除该目录
	Reclaim(inodeNum, tmpDir->length, tmpDir->psyAddr);

	return;
}

void Help() {

	cout << "==================================================================" << endl
		<< "                    Simple Linux File System                      " << endl
		<< "   指令                                        说明                " << endl
		<< "   mk                              mk FileName FileLength 创建文件 " << endl
		<< "                                           文件长度以KB为单位       " << endl
		<< "   mkdir                               mkdir DirName 创建目录      " << endl
		<< "   cat                                   cat FileName 打开文件     " << endl
		<< "   link                         link NewDirName OldDirName 链接文件" << endl
		<< "   rm                                      rm FileName 删除文件    " << endl
		<< "   rmdir                                 rmdir DirName 删除目录    " << endl
		<< "   ls                                        ls 显示目录           " << endl
		<< "   cd                                     cd DirName 目录跳转      " << endl
		<< "   help                                    help 显示帮助信息        " << endl
		<< "   sys                                     sys 查看系统信息         " << endl
		<< "   esc                                       esc   退出            " << endl
		<< "===================================================================" << endl;
	cout << endl;
	return;
}

void Run() {

	bool run = true;
	string command;

	while (run) {

		for (auto i : path) {
			if (i == "\\")
				cout << "." << i;
			else
				cout << i << "\\";
		}
		cout << ':';

		cin >> command;
		if (command == "mk") {
			Mk();
		}
		else if (command == "mkdir") {
			Mkdir();
		}
		else if (command == "cat") {
			Cat();
		}
		else if (command == "rm") {
			Rm();
		}
		else if (command == "rmdir") {
			Rmdir();
		}
		else if (command == "ls") {
			Ls();
		}
		else if (command == "sys") {
			SysShow();
		}
		else if (command == "link") {
			Link();
		}
		else if (command == "cd") {
			Cd();
		}
		else if (command == "help") {
			Help();
		}
		else if (command == "esc") {
			run = false;
		}
		SaveData();
	}
}

int main() {

	if (!ReadSystem())
		InitSystem();
	Help();
	Run();
	return 0;
}

 才疏学浅,由于数据结构设计的原因,程序存在一些bug,体现在嵌套创建同名目录和递归删除连续目录和文件方面。不影响最基础的使用。

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐