【c++】模拟UNIX(Linux)文件系统
【代码】【c++】模拟UNIX(Linux)文件系统。
·
//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,体现在嵌套创建同名目录和递归删除连续目录和文件方面。不影响最基础的使用。
更多推荐
已为社区贡献1条内容
所有评论(0)