📄 myfs.txt
字号:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<iostream.h>
#include<windows.h>
#define BLOCK_SIZE 512 //磁盘块大小
#define DIR_NUM 64 //最多目录节点数
#define FILE_NUM 512 //最多文件节点数
#define BLOCK_NUM 1024 //磁盘块数目
#define BUF_NUM 32 //主存缓冲区数目
const char file_system_name[]="fs.dat"; //磁盘文件名
struct dir_node //目录节点
{
char space;
SYSTEMTIME ctime; //创建时间
char dir_name[32]; //目录名
int child_dir[8]; //子目录索引
int dir_count; //当前子目录数
int child_file[16]; //子文件索引
int file_count; //当前子文件数
int parent; //父目录索引
};
struct file_node //文件节点
{
char space;
SYSTEMTIME ctime; //创建时间
char file_name[32]; //文件名
int block[4]; //该文件占有的磁盘块索引
int block_count; //该文件当前占有的磁盘块数
int file_length; //文件长度
int parent; //父目录索引
};
struct buffer_node //主存缓冲区节点
{
int flag; //占用标志
int file_id; //占用该缓冲区节点的文件索引
char buf[BLOCK_SIZE*4]; //缓冲区,存放读写文件的数据
int length; //缓冲区大小
int offset; //打开系统后第一次写该文件的开始位置
};
struct dir_node dir[DIR_NUM+1]; //目录节点表
struct file_node file[FILE_NUM]; //文件节点表
struct buffer_node buffer[BUF_NUM]; //缓冲区数组
int dir_flag[DIR_NUM]; //各目录节点占用标志,0表示空闲,1表示被占用
int used_dir; //已用的目录节点数
int file_flag[FILE_NUM]; //各文件节点的占用标志
int used_file; //已用的文件节点数
int block_flag[BLOCK_NUM]; //磁盘块的占用标志
int used_block; //已用的磁盘块数
int al_dir[DIR_NUM]; //目录节点修改登记表
int al_file[FILE_NUM]; //文件节点修改登记表
int al_dflag[DIR_NUM]; //目录节点占用标志登记表
int al_fflag[FILE_NUM]; //文件节点占用标志登记表
int al_bflag[BLOCK_NUM]; //磁盘块占用标志登记表
int open_files[FILE_NUM]; //文件读写登记表
int curr; //当前目录索引
struct dir_node *curr_dir; //当前目录节点指针
char curr_path[512]; //当前路径
FILE *fp; //文件指针
int f_count; //用于计算被复制目录下的文件数目
int d_count; //用于计算被复制目录下的子目录数目
int b_count; //用于计算被复制目录下的文件占用的磁盘块数目
void create_file_system() //创建文件系统
{
fp=fopen(file_system_name,"wb+"); //以读写方式打开,如果存在,则覆盖原来信息,
if(fp==NULL) //否则创建该文件
{
printf("Create file system error!\n");
exit(1);
}
//申请空间
int total=sizeof(int)*(DIR_NUM+FILE_NUM+BLOCK_NUM+3)+sizeof(struct dir_node)*DIR_NUM+sizeof(struct file_node)*FILE_NUM+BLOCK_SIZE*BLOCK_NUM;
for(long len=0;len<total;len++)
fputc(0,fp);
fseek(fp,0,SEEK_SET); //写超级块信息
used_dir=1;
fwrite(&used_dir,sizeof(int),1,fp);
used_file=0;
used_block=0;
fwrite(&used_file,sizeof(int),2,fp);
dir_flag[0]=1;
fwrite(&dir_flag[0],sizeof(int),1,fp); //标志对应目录节点、文件节点的使用情况
fwrite(&dir_flag[1],sizeof(int),DIR_NUM+FILE_NUM+BLOCK_NUM-1,fp);
strcpy(dir[0].dir_name,"A:"); //写根目录信息
dir[0].dir_count=0;
dir[0].file_count=0;
dir[0].parent=-1;
GetLocalTime(&dir[0].ctime); //获得当前时间
fwrite(&dir[0],sizeof(struct dir_node),1,fp);
for(int i=0;i<DIR_NUM;i++) //将所有标记清零
{
al_dir[i]=0;
al_dflag[i]=0;
dir[i].dir_count=0;
dir[i].file_count=0;
}
for(i=0;i<FILE_NUM;i++)
{
al_file[i]=0;
al_fflag[i]=0;
open_files[i]=0;
}
for(i=0;i<BLOCK_NUM;i++)
al_bflag[i]=0;
for(i=0;i<BUF_NUM;i++)
buffer[i].flag=0;
fflush(fp);
fclose(fp);
}
int search(int parent,char *name,int type,int &index) //搜索目录或文件,成功则返回该文件或目录的索引
{ //失败则返回-1,type用来区分要搜索的是文件还是目录
struct dir_node *p=&dir[parent]; //0表示目录,1表示文件,index用来指定找到的文件或
int i,temp; //目录在父目录下的位置
if(type==0)
for(i=0;i<p->dir_count;i++)
{
temp=p->child_dir[i];
if(strcmp(name,dir[temp].dir_name)==0)
{
index=i;
return temp;
}
}
else
for(i=0;i<p->file_count;i++)
{
temp=p->child_file[i];
if(strcmp(name,file[temp].file_name)==0)
{
index=i;
return temp;
}
}
return -1;
}
int get_parent(char *name,int &p) //根据输入的字符串,获得父目录及真正的文件
{ //或目录名,引用参数p用来指定目录或文件名
char buf[32],*path,*s; //的起始位置
int pos,start=0,index;
path=new char[128];
strcpy(path,name);
s=strrchr(path,'/'); //如果没有指定路径,则将当前目录指定为
if(s==NULL) //父目录
return curr;
pos=(int)(s-path);
p=pos+1;
if(p==(int)strlen(path))
return -1;
path[p]='\0';
s=strchr(path,'/');
pos=(int)(s-path);
if(strncmp(path,"A:",pos)!=0) //前面没有跟目录名,则从当前目录往下搜索
start=curr;
else
path+=3;
while(start!=-1 && (int)strlen(path)>0) //进行搜索,知道路径名结束或出现不匹配
{
s=strchr(path,'/');
pos=(int)(s-path);
strncpy(buf,path,pos);
buf[pos]='\0';
start=search(start,buf,0,index);
path+=pos+1;
}
return start;
}
int get_block(int pos) //为文件申请磁盘块,一次调用申请一块,成功则返回
{ //磁盘块索引,失败返回-1
for(int i=0;i<BLOCK_NUM;i++)
if(block_flag[i]==0)
{ //修改磁盘块使用情况及文件的控制信息
block_flag[i]=1;
al_bflag[i]++;
used_block++;
int top=file[pos].block_count;
file[pos].block[top]=i;
file[pos].block_count++;
return i;
}
return -1;
}
void return_block(int pos) //释放文件占用的磁盘块,用于删除文件时用
{
for(int i=0;i<file[pos].block_count;i++)
{
int temp=file[pos].block[i];
block_flag[temp]=0;
al_bflag[temp]++;
}
used_block-=file[pos].block_count;
}
int get_dir(int parent,char *dir_name) //创建目录节点,成功则返回目录的索引,失败则返回-1
{
int index;
if(search(parent,dir_name,0,index)!=-1) //搜索在父目录下是否有同名目录,有则创建失败
{
printf("Directory name repeated!\n");
return -1;
}
for(int i=1;i<DIR_NUM;i++) //搜索空闲的目录节点
if(dir_flag[i]==0)
{ //登记并给目录节点初始化
dir_flag[i]=1;
al_dflag[i]++;
al_dir[i]++;
used_dir++;
strcpy(dir[i].dir_name,dir_name);
dir[i].dir_count=0;
dir[i].file_count=0;
dir[i].parent=parent;
GetLocalTime(&dir[i].ctime); //获得当前时间
return i;
}
return -1;
}
int get_file(int parent,char *file_name) //创建文件节点,成功则返回文件的索引号,失败返回-1
{
int index;
if(search(parent,file_name,1,index)!=-1) //搜索在父目录下是否有同名文件存在,有则创建失败
{
printf("File name repeated!\n");
return -1;
}
for(int i=0;i<FILE_NUM;i++) //搜索空闲的文件节点
if(file_flag[i]==0)
{
strcpy(file[i].file_name,file_name);
file[i].block_count=0;
if(get_block(i)==-1) //给新创建的文件申请磁盘块,如果失败,创建文件
{ //将失败
printf("Disk volumn error!\n");
return -1;
}
file_flag[i]=1;
al_fflag[i]++; //登记并给文件节点初始化
al_file[i]++;
used_file++;
file[i].file_length=0;
file[i].parent=parent;
GetLocalTime(&file[i].ctime); //获得当前时间
return i;
}
return -1;
}
int get_buffer(int pos) //给文件申请缓冲区,打开文件时调用,失败时返回-1
{
for(int i=0;i<BUF_NUM;i++)
if(buffer[i].flag==0)
{
buffer[i].flag=1; //修改使用标志并初始化
buffer[i].file_id=pos;
buffer[i].length=0;
buffer[i].offset=0;
return i;
}
return -1;
}
int get_buffer_id(int pos) //得到被打开文件的缓冲区索引号,失败则返回-1
{
for(int i=0;i<BUF_NUM;i++)
if(buffer[i].flag==1 && buffer[i].file_id==pos)
return i;
return -1;
}
int create_file(int parent,char *file_name) //在指定的目录下创建文件,如果创建成功则返回
{ //文件的索引号,否则返回-1
if(dir[parent].file_count==16) //如果父目录已满,则创建失败
{
printf("Parent directory is full!\n");
return -1;
}
int pos=get_file(parent,file_name); //开始创建文件
if(pos==-1)
{
printf("Create file error!\n");
return -1;
}
struct dir_node *p=&dir[parent]; //修改父目录的控制信息
int top=p->file_count;
p->child_file[top]=pos;
p->file_count++;
al_dir[parent]++;
return pos;
}
int create_dir(int parent,char *dir_name) //在指定的目录下创建目录,如果成功则返回目录
{ //的索引号,否则返回-1
if(dir[parent].dir_count==8) //如果父目录已满,则创建失败
{
printf("Parent directory is full!\n");
return -1;
}
int pos=get_dir(parent,dir_name); //开始创建目录
if(pos==-1)
{
printf("Create directory error!\n");
return -1;
}
struct dir_node *p=&dir[parent]; //修改父目录的控制信息
int top=p->dir_count;
p->child_dir[top]=pos;
p->dir_count++;
al_dir[parent]++;
return pos;
}
int md(char *name) //创建目录的主调函数,它的参数只有用户输入
{ //如果创建成功,则返回目录的索引号,否则
int parent,p=0; //返回-1
parent=get_parent(name,p);
if(parent==-1) //父目录找不到,输入有误,创建失败
{
printf("Path name error!\n");
return -1;
}
return create_dir(parent,name+p); //开始创建目录
}
int rename_dir(char *old_name,char *new_name) //对目录重命名,需要输入两个参数,如果
{ //成功返回目录的索引号,否则返回-1
int parent,p=0,index;
parent=get_parent(old_name,p);
if(parent==-1) //找不到父目录,输入错误,重命名失败
{
printf("Path name error!\n");
return -1;
}
int dir_id=search(parent,old_name+p,0,index); //找到父目录,查找要重命名的目录
if(dir_id==-1) //找不到该目录,重命名失败
{
printf("The directory not exist!\n");
return -1;
}
if(strcmp(old_name+p,new_name)!=0 && search(parent,new_name,0,index)!=-1)
{ //重命名后出现目录重名,重命名失败
printf("Dir name repeated!\n");
return -1;
}
strcpy(dir[dir_id].dir_name,new_name);
al_dir[dir_id]++;
return dir_id;
}
int create(char *name) //创建文件的主调函数,直接接受用户输入
{ //成功返回文件的索引号,否则返回-1
int parent,p=0;
parent=get_parent(name,p);
if(parent==-1) //找不到父目录,输入错误,创建失败
{
printf("Path name error!\n");
return -1;
}
return create_file(parent,name+p); //开始创建文件
}
int rename_file(char *old_name,char *new_name) //对文件重命名,成功返回文件的索引号
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -