⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fat.txt

📁 FAT 文件系统半成品
💻 TXT
📖 第 1 页 / 共 2 页
字号:
#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 + -