内存中开辟一块虚拟磁盘空间
做为文件存储分区,在其上实现一个简单的基于多级目录的单用户单任务系统
中的文件系统。ios
在退出该文件系统的使用时,虚拟文件系统以一个文件的方式保存到磁盘中,以便下次能够把它恢复到内存的虚拟存储空间git
cd /home/zy/Desktop/
这样的绝对路径cd ../hah/1/2
这样的相对路径mkdir
,rmdir
,cd
,creat
,rm
均支持open_path
是open
的升级版,也是支持上述函数实现的主要函数。open
,read
,close
实现了一个cat
直接打印文件内容。
read
出全部内容创建目录树,/home
是用户的根目录github
/home
下有/zy
函数
/zy
下有 /Documents
,/Desktop
,/Viedeos
,Music
等测试
/home/zy/Documents
目录下创建一个文件Hello.txt
Hello World!Fisrt
,能正确显示长度和文件内容。creat
,open
,close
,read
,write
等基本用法creat /home/zy/hellozy.txt
在/home/zy
下创建了一个hellozy.txt
creat
在路径下的用法测试了mkdir
,cd
,rmdir
在路径下也能正常工做。其他几个相似的同理,OVERspa
#include <cstdio> #include <memory.h> #include <string> #include <iostream> #include <malloc.h> #include <time.h> using namespace std; /*常量定义*/ #define Path "/home" //根目录 #define BLOCKSIZE 1024 //磁盘块大小 #define BLOCKCOUNT 1000 //盘块大小 #define MAXOPENFILE 10 //能打开最多的文件数 #define DISKSIZE (BLOCKSIZE*BLOCKCOUNT)//磁盘大小 #define END -1 const int FCBCOUNT = BLOCKSIZE/sizeof(FCB);//一个块的最多FCB数量
FAT1
:4个FAT2
:4个根目录
1个其他数据
991个代码:命令行
/*------------------磁盘------------------------*/ struct DISK { int FAT1[BLOCKCOUNT];//磁盘块0-3表明FAT int FAT2[BLOCKCOUNT];//磁盘块4-7表明FAT2 DirFile RootDir; //根目录 磁盘块8 char Data[BLOCKCOUNT-9][BLOCKSIZE];//目录和其余文件 磁盘块9~1000 };
代码:指针
/*-----------------目录文件---------------------*/ struct DirFile{ FCB fcb[FCBCOUNT]; //文件控制块 void init(int father,int self) { //给根目录建立.. 和 . 序号0放".", 序号1放".." memset(fcb,0,sizeof(fcb)); fcb[1].free=fcb[0].free=1; fcb[1].attribute=fcb[0].attribute=1; fcb[1].first=father; fcb[0].first=self; memcpy(fcb[0].filename,".",sizeof(".")); memcpy(fcb[1].filename,"..",sizeof("..")); } };
struct FCB { char filename[12]; //文件名 char attribute;//0表示目录,1表示数据文件 int time;//建立时间 int data;//建立日期 int first;//起始盘号 int length;//长度 char free;//表示目录项是否为空 };
struct USEROPEN { FCB fcb; char dir[80];//相应打开文件所在的目录名 int count;//读写指针在文件的位置 char fcbstate;//是否修改了文件的FCB内容,修改了置为1,不然置为0 char topenfile;//表示该用户表项是否被占用,1就是被占用,0就是没有被占用 char fatherfilename[12];//上一层目录的名字 int pos; };
ls
函数#include "OS.h" using namespace std; /*-------------函数声明------------------------*/ void help(); int cd(char *dirname); int startsys(); int format(); int mkdir(char *dirname); int rmdir(char *dirname); int close(int fd); int open(char *filename); int creat(char *filename); int rm(char *filename); int filewrite(int fd); int dowrite(int fd,char *text,int len, char wstyle); int fileread(int fd,int len); int doread(int fd,int len,char *text); void exitsys(); /*--------------全局变量-------------------------*/ char* myvhard;//虚拟磁盘起始地址 string currentdir="/home";//当前目录 string cmd; //读取指令 USEROPEN openfilelist[MAXOPENFILE];//文件打开表 USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 DISK* disk;//将内容结构化 char command[50];//文件名标示符 /*--------------------- 显示目录函数 ---------------*/ void ls() { int BlockDirNum = (ptrcuridr->fcb).first; DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8]; for (int i = 0; i < FCBCOUNT; i++) { if (dir->fcb[i].free == 1) { if (dir->fcb[i].attribute == 0) printf("%10s---length:%5d----File\n",dir->fcb[i].filename,dir->fcb[i].length); else printf("%10s---length:%5d----Directory\n",dir->fcb[i].filename,dir->fcb[i].length); } } } int main() { printf("Welcome the OS FileSystem\n"); printf("input 'help' get more information\n\n\n"); // freopen("E:\\OSFileSystem\\a.in","r",stdin); startsys(); //Init the System int len; while(1) { cout<<currentdir+">"; cin>>cmd; if(cmd=="help"){ //帮助 help(); } else if(cmd=="mkdir"){ cin>>command; mkdir(command); } else if(cmd=="cd"){ cin>>command; cd(command); } else if(cmd=="exit") { break; } else if(cmd=="rmdir"){ cin>>command; rmdir(command); } else if(cmd=="ls"){ ls(); } else if(cmd=="open"){ cin>>command; open(command); } else if(cmd=="close"){ cin>>command; close(atoi(command)); } else if(cmd=="creat"){ cin>>command; creat(command); } else if(cmd=="rm"){ cin>>command; rm(command); } // else if(cmd=="write"){ cin>>command; filewrite(atoi(command)); } else if(cmd=="read") { cin >> command >> len; fileread(atoi(command),len); } else if(cmd=="exitsys"){ exitsys(); }else { printf("The cmd is not exits\n"); } } }
int format()
.
和..
两个子目录int startsys()
把根目录加载进文件打开表。code
#include "OS.h"
/--------------全局变量-------------------------/
extern char* myvhard;//虚拟磁盘起始地址
extern string currentdir;//当前目录
extern string cmd; //读取指令
extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表
extern USEROPEN ptrcuridr;//当前目录在文件打开表的位置
extern DISK disk;//将内容结构化
extern char command[50];//文件名标示符
/--------------------------------磁盘格式化函数-------------------/
int format() {
memset(myvhard,0,DISKSIZE);
//建立根目录,在磁盘块8orm
//前九个被FAT1+FAT2+root占用 for(int i=0;i<9;i++){ disk->FAT1[i]=disk->FAT2[i]=-2;//-2表明被占用 } DirFile *dir=(DirFile *)disk->Data[8-8];//注意Data和FAT的区别 //初始化根目录. dir->init(8,8); return 1;
}
/--------------------------------进入文件系统函数--------------------/
int startsys() {
myvhard=(char )malloc(DISKSIZE); //申请10241000磁盘空间
disk=(DISK )myvhard;
FILE fp=fopen("myfsys","r");
if(fp!=NULL)
{
printf("|-------------------------------------------|\n");
printf("|-----------myfsys is loading---------------|\n");
printf("|-------------------------------------------|\n\n");
fread(myvhard,sizeof(char),DISKSIZE,fp);
fclose(fp);
}
else{
printf("|-------------------------------------------|\n");
printf("|-----------myfsys is not exit--------------|\n");
printf("|--File system is being created now --------|\n");
printf("|-------------------------------------------|\n\n");
format();
}
//初始化用户打开表
memset(openfilelist,0,sizeof(openfilelist));
//将根目录打开,首先修改fcb里的内容
openfilelist->fcb.first=8;
//文件打开表项的内容
openfilelist[0].topenfile=1;
strcpy(openfilelist->dir,"");
strcpy(openfilelist->fcb.filename,"home");
strcpy(openfilelist->fatherfilename,"");
ptrcuridr=&openfilelist[0];
openfilelist[0].pos=0;
//当前目录设置为根目录
currentdir=Path;
return 1;
}
处理好.
和..
两个子目录
维护好openfilelist
里的每一个值
#include "OS.h"
/--------------全局变量-------------------------/
extern char* myvhard;//虚拟磁盘起始地址
extern string currentdir;//当前目录
extern string cmd; //读取指令
extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表
extern USEROPEN ptrcuridr;//当前目录在文件打开表的位置
extern DISK disk;//将内容结构化
extern char command[50];//文件名标示符
/-----------------------------打开文件函数--------------------/
int open(char *filename){
//检查要被打开文件是否存在 int BlockDirNum = (ptrcuridr->fcb).first; DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8]; int Fileaddr = -1; for (int i = 0; i < FCBCOUNT; i++) { if (dir->fcb[i].free == 1 && strcmp(dir->fcb[i].filename, filename) == 0)//表项被使用,且是目录,且文件名相等 { Fileaddr = i;//文件存在 break; } } //文件不存在 输出-1 if(Fileaddr==-1){ printf("file does not exist\n"); return -1; } //检查打开文件表是否还有空表项,没有报错,有则记录 int OpenFileaddr=-1; for(int i=0;i<MAXOPENFILE;i++) { if (openfilelist[i].topenfile == 0) { OpenFileaddr=i; } } //没有空表了 if(OpenFileaddr==-1) { printf("File open table is full \n"); return -1; } //若是又要打开一个根目录,那么直接返回0 if(dir->fcb[Fileaddr].first==8) { OpenFileaddr=0; if(ptrcuridr->fcb.first==8) return 0; } //为该文件填写文件打开表项 //检查是否已经打开 //须要一个temp来表示实际的dir值 char temp[300]; if(strcmp(filename,"..")==0) { strcpy(temp,ptrcuridr->dir); int len1=strlen(ptrcuridr->dir); int len2=strlen(ptrcuridr->fatherfilename); temp[len1-len2-1]=0; } else { char buffer[80]; memset(buffer,0,sizeof(buffer)); strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename); strcpy(temp,buffer); } for(int i=1;i<MAXOPENFILE;i++) { //"."必定是被打开了 if ((openfilelist[i].topenfile == 1 && strcmp(openfilelist[i].fcb.filename, filename) == 0 && strcmp(openfilelist[i].dir,temp) ==0 )||(strcmp(filename,".")==0)) { printf(" The file has been opened !\n"); return -1;//无效返回-1 } } if(strcmp(filename,"..")==0) { openfilelist[OpenFileaddr].fcb=dir->fcb[Fileaddr]; //名字是错的,会是"..";正确的名字在工做块的父亲名字 strcpy(openfilelist[OpenFileaddr].fcb.filename,ptrcuridr->fatherfilename); //曾经的路径减去名字减去'/' 就是新的 strcpy(openfilelist[OpenFileaddr].dir,ptrcuridr->dir); int len1=strlen(openfilelist[OpenFileaddr].dir); int len2=strlen(ptrcuridr->fatherfilename); openfilelist[OpenFileaddr].dir[len1-len2-1]=0; //找新的fathername,经过分析dir来获得 char test[20]; strcpy(test,openfilelist[OpenFileaddr].dir); char *q; int len=strlen(test); for(int i=0;i<len;i++) { if(test[i]=='/'&&i!=len-1) q=test+i+1; } strcpy(openfilelist[OpenFileaddr].fatherfilename,q); } else { openfilelist[OpenFileaddr].fcb=dir->fcb[Fileaddr]; char buffer[80]; memset(buffer,0,sizeof(buffer)); strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename); strcpy(openfilelist[OpenFileaddr].dir,buffer); strcpy(openfilelist[OpenFileaddr].fatherfilename,ptrcuridr->fcb.filename); } openfilelist[OpenFileaddr].pos=OpenFileaddr; openfilelist[OpenFileaddr].count=0; openfilelist[OpenFileaddr].fcbstate=0; openfilelist[OpenFileaddr].topenfile=1; //返回文件描述符fd,此时的fd跟下标相同,通常不一样. if(openfilelist[OpenFileaddr].fcb.attribute==0)//若是是文件,输出文件打开符号 printf("File Open Success,The fd is %d\n",OpenFileaddr); return OpenFileaddr;
}
cd
,mkdir
,creaet
,rm
,rmdir
使用的方式是拆分路径的元素,而后分析元素
不断的调用open
和close
来实现。
#include "OS.h" int open(char *filename); int close(int fd); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[50];//文件名标示符 /*----------------------更改当前目录函数--------------------- 读入一条文件路径,返回一个打开的fd 支持绝对路径和相对路径. 输出,若是路径正确,返回文件打开后的fd. ------------------------------------------------------*/ int open_path(char *dirname) { //若是dirname是绝对路径 int fd=0, ok = 1, fdtemp = -1;//ok表明是否找到dirname所指的文件,fdtemp存临时的,用来关闭 USEROPEN *temp = ptrcuridr;//暂时保管一下ptrcuridr原始值,可能要回溯 if (dirname[0] == '/') { ptrcuridr = openfilelist;//咱们的openfilelist[0]永远是根目录 //使工做目录暂时指向根目录 char *p = strtok(dirname + 1, "/");//用“/”分割 dirname[1]开始的字符串 if (p != NULL) p = strtok(NULL, "/");//跳过/home while (p) { fd = open(p); if (fd == -1) { ok = 0; if (fdtemp != -1) //离开前记得关文件 close(fdtemp);//把上个打开的文件关掉 break; } ptrcuridr = openfilelist + fd; if (fdtemp != -1) close(fdtemp);//把上个打开的文件关掉 fdtemp = fd; p = strtok(NULL, "/"); } } //若是是相对路径 else { int len=strlen(dirname); dirname[len]='/'; dirname[len+1]=0; char *p = strtok(dirname, "/");//用“/”分割 dirname[1]开始的字符串 while (p) { fd = open(p); if (fd == -1) { ok = 0; if (fdtemp != -1) //离开前记得关文件 close(fdtemp);//把上个打开的文件关掉 break; } ptrcuridr = openfilelist + fd; if (fdtemp != -1) close(fdtemp);//把上个打开的文件关掉 fdtemp = fd; p = strtok(NULL, "/"); } } ptrcuridr = temp; //输出数据 if (ok == 1) return fd; else return -1; }
#include "OS.h" int open_path(char* dirname); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[16];//文件名标示符 /*---------------关闭文件函数-----------------*/ int close(int fd){ //检查fd的合法性 if(fd>=MAXOPENFILE||fd<=0){ printf(" Is not a legitimate fd \n"); return -1; }else if(openfilelist[fd].topenfile==0){ printf("filewrite ERROR:The File Don't Open\n"); return -1; } //检查用户打开文件表表项的`fcbstate`字段,若是是1,则须要将该文件的FCB的内容保存的虚拟磁盘上该文件的目录项 //方法是:打开该文件的父目录文件,已覆盖写方式调用do_wirte()将欲关闭的FCB写入父目录文件的相应盘块. if(openfilelist[fd].fcbstate==1){ char buffer[30]=".."; int fatherfd=open_path(buffer); if(fatherfd!=-1) { //找到相应的盘号 int pan1 = openfilelist[fatherfd].fcb.first; int area1 = -1; //盘号上相应的位置 DirFile *dirson = (DirFile *) (disk->Data[pan1 - 8]); for (int i = 0; i < FCBCOUNT; i++) { if (dirson->fcb[i].free == 1 && strcmp(dirson->fcb[i].filename, openfilelist[fd].fcb.filename) == 0) { //找到了该文件,覆盖fcb dirson->fcb[i] = openfilelist[fd].fcb; break; } } //关文件 if(fatherfd!=0) close(fatherfd); } } //回收该文件占据的用户打开表表项(clear),topenfile字段置0 memset(openfilelist+fd,0,sizeof(openfilelist[0])); openfilelist[fd].topenfile=0; //返回 return 0; }
open_path
来返打开一个父级目录,并返回fd
ptrcuridr
的原始值保存下来,而后将其赋值给那个父级目录。ptrcuridr
#include "OS.h" int close(int fd); int open_path(char *dirname); int FileSubstr(char *str); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[50];//文件名标示符 int mkdir(char *dirname) { char newdir[20]; char dirpath[60]; USEROPEN *tempp = ptrcuridr;//暂时保管一下ptrcuridr原始值,可能要回溯 int k=FileSubstr(dirname),fd=-1; if(k!=-1) { dirname[k] = 0; memset(newdir, 0, sizeof(newdir)); memset(dirpath, 0, sizeof(dirpath)); strcpy(newdir, dirname + k + 1); strcpy(dirpath, dirname); fd = open_path(dirpath); if(fd!=-1) { ptrcuridr = openfilelist + fd; dirname = newdir; } else { printf("error\n"); return -1; } } //-------------如下为一天前的代码-----------------------// //读取当前目录的地址 int BlockDirNum=(ptrcuridr->fcb).first; DirFile *dir=(DirFile *)disk->Data[BlockDirNum-8]; //遍历文件目录,检查是否有文件名相同的文件或目录,并找一个没有被使用的目录空闲表项 int temp=-1, DirFreeItems =-1; for(int i=0;i<FCBCOUNT;i++) { if (dir->fcb[i].free == 1 && strcmp(dir->fcb[i].filename, dirname) == 0)//表项被使用,且是目录,且文件名相等 { temp = i;//重名的表项 break; } else if (dir->fcb[i].free == 0) { DirFreeItems = i;//目录空闲表项 } } //若是文件名已存在,报错并退出 if(temp!=-1) { printf("mkdir: cannot create directory '%s': Directory exists\n",dirname); if(fd!=-1) close(fd); ptrcuridr=tempp; return 0; } //若是没有空闲位置,报错退出 if(DirFreeItems==-1) { printf("mkdir: cannot create directory '%s': Directory is full \n",dirname); if(fd!=-1) close(fd); ptrcuridr=tempp; return 0; } //检查FAT中是否有空闲的盘块 int FATFreeItems=-1; for(int i = 0;i < BLOCKCOUNT;i++) { if(disk->FAT1[i] == 0) {//没被使用的块标记为0 FATFreeItems=i;//找到了一个空闲块 break; } } //若是FAT没有空闲块,报错退出 if(FATFreeItems==-1) { printf("mkdir: cannot create directory '%s': Disk is full \n",dirname); if(fd!=-1) close(fd); ptrcuridr=tempp; return 0; } /*----------------开始新建目录-------------------*/ //修改长度,fcbstate置为1 ptrcuridr->fcbstate=1; ptrcuridr->fcb.length++;//不包括.和..的 //分配FAT的空闲块,2表示被目录使用 disk->FAT1[FATFreeItems]=disk->FAT2[FATFreeItems]=2; //将改块分配到 当前目录的空闲项目下 strcpy(dir->fcb[DirFreeItems].filename,dirname); dir->fcb[DirFreeItems].free=1;//被使用 dir->fcb[DirFreeItems].attribute=1;//是目录 dir->fcb[DirFreeItems].first=FATFreeItems;//分配FAT空闲块 dir->fcb[DirFreeItems].length=0; dir->fcb[DirFreeItems].data=0;//时间以后弄 dir->fcb[DirFreeItems].time=0;//时间以后弄 //进入下一次目录,初始化新得到的块(重置给予"."和"..") dir=(DirFile*)(disk->Data[FATFreeItems-8]); dir->init(BlockDirNum,FATFreeItems); /*----------------恢复现场------------------------*/ if(fd!=-1) close(fd); ptrcuridr=tempp; return 1; }
mkdir
相似#include "OS.h" int close(int fd); int open_path(char *dirname); int FileSubstr(char *str); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[50];//文件名标示符 /*-------------------------------删除子目录函数---------------------*/ int rmdir(char *dirname) { char newdir[20]; char dirpath[60]; USEROPEN *tempp = ptrcuridr;//暂时保管一下ptrcuridr原始值,可能要回溯 int k=FileSubstr(dirname),fd=-1; if(k!=-1) { dirname[k] = 0; memset(newdir, 0, sizeof(newdir)); memset(dirpath, 0, sizeof(dirpath)); strcpy(newdir, dirname + k + 1); strcpy(dirpath, dirname); fd = open_path(dirpath); if(fd!=-1) { ptrcuridr = openfilelist + fd; dirname = newdir; } else { printf("error\n"); return -1; } } /*---------使用open_path更新----------------------*/ //检查文件是否存在 int BlockDirNum = (ptrcuridr->fcb).first; DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8]; int temp = -1; for (int i = 0; i < FCBCOUNT; i++) { if (dir->fcb[i].free == 1 && dir->fcb[i].attribute == 1 && strcmp(dir->fcb[i].filename, dirname) == 0)//表项被使用,且是目录,且文件名相等 { temp = i;//文件存在 break; } } //要删除的目录不存在 if(temp == -1) { printf("rmdir: failed to remove '%s': No such file or directory\n",dirname); if(fd!=-1) close(fd); ptrcuridr=tempp; return 0; } //判断子目录是否为空,不包括0和1,也能够用length,懒得用 DirFile *dirson=(DirFile*)(disk->Data[dir->fcb[temp].first-8]); int flag=-1; for(int i=2; i < FCBCOUNT; i++ ) { if (dir->fcb[i].free == 1){ flag=1; break; } } //要删除的目录不为空 if(flag==-1) { printf("rmdir: failed to remove '%s': Directory not empty\n",dirname); if(fd!=-1) close(fd); ptrcuridr=tempp; return 0; } //检查目录是否已打开,打开就关闭 //回收该目录文件所占据的磁盘块,修改FAT disk->FAT1[dir->fcb[temp].first]=disk->FAT1[dir->fcb[temp].first]=0; //当前目录文件中清空该目录文件的目录项,memset清理干净 memset(&(dir->fcb[temp]),0,sizeof(dir->fcb[temp])); //修改长度,表项的fcbstate置为1 ptrcuridr->fcbstate=1; ptrcuridr->fcb.length--;//不包括.和..的 /*-----------------恢复现场-------------*/ if(fd!=-1) close(fd); ptrcuridr=tempp; return 1; }
open_path
十分简单的实现一个跳转到任意路径的函数#include "OS.h" int open(char *filename); int close(int fd); int open_path(char *dirname); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[50];//文件名标示符 /*----------------------更改当前目录函数---------------------*/ int cd(char *dirname) { USEROPEN *temp = ptrcuridr;//暂时保管一下ptrcuridr原始值,可能要回溯 int fd=open_path(dirname); if (fd != -1) { //关掉旧的描述符 int old=temp->pos; //获取旧的描述符 if (old != 0) //根目录描述符不关 close(old); //工做目录指向它 ptrcuridr = openfilelist + fd; //当前目录赋值 currentdir= ptrcuridr->dir ; currentdir+= '/'; currentdir+= ptrcuridr->fcb.filename; return 0; } else { ptrcuridr = temp; printf("No such file or directory\n"); return 0; } }
有了open_path
so easy
#include "OS.h"
int close(int fd);
int open_path(char dirname);
int FileSubstr(char str);
/--------------全局变量-------------------------/
extern char* myvhard;//虚拟磁盘起始地址
extern string currentdir;//当前目录
extern string cmd; //读取指令
extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表
extern USEROPEN ptrcuridr;//当前目录在文件打开表的位置
extern DISK disk;//将内容结构化
extern char command[50];//文件名标示符
int creat(char filename){
//为新文件分配一个空闲打开文件表项,若是没有空闲表项就返回 -1
//检查打开文件表是否还有空表项,没有报错,有则记录
int OpenFileaddr=-1;
for(int i=0;i<MAXOPENFILE;i++) {
if (openfilelist[i].topenfile == 0) {
OpenFileaddr=i;
}
}
//没有空表了
if(OpenFileaddr==-1) {
printf("File open table is full \n");
return -1;
}
/-----------打开路径所指的父目录---------/
char newdir[20];
char dirpath[60];
USEROPEN tempp = ptrcuridr;//暂时保管一下ptrcuridr原始值,可能要回溯
int k=FileSubstr(filename),fd=-1;
if(k!=-1) {
filename[k] = 0;
memset(newdir, 0, sizeof(newdir));
memset(dirpath, 0, sizeof(dirpath));
strcpy(newdir, filename + k + 1);
strcpy(dirpath, filename);
fd = open_path(dirpath);
if(fd!=-1) {
ptrcuridr = openfilelist + fd;
filename = newdir;
}
else {
printf("error\n");
return -1;
}
}
//检查重名
int BlockDirNum = (ptrcuridr->fcb).first;
DirFile dir = (DirFile ) disk->Data[BlockDirNum - 8];
int temp = -1,DirFreeItems =-1;
for (int i = 0; i < FCBCOUNT; i++) {
if (dir->fcb[i].free == 1 &&
strcmp(dir->fcb[i].filename, filename) == 0)//表项被使用,且是目录,且文件名相等
{
temp = i;//有重名,可能文件,可能文件夹
break;
}
else if (dir->fcb[i].free == 0) {
DirFreeItems = i;//目录空闲表项
}
}
//若是文件名已存在,报错并退出
if(temp!=-1)
{
if(fd!=-1)
close(fd);
ptrcuridr=tempp;
printf("creat: cannot create file '%s': File exists\n",filename);
return 0;
}
//若是没有空闲位置,报错退出
if(DirFreeItems==-1)
{
printf("creat: cannot create file '%s': Directory is full \n",filename);
if(fd!=-1)
close(fd);
ptrcuridr=tempp;
return 0;
}
//检查FAT中是否有空闲的盘块
int FATFreeItems=-1;
for(int i = 0;i < BLOCKCOUNT;i++)
{
if(disk->FAT1[i] == 0) {//没被使用的块标记为0
FATFreeItems=i;//找到了一个空闲块
break;
}
}
//若是FAT没有空闲块,报错退出
if(FATFreeItems==-1)
{
printf("mkdir: cannot create directory '%s': Disk is full \n",filename);
if(fd!=-1)
close(fd);
ptrcuridr=tempp;
return 0;
}
/----------------开始新建文件-------------------/
//修改长度,fcbstate置为1
ptrcuridr->fcbstate=1;
ptrcuridr->fcb.length++;//不包括.和..的
//准备好新文件的FCB的内容,文件属性为数据文件,长度0.
//分配FAT的空闲块,-3表示被文件使用,-1表示文件结尾
disk->FAT1[FATFreeItems]=disk->FAT2[FATFreeItems]=-1;
//将改块分配到 当前目录的空闲项目下
strcpy(dir->fcb[DirFreeItems].filename,filename);
dir->fcb[DirFreeItems].free=1;//被使用
dir->fcb[DirFreeItems].attribute=0;//是文件
dir->fcb[DirFreeItems].first=FATFreeItems;//分配FAT空闲块
dir->fcb[DirFreeItems].length=0;
dir->fcb[DirFreeItems].data=0;//时间以后弄
dir->fcb[DirFreeItems].time=0;//时间以后弄
//文件新建完毕
//填写文件打开表项
openfilelist[OpenFileaddr].fcb=dir->fcb[DirFreeItems];
char buffer[80];
memset(buffer,0,sizeof(buffer));
strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename);
strcpy(openfilelist[OpenFileaddr].dir,buffer);
strcpy(openfilelist[OpenFileaddr].fatherfilename,ptrcuridr->fcb.filename);
openfilelist[OpenFileaddr].pos=OpenFileaddr;
openfilelist[OpenFileaddr].count=0;
openfilelist[OpenFileaddr].fcbstate=0;
openfilelist[OpenFileaddr].topenfile=1;
//关闭文件走人
if(fd!=-1)
close(fd);
ptrcuridr=tempp;
//返回文件描述符fd,此时的fd跟下标相同,通常不一样.
printf("File Creat Success,The fd is %d\n",OpenFileaddr);
return OpenFileaddr;
}
-1
#include "OS.h" int close(int fd); int open_path(char *dirname); int FileSubstr(char *str); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[50];//文件名标示符 /*--------------------------删除文件函数---------------------*/ int rm(char *filename){ /*--------------------------打开上级目录---------------------*/ char newdir[20]; char dirpath[60]; USEROPEN *tempp = ptrcuridr;//暂时保管一下ptrcuridr原始值,可能要回溯 int k=FileSubstr(filename),fd=-1; if(k!=-1) { filename[k] = 0; memset(newdir, 0, sizeof(newdir)); memset(dirpath, 0, sizeof(dirpath)); strcpy(newdir, filename + k + 1); strcpy(dirpath, filename); fd = open_path(dirpath); if(fd!=-1) { ptrcuridr = openfilelist + fd; filename = newdir; } else { printf("error\n"); return -1; } } //调用read,判断目录下文件是否存在 int BlockDirNum = (ptrcuridr->fcb).first; DirFile *dir = (DirFile *) disk->Data[BlockDirNum - 8]; int temp = -1; for (int i = 0; i < FCBCOUNT; i++) { if (dir->fcb[i].free == 1 && dir->fcb[i].attribute == 0 && strcmp(dir->fcb[i].filename, filename) == 0)//表项被使用,且是文件,且文件名相等 { temp = i;//文件存在 break; } } //要删除的目录不存在 if(temp == -1) { printf("rm: failed to remove '%s': No such file or directory\n",filename); if(fd!=-1) close(fd); ptrcuridr=tempp; return 0; } //检查该文件是否打开,若打开则关闭 char buffer[80]; memset(buffer,0,sizeof(buffer)); strcat(strcat(strcat(buffer,ptrcuridr->dir),"/"),ptrcuridr->fcb.filename); for(int i=1;i<MAXOPENFILE;i++) { //"."必定是被打开了 if ((openfilelist[i].topenfile == 1 && strcmp(openfilelist[i].fcb.filename, filename) == 0 && strcmp(openfilelist[i].dir,buffer) ==0 )) { printf(" The file been opened,Now Close it !\n"); close(i); break; } } //回收磁盘,一个链表 int TEMP=0; for(int p=dir->fcb[temp].first;p!=-1;p=TEMP) { TEMP=disk->FAT1[p]; disk->FAT1[p]=disk->FAT2[p]=0; } //清空该目录项,free字段为0, memset(&(dir->fcb[temp]),0,sizeof(dir->fcb[temp])); //修改长度,表项的fcbstate置为1 ptrcuridr->fcbstate=1; ptrcuridr->fcb.length--;//不包括.和..的 /*-----------------恢复现场-------------*/ if(fd!=-1) close(fd); ptrcuridr=tempp; return 1; }
blockno
和 块内偏移blockoff;
#include "OS.h" int open_path(char* dirname); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[16];//文件名标示符 /*---------------实际写文件函数----------------*/ int dowrite(int fd,char *text,int len, char wstyle) { //申请1024字节的缓冲区buf char *buf = (char *) malloc(1024); if (buf == NULL) { printf("MALLOC ERROR b\n"); return -1; } int tmplen = 0; int textpos = 0; int textlen = strlen(text); //将文件指针转换为逻辑块块号blockno 和 块内偏移blockoff; /*--------------------分配-----------------*/ while(tmplen<len) { int blockno = (openfilelist[fd].count) / 1024; int blockoff = (openfilelist[fd].count) % 1024; //寻找磁盘块blockno int currentblock = 0; int cnt = 0; for (int p = openfilelist[fd].fcb.first; p != -1; p = disk->FAT1[p]) { cnt++; currentblock = p; if (cnt == blockno + 1) break; } int pre = currentblock; if (cnt != blockno + 1)//若是找不到这样的一块,那么还须要给它分配blockno+1-cnt块 { //从currentblock开始分配 for (int i = 1; i <= blockno + 1 - cnt; i++) { //检查FAT中是否有空闲的盘块 int FATFreeItems = -1; for (int i = 0; i < BLOCKCOUNT; i++) { if (disk->FAT1[i] == 0) {//没被使用的块标记为0 FATFreeItems = i;//找到了一个空闲块 break; } } //若是FAT没有空闲块,报错退出 if (FATFreeItems == -1) { printf("FAT IS FULL\n"); return -1; } disk->FAT1[pre] = FATFreeItems; pre = FATFreeItems; } } //若是是覆盖写,或者块内偏移off不等于0,则将blkno的虚拟磁盘块所有写入buff中,不然memset if (wstyle == 2 || blockoff != 0) { memcpy(buf, disk->Data[currentblock - 8], 1024); } //将text中的内容暂存到缓冲区buff的第off字节开始的位置,直到缓冲区满 for (int i = blockoff; i < 1024 && textpos < textlen && tmplen<len; i++) { buf[i] = text[textpos]; textpos++; tmplen++; //读入长度 } memcpy(disk->Data[currentblock - 8], buf, 1024); openfilelist[fd].count += tmplen; } free(buf); return tmplen; }
#include "OS.h" int open_path(char* dirname); int dowrite(int fd,char *text,int len, char wstyle); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[16];//文件名标示符 /*---------------写文件函数----------------*/ int filewrite(int fd) { int way = 0; //检查fd的有效性 if (fd >= MAXOPENFILE || fd <= 0) { printf("filewirt ERROR:Is not a legitimate fd \n"); return -1; }else if(openfilelist[fd].topenfile==0){ printf("filewrite ERROR:该文件没有被打开\n"); return -1; } while (1) { //提示等待用户输入写方式 printf(" ------Please enter the way to write---------\n "); //1 : 截断写 2: 覆盖写 3: 追加写 printf(" ------1:TRUNC 2:OVER 3:APPEND---------\n "); scanf("%d", &way); if (1 <= way && way <= 3) break; else printf("Input Error,Please Try Again\n"); } // 若是是截断写,释放文件除第一块外的磁盘空间内容 //内存用户打开表中文件长度为0,,读写指针置为0 if (way == 1) { //释放文件除第一块外的磁盘空间内容 int TEMP = 0; int ok = 1; for (int p = openfilelist[fd].fcb.first; p != -1; p = TEMP) { TEMP = disk->FAT1[p]; if (ok != 1) { disk->FAT1[p] = disk->FAT2[p] = 0; } else { ok = 0; } } //长度置为0 openfilelist[fd].fcb.length = 0; //读写指针置为0 openfilelist[fd].count = 0; } //若是是追加写,修改文件的当前读写指针到文件的末尾 else if (way == 3) { openfilelist[fd].count = openfilelist[fd].fcb.length; } //提示用户,输入内容经过CTRL+Z结束,用户可分屡次输入写入内容,每次用回车结束 printf(" Input CTRL+D end the input\n "); int temp=0; char buffer[3000]; while(gets(buffer)!=0){ int len=strlen(buffer); buffer[len]='\n'; buffer[len+1]='\0'; int ret=dowrite(fd,buffer,strlen(buffer),way); if(ret==-1) { return -1; } else temp+=ret; } //若是当前读写指针位置大于长度,则更新长度,并置fcbstate置1 if(openfilelist[fd].count>openfilelist[fd].fcb.length) { openfilelist[fd].fcb.length = openfilelist[fd].count; openfilelist[fd].fcbstate=1; } //返回实际写入的字节 return temp; }
每次读一片磁盘
#include "OS.h"
int open_path(char* dirname);
int dowrite(int fd,char text,int len, char wstyle);
/--------------全局变量-------------------------/
extern char myvhard;//虚拟磁盘起始地址
extern string currentdir;//当前目录
extern string cmd; //读取指令
extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表
extern USEROPEN ptrcuridr;//当前目录在文件打开表的位置
extern DISK disk;//将内容结构化
extern char command[16];//文件名标示符
/------------------实际读文件函数--------------------------/
//text的指向那个读出数据的用户地址
int doread(int fd,int len,char text){
//申请1024字节的缓冲区buf
char buf = (char *) malloc(1024);
if (buf == NULL) {
printf("MALLOC ERROR b\n");
return -1;
}
int tmplen = 0;
int textpos = 0;
//将最终指针转换为逻辑块块号blockno 和 块内偏移blockoff;
while(tmplen<len) {
int blockno = (openfilelist[fd].count) / 1024;
int blockoff = (openfilelist[fd].count) % 1024;
//寻找磁盘块blockno
int currentblock = 0;
int cnt = 0;
for (int p = openfilelist[fd].fcb.first; p != -1; p = disk->FAT1[p]) {
cnt++;
currentblock = p;
if (cnt == blockno + 1)
break;
}
memcpy(buf, disk->Data[currentblock - 8], 1024); // for (int i = blockoff; i < 1024 && tmplen<len && openfilelist[i].count<openfilelist[i].fcb.length; i++) { text[textpos] = buf[i]; textpos++; tmplen++; //读入长度 openfilelist[fd].count; } memcpy(disk->Data[currentblock - 8], buf, 1024); } free(buf); return tmplen;
}
#include "OS.h" int open_path(char* dirname); int dowrite(int fd,char *text,int len, char wstyle); int doread(int fd,int len,char *text); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[16];//文件名标示符 /*---------------读文件函数----------------*/ const int MAXSIZE=1024*50; int fileread(int fd,int len){ char text[MAXSIZE]; memset(text,0,sizeof(text)); //检查fd的有效性 if (fd >= MAXOPENFILE || fd <= 0) { printf("filewirt:Is not a legitimate fd \n"); return -1; }else if(openfilelist[fd].topenfile==0){ printf("filewrite ERROR:The File Don't Open\n"); return -1; } //调用do_read()读取指定文件的len字节内容到text[]中. int rt=doread(fd,len,text); //若是do_read()返回值为负,则显示出错信息,不然将text[]中的内容显示到屏幕上; if(rt==-1){ printf("READ FAIL"); return -1; }else{ //输出text的内容 for(int i=0;i<len;i++){ printf("%c",text[i]); } printf("\n"); } }
#include "OS.h" int open_path(char* dirname); int close(int fd); /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[16];//文件名标示符 /*--------------退出文件系统函数------------------*/ void exitsys(){ FILE * fd=fopen("myfsys","w"); //关闭全部打开的文件 for(int i=0;i<MAXOPENFILE;i++){ if(openfilelist[i].topenfile==1) close(i); } fwrite(myvhard,sizeof(char),DISKSIZE,fd); fclose(fd); free(myvhard); exit(0); }
几个可有可无的函数
#include "stdio.h" void help() { printf("\n"); printf("-----------------------help------------\n"); printf("format :-------Format The Disk.\n"); printf("exit :-------Exit OS File System AND **NOT SAVE**\n"); printf("exitsys :-------Exit OS File System AND SAVE") printf("cd dirname :-------Change Directory\n"); printf("mkdir dirname :-------Make Directory.\n"); printf("rmdir dirname :-------Delete Directory.\n"); printf("ls dirname :-------List Directory .\n"); printf("creat filename:-------Creat File\n"); printf("write fd :-------Wirte File\n"); printf("read fd :-------Read File\n"); printf("rm filename:-------Remove File\n"); printf("open filename:-------Open File\n"); printf("close fd :-------Close File\n"); printf("open_path\n"); printf("--------------------------------------\n\n"); }
和本身实现的分割字符串
// // 切割字符串,例如/A/B/C/D 切割成 /A/B/C 和 D // #include "OS.h" /*--------------全局变量-------------------------*/ extern char* myvhard;//虚拟磁盘起始地址 extern string currentdir;//当前目录 extern string cmd; //读取指令 extern USEROPEN openfilelist[MAXOPENFILE];//文件打开表 extern USEROPEN *ptrcuridr;//当前目录在文件打开表的位置 extern DISK* disk;//将内容结构化 extern char command[50];//文件名标示符 /*-----------------------------------------------*/ int FileSubstr(char *str){ int len=strlen(str); int cnt=0,flag=0; for(int i=1;i<len-1;i++) { if(str[i]=='/') { cnt++; flag=i; } } if(cnt==0) return -1; else return flag; }