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

📄 myfs.txt

📁 这是我写的一个用于测试的文件系统
💻 TXT
📖 第 1 页 / 共 4 页
字号:
	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 + -