📄 myfs.txt
字号:
if(parent==-1)
{
printf("Path name error!\n");
return -1;
}
return save_file(parent,name+p);
}
int save_dir(int parent,char *dir_name) //显式保存目录
{
int pos,index;
if((pos=search(parent,dir_name,0,index))==-1)
{
printf("The file not exist in current directory!\n");
return -1;
}
savedir(parent); //保存父目录
save(pos); //保存自身及下面的所有文件及目录
write_bit(pos,0);
return pos;
}
int saved(char *name) //保存目录的主调函数
{
int parent,p=0;
parent=get_parent(name,p);
if(parent==-1)
{
printf("Path name error!\n");
return -1;
}
return save_dir(parent,name+p);
}
void return_buffer() //释放缓冲区,并将数据写回磁盘
{ //该函数在缓冲区不够时调用
for(int i=0;i<BUF_NUM;i++)
savefile(buffer[i].file_id);
}
int open_file(int pos,int type) //打开文件,该函数在读写或复制文件时调用
{
int buffer_id;
if(open_files[pos]==0) //如果该文件未被打开,需要为其分配缓冲区
{
buffer_id=get_buffer(pos); //申请缓冲区
if(buffer_id==-1) //如果失败,将缓冲区内数据全部写回磁盘
{ //然后重新申请
return_buffer();
buffer_id=get_buffer(pos);
}
buffer[buffer_id].length=file[pos].file_length;
int num=file[pos].file_length%BLOCK_SIZE;
for(int j=0;j<file[pos].block_count-1;j++) //将磁盘的数据调入缓冲区
{
fseek(fp,sizeof(int)*(DIR_NUM+FILE_NUM+BLOCK_NUM+3)+sizeof(struct dir_node)*DIR_NUM+sizeof(struct file_node)*FILE_NUM+file[pos].block[j]*BLOCK_SIZE,SEEK_SET);
fread(buffer[buffer_id].buf+BLOCK_SIZE*j,BLOCK_SIZE,1,fp);
}
if(num>0)
{
fseek(fp,sizeof(int)*(DIR_NUM+FILE_NUM+BLOCK_NUM+3)+sizeof(struct dir_node)*DIR_NUM+sizeof(struct file_node)*FILE_NUM+file[pos].block[j]*BLOCK_SIZE,SEEK_SET);
fread(buffer[buffer_id].buf+BLOCK_SIZE*j,num,1,fp);
}
fflush(fp);
}
else //如果改文件已经被打开,只要获得缓冲区节点号
buffer_id=get_buffer_id(pos);
if(open_files[pos]<type) //如果是首次打开,或首次以写方式打开,
open_files[pos]=type; //需要做标记
return buffer_id;
}
//读文件,成功返回文件的索引号,否则返回-1
int read(int parent,char *file_name,int offset,int count,char *str)
{
int pos,index;
if((pos=search(parent,file_name,1,index))==-1) //搜索在指定目录下是否存在该文件
{
printf("The file to read not exist!\n");
return -1;
}
index=open_file(pos,1); //以读方式打开,并获得缓冲区节点号
if(offset>=buffer[index].length) //如果读的位置没有信息,将失败
{
printf("surpass the end of the file!\n");
return -1;
}
else if(offset+count>buffer[index].length) //如果读的字符数超过实际长度,以实际长度为准
count=buffer[index].length-offset;
strncpy(str,buffer[index].buf+offset,count); //读出
str[offset+count]='\0';
return pos;
}
int read_file(char *name,int offset,int count,char *str)
{ //读文件的主调函数
int parent,p=0;
parent=get_parent(name,p);
if(parent==-1)
{
printf("Path name error!\n");
return -1;
}
return read(parent,name+p,offset,count,str);
}
//写文件,成功返回文件的索引号,否则返回-1
int write(int parent,char *file_name,int offset,int count,char *str)
{
int pos,index,block_id;
if((pos=search(parent,file_name,1,index))==-1) //搜索在指定目录下是否存在该文件
{
printf("The file to write not exist!\n");
return -1;
}
int flag=open_files[pos];
index=open_file(pos,2); //以写方式打开,并获得缓冲区节点号
if(count>(int)strlen(str)) //如果写字符数超过实际的字符数,将做修改
count=(int)strlen(str);
int block_num=(offset+count)/BLOCK_SIZE;
if((offset+count)%BLOCK_SIZE>0)
block_num++;
if((used_block+block_num-file[pos].block_count)>BLOCK_NUM || block_num>4)
{ //磁盘空间不够,写失败
printf("Disk volumn error!\n");
return -1;
}
while(file[pos].block_count<block_num) //需要申请新的磁盘块
block_id=get_block(pos);
if(offset>=file[pos].file_length) //如果写的开始位置超过文件尾部,在中间填写
for(int i=file[pos].file_length;i<offset;i++)//空格,否则下次读可能会有问题
buffer[index].buf[i]=' ';
strncpy(buffer[index].buf+offset,str,count); //写入
buffer[index].length=offset+count;
if(flag<2) //该文件是第一次以写的方式打开,做标记
buffer[index].offset=offset;
return pos;
}
int write_file(char *name,int offset,int count,char *str)
{ //写文件的主调函数
int parent,p=0;
parent=get_parent(name,p);
if(parent==-1)
{
printf("Path name error!\n");
return -1;
}
return write(parent,name+p,offset,count,str);
}
//编辑文件,包括插入与删除
void edit(int buf_id,int type,int start,int finish,char *str)
{
char buf[1024];
int file_id=buffer[buf_id].file_id,i;
if(start<0)
start=0;
if(type==1) //插入字符串
{
if(start>buffer[buf_id].length)
{
for(i=buffer[buf_id].length;i<start;i++)
buffer[buf_id].buf[i]=' ';
buffer[buf_id].buf[i]='\0';
}
strcpy(buf,str);
strcat(buf,buffer[buf_id].buf+start);
strcat(buffer[buf_id].buf+start,buf);
buffer[buf_id].length=(int)strlen(buffer[buf_id].buf);
int block_num=buffer[buf_id].length/BLOCK_SIZE;
if(buffer[buf_id].length%BLOCK_SIZE!=0)
block_num++;
int block_id;
while(file[file_id].block_count<block_num) //需要申请新的磁盘块
block_id=get_block(file_id);
}
else //删除字符串
{
if(finish>buffer[buf_id].length)
finish=buffer[buf_id].length;
strcpy(buf,buffer[buf_id].buf+finish);
strcpy(buffer[buf_id].buf+start,buf);
buffer[buf_id].length-=finish-start;
int block_count=buffer[buf_id].length/BLOCK_SIZE;
if(buffer[buf_id].length%BLOCK_SIZE!=0)
block_count++;
int snum=file[file_id].block_count;
if(snum>1) //释放磁盘块
{
for(i=snum-1;i>block_count-1;i--)
{
int block_id=file[file_id].block[i];
block_flag[block_id]=0;
al_bflag[block_id]++;
file[file_id].block_count--;
used_block--;
}
al_file[file_id]++;
}
}
}
int copy_file(int dir_id,int source) //复制文件的核心函数,成功返回复制文件
{ //的索引号,否则返回-1
int pos,indexs,indext,block_id;
pos=create_file(dir_id,file[source].file_name);//创建文件
if(pos!=-1 && (file[source].file_length>0 || open_files[source]==2))
{ //如果创建成功,并且该文件中有数据,需要复制
indexs=open_file(source,1); //数据
indext=open_file(pos,2);
while(file[pos].block_count<file[source].block_count)
block_id=get_block(pos); //磁盘块不够,申请新的磁盘块
strcpy(buffer[indext].buf,buffer[indexs].buf);
int length=buffer[indexs].length;
buffer[indext].length=length;
file[pos].file_length=length;
al_file[pos]++;
}
return pos;
}
int copy_file(char *tname,char *sname) //复制文件的主调函数
{
int s=0,t=0,sparent,tparent,file_id,dir_id,index;
sparent=get_parent(sname,s);
tparent=get_parent(tname,t);
if(sparent==-1 || tparent==-1)
{
printf("Path name error!\n");
return -1;
}
file_id=search(sparent,sname+s,1,index);
if(file_id==-1)
{
printf("The source file not exist!\n");
return -1;
}
if(strcmp(tname,"A:")==0) //以下这几种情况上面无法处理,所以直接赋值
dir_id=0;
else if(strcmp(tname,".")==0)
dir_id=curr;
else if(strcmp(tname,"..")==0)
dir_id=dir[curr].parent;
else
dir_id=search(tparent,tname+t,0,index);
if(dir_id==-1)
{
printf("The dest dir not exist!\n");
return -1;
}
if(used_file==FILE_NUM || used_block+file[file_id].block_count>BLOCK_NUM)
{ //系统资源不足复制失败
printf("System source error!\n");
return -1;
}
return copy_file(dir_id,file_id);
}
void copy_dirs(int dest,int source) //复制目录的核心函数,用了递归思想
{
int n,pos=create_dir(dest,dir[source].dir_name);
if(pos==-1)
return;
for(int i=0;i<dir[source].file_count;i++)
n=copy_file(pos,dir[source].child_file[i]);
for(i=0;i<dir[source].dir_count;i++)
copy_dirs(pos,dir[source].child_dir[i]);
}
void precal(int dir_id) //计算要复制的目录需要的目录、文件及磁盘块数目
{ //用了递归思想
d_count++;
f_count+=dir[dir_id].file_count;
for(int i=0;i<dir[dir_id].file_count;i++)
b_count+=file[i].block_count;
for(i=0;i<dir[dir_id].dir_count;i++)
precal(dir[dir_id].child_dir[i]);
}
int copy_dir(char *tname,char *sname) //跟上面复制文件类似
{
int s=0,t=0,sparent,tparent,sdir_id,tdir_id,index;
sparent=get_parent(sname,s);
tparent=get_parent(tname,t);
if(sparent==-1 || tparent==-1)
{
printf("Path name error!\n");
return -1;
}
sdir_id=search(sparent,sname+s,0,index);
if(sdir_id==-1)
{
printf("The source dir not exist!\n");
return -1;
}
if(strcmp(tname,"A:")==0)
tdir_id=0;
else if(strcmp(tname,".")==0)
tdir_id=curr;
else if(strcmp(tname,"..")==0)
tdir_id=dir[curr].parent;
else
tdir_id=search(tparent,tname+t,0,index);
if(tdir_id==-1)
{
printf("The dest dir not exist!\n");
return -1;
}
f_count=0;
d_count=0;
b_count=0;
precal(sdir_id);
if(d_count+used_dir>DIR_NUM || f_count+used_file>FILE_NUM || b_count+used_block>BLOCK_NUM)
{ //系统资源不足,复制失败
printf("System source error!\n");
return -1;
}
copy_dirs(DIR_NUM,sdir_id); //主要解决把父目录复制到子目录的问题
int top=dir[tdir_id].dir_count;
int result=dir[DIR_NUM].child_dir[0];
dir[DIR_NUM].dir_count=0;
dir[tdir_id].child_dir[top]=result;
dir[tdir_id].dir_count++;
dir[result].parent=tdir_id;
al_dir[tdir_id]++;
al_dir[result]++;
return tdir_id;
}
void format() //格式化,相当于重新创建文件系统
{
create_file_system();
fp=fopen(file_system_name,"rb+");
if(fp==NULL)
{
printf("Open file system error!\n");
exit(1);
}
curr=0;
curr_dir=&dir[curr]; //设置当前目录为根目录
strcpy(curr_path,curr_dir->dir_name);
strcat(curr_path,"/");
}
void collect(int dir_id) //该函数主要为了防止因非正常退出导致
{ //丢失数据而出现的不一致情况,不过
for(int i=0;i<dir[dir_id].dir_count;i++) //它不能恢复丢失的数据
collect(dir[dir_id].child_dir[i]);
for(i=0;i<dir[dir_id].file_count;i++) //该目录虽然保存了,但它下面的某个文件
{ //未保存,则将有关于它的信息从父目录中删除
int file_id=dir[dir_id].child_file[i];
if(file_flag[file_id]==0)
{
dir[dir_id].file_count--;
if(dir[dir_id].file_count>0)
{
int top=dir[dir_id].file_count;
dir[dir_id].child_file[i]=dir[dir_id].child_file[top];
}
al_dir[dir_id]++;
}
}
for(i=0;i<dir[dir_id].dir_count;i++) //跟上面类似,只是,这是某个子目录未保存
{
int temp=dir[dir_id].child_dir[i];
if(dir_flag[temp]==0)
{
dir[dir_id].dir_count--;
if(dir[dir_id].dir_count>0)
{
int top=dir[dir_id].dir_count;
dir[dir_id].child_dir[i]=dir[dir_id].child_dir[top];
}
al_dir[dir_id]++;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -