📄 fat.txt
字号:
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
using namespace std;
#define FCB_NUM 100//设备目录区中可存放的文件描述信息的个数
#define BLOCK_NUM 1000//文件区盘块数
#define BLOCK_SIZE 512//文件区盘块大小
#define MAX_COMMAND_NUM 20//用户输入的命令的最大参数个数
#define MAX_COMMAND_LENGTH 20//用户输入的命令的最大长度
struct VolumeInfo//盘卷总信息结构体
{
long fcbAreaAddress;//设备目录区首地址
long fatAreaAddress;//FAT表区首地址
long dataAreaAddress;//文件区首地址
long totalSpaceNum;//总空间大小
long leftSpaceNum;//剩余空间大小
};
struct FCB//文件描述信息结构体
{
char name[MAX_COMMAND_LENGTH];//文件名
long headBlock;//首块号
long size;//文件大小
int type;// 文件类型
int premeunid; //上一级目录的id号 0为目录 其他为文件
};
struct FAT//FAT表元素结构体
{
long nextBlock;//块号。
//当该nextBlock值为-2时,表示当前块空闲
//值为-1时,表示当前块为文件的最后一块
};
int filedes;//模拟文件系统的文件的文件描述符
VolumeInfo volumeInfo;//盘卷总信息缓存
char command[MAX_COMMAND_NUM][ MAX_COMMAND_LENGTH];//存放用户输入的命令的字符串数组
int commandNum;//用户输入的命令的参数个数
//显示命令提示符,并接收用户输入的命令
void getCommand()
{
//处理用户输入的命令,放入command二维数组中
char commandChar;
int commandLength;
commandNum=0;
commandLength=0;
while(true)
{
cout<<"input command:";//输出命令提示符
commandChar=getchar();
while(commandChar!='\n')
{
if(commandChar==' ')
{
if(commandLength!=0)
{
command[commandNum][commandLength]='\0';
commandNum++;
commandLength=0;
}
commandChar=getchar();
continue;
}
else
{
command[commandNum][commandLength]= commandChar;
commandLength++;
}
commandChar=getchar();
}
command[commandNum][commandLength]= '\0';
if(commandLength>0)
commandNum++;
if(commandNum!=0)
break;
}
}
//显示帮助
void showHelp()
{
cout<<"exit 退出"<<endl;
cout<<"format 格式化文件系统"<<endl;
cout<<"showVolumeInfo 显示盘卷总信息"<<endl;
cout<<"ls 显示文件列表"<<endl;
cout<<"createFile 建立文件"<<endl;
cout<<"deleteFile 删除文件"<<endl;
cout<<"writeFile 写文件"<<endl;
cout<<"readFile 读文件"<<endl;
cout<<"mkdir 创建目录"<<endl;
cout<<"rm 删除目录"<<endl;
cout<<"clear 清屏"<<endl;
cout<<"outFile 文件导出"<<endl;
cout<<"inFile 文件导入"<<endl;
cout<<"cd.. 目录的切换"<<endl;
cout<<"cd meunName 进入某个目录"<<endl;
cout<<"remeunName 修改某个目录的文件名"<<endl;
cout<<"refileName 修改某个文件的文件名"<<endl;
cout<<"lsFile 显示文件内容"<<endl;
//*****************
}
//显示版权信息函数
void version()
{
cout<<endl<<endl;
cout<<" ┏━━━━━━━━━━━━━━━━━━━━━━━┓"<<endl;
cout<<" ┃ OS课程设计--模拟多级目录FAT文件系统 ┃"<<endl;
cout<<" ┠───────────────────────┨"<<endl;
cout<<" ┃ (c)All Right Reserved by ┃"<<endl;
cout<<" ┃ 李华、梁镇、尤泉湖 ┃"<<endl;
cout<<" ┃ version 2007 build 12 ┃"<<endl;
cout<<" ┗━━━━━━━━━━━━━━━━━━━━━━━┛"<<endl;
cout<<endl<<endl;
}
//格式化虚拟文件系统
void format()
{
int i=0;
//初始化盘卷总信息
volumeInfo.fcbAreaAddress=sizeof(VolumeInfo);
volumeInfo.fatAreaAddress=volumeInfo.fcbAreaAddress+sizeof(FCB)*FCB_NUM;
volumeInfo.dataAreaAddress=volumeInfo.fatAreaAddress+sizeof(FAT)*BLOCK_NUM;
volumeInfo.totalSpaceNum=BLOCK_SIZE*BLOCK_NUM;
volumeInfo.leftSpaceNum=volumeInfo.totalSpaceNum;
lseek(filedes,0,SEEK_SET);//移动文件读写指针到虚拟文件系统的开始处
write(filedes,&volumeInfo,sizeof(VolumeInfo));//写入盘卷总信息
//初始化设备目录区
FCB fcb;
memset(fcb.name,'\0',sizeof(fcb.name));
for(i=0;i<FCB_NUM;i++)
write(filedes,&fcb,sizeof(FCB));//写入经过初始化的文件描述信息
//初始化FAT表区
FAT fat;
fat.nextBlock=-2;
for(i=0;i<BLOCK_NUM;i++)
write(filedes,&fat,sizeof(FAT));//写入经过初始化的FAT信息
//初始化文件区
char block[BLOCK_SIZE];
memset(block,'\0',sizeof(block));
for(i=0;i<BLOCK_NUM;i++)
write(filedes,block,sizeof(block));//写入经过初始化的FAT信息
cout<<"格式化完成!"<<endl;//输出提示,格式化完成。
}
//显示盘卷总信息
void showVolumeInfo()
{
cout<<"FCB Area Address:"<<volumeInfo.fcbAreaAddress<<endl;
cout<<"FAT Area Address:"<<volumeInfo.fatAreaAddress<<endl;
cout<<"Data Area Address:"<<volumeInfo.dataAreaAddress<<endl;
cout<<"Total Space Num:"<<volumeInfo.totalSpaceNum<<endl;
cout<<"Left Space Num:"<<volumeInfo.leftSpaceNum<<endl;
}
//显示目录内容
void ls()
{
FCB fcb;
int fileNum=0;//文件数
lseek(filedes,volumeInfo.fcbAreaAddress,SEEK_SET);//将读写指针移动到设备目录区处
//读取整个设备目录区
for(int i=0;i<FCB_NUM;i++)
{
read(filedes,&fcb,sizeof(FCB));//读取文件描述信息
//判断读取出的文件描述信息是否有内容
if(strcmp(fcb.name,"")!=0)
{
cout<<fcb.name<<'\t';//输出文件名
fileNum++;//文件数加1
}
}
cout<<endl<<fileNum<<" Files"<<endl;//显示共找到多少个文件
}
//建立文件
void createFile (char* fileName)
{
//查找空闲FCB
FCB fcb;
int fcbPos;
lseek(filedes,volumeInfo.fcbAreaAddress,SEEK_SET);//将读写指针移动到设备目录区处
for(fcbPos=0;fcbPos<FCB_NUM;fcbPos++)
{
read(filedes,&fcb,sizeof(FCB)); //读取文件描述信息
if(strcmp(fcb.name,"")==0)
break;
}
//查找空闲FAT
FAT fat;
int fatPos;
lseek(filedes,volumeInfo.fatAreaAddress,SEEK_SET); //将读写指针移动到FAT表区处
for(fatPos=0;fatPos<BLOCK_NUM;fatPos++)
{
read(filedes,&fat,sizeof(FAT));//读取FAT信息
if(fat.nextBlock==-2)
break;
}
strcpy(fcb.name,fileName);
fcb.headBlock=fatPos;
fat.nextBlock=-1;
lseek(filedes,volumeInfo.fcbAreaAddress+fcbPos*sizeof(FCB),SEEK_SET);
write(filedes,&fcb,sizeof(FCB));
lseek(filedes,volumeInfo.fatAreaAddress+fatPos*sizeof(FAT),SEEK_SET);
write(filedes,&fat,sizeof(FAT));
}
//打开文件,取得文件描述信息。
//取得的文件描述信息通过pfcb指针传回。
//返回值为找到的文件描述信息的行号
long openFile(char* filename,FCB* pfcb)
{
long fcbPos;
lseek(filedes,volumeInfo.fcbAreaAddress,SEEK_SET);//将读写指针移动到设备目录区处
for(fcbPos=0;fcbPos<FCB_NUM;fcbPos++)
{
read(filedes,pfcb,sizeof(FCB));//读取文件描述信息
if(strcmp(pfcb->name,fileName)==0)
return fcbPos;//找到指定文件,返回文件的描述信息的行号
}
return -1;//未找到指定文件,则返回-1
}
//删除文件
void deleteFile (char* fileName)
{
FCB fcb;
long fcbPos =opernFile(filename,&fcb);//取得文件的描述信息fcb。及该fcb的行号fcbPos
if(fcbPos ==-1)
{
cout<<"file not found!"<<endl;
return;
}
long fatPos=fcb.headBlock;
memset(fcb.name,'\0',sizeof(fcb.name));
fcb.headBlock=0;
lseek(filedes,volumeInfo.fcbAreaAddress+fcbPos*sizeof(FCB),SEEK_SET);
write(filedes,&fcb,sizeof(FCB));
FAT fat;
long temp;
while(fatPos!=-1)
{
lseek(filedes,volumeInfo.fatAreaAddress+fatPos*sizeof(FAT),SEEK_SET);
read(filedes,&fat,sizeof(FCB));
temp=fat.nextBlock;
fat.nextBlock=-2;
lseek(filedes,volumeInfo.fatAreaAddress+fatPos*sizeof(FAT),SEEK_SET);
write(filedes,&fat,sizeof(FAT));
fatPos=temp;
}
}
//写文件。fileName是要执行操作的文件名,buf是要写入的数据
//writeNum是要写入的数据量,writePos是写入位置
//返回值是实际写入数据量
long writeFile (char* fileName,char* buf,long writeNum,long writePos)
{
FCB fcb; //文件描述信息
long block; //当前块号
long blockPos; //块内偏移
long finishNum; //记录已经写入的数据量
FAT fat;
//取得文件的描述信息fcb。及该fcb的行号fcbPos
//************
long fcbPos =openFile(fileName,&fcb);
//当写入位置超过文件大小时,将写入位置改为文件最末尾
if(writePos>fcb.size)
{
writePos=fcb.size;
}
//当前块号block移动到文件的首块
//************
block=fcb.headBlock;
//计算写入位置的块内偏移量blockPos
//************
blockPos=writePos%BLOCK_SIZE;
//初始化已经写入的数据量finishNum
//************
finishNUM=0;
//将当前块号block,移动到writePos所在的块
long moveTime;// block要移动的次数
//计算block要移动的次数moveTime
//例如:若writePos=510,则要将block要移动到该文件的第1个盘块,需移动0次, moveTime=0
//若writePos=600,则要将block移动到该文件的第2个盘块,需移动1次, moveTime=1
//************
moveTime=writePos/BLOCK_SIZE;
//移动block
while(moveTime >0)
{
//读取当前块的fat值,获取下一块的块号
//************
lseek(filedes,volumeInfo.fatAreaAddress+block*sizeof(fat),SEEK_SET);
read(filedes,&fat,sizeof(FAT));
//将block移动到下一块号
//************
block=fat.nextBlock;
moveTime --;
}
//当已经写入数据量小于要写入数据量时,循环写入
while(finishNum<writeNum)
{
//当块内偏移等于块长时说明要移动到下一个块进行写操作
if(blockPos==BLOCK_SIZE)
{
//查询下一块的块号
lseek(filedes,volumeInfo.fatAreaAddress+block*sizeof(FAT),SEEK_SET);
read(filedes,&fat,sizeof(FAT));
//若没有下一块,则分配一个新块.
if(fat.nextBlock==-1)
{
//在FAT表中查找空闲块
FAT newFat;
int newFatPos;//登记新块的位置
lseek(filedes,volumeInfo.fatAreaAddress,SEEK_SET);//将读写指针移动到设备目录区处
for(newFatPos=0;newFatPos<BLOCK_NUM;newFatPos++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -