操作系统课程设计--文件管理系统



/* 定义控制台应用程序的入口点 */
#include <map>
#include<iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <algorithm>

//#include <windows.h>  //linux lab 无法引用 
#define PHYSICAL_BLOCK_SIZE 1024
#define LOGICAL_BLOCK_SIZE 1024
#define NAME_LEN 14
#define START_PARTITION_TABLE 0x1be

using namespace std;

void print_char(char c);
void get_inode(unsigned short inode_id, struct d_inode* inode);
void puts(const char s[],const int ma);
bool print_file(unsigned short id);
string new_string(const char *s,const int ma);
void load_logical_bitmap();
void write_load_logical_bitmap();
int is_logical_valid(unsigned short inode_id);
bool update_logical_valid(unsigned short inode_id);
void delete_inode_father(unsigned short id);

//分区表结构
struct par_table_entry {
	char boot_indicator;	//导入指示器,绝大多数情况都是0
	char start_chs_val[3];	//起始柱面磁头扇区值,3个字节分别对应柱面号、磁头号、扇区号
	char par_type;			//分区类型
	char end_chs_val[3];	//终止柱面磁头扇区值
	int start_sector;		//起始盘块号
	int par_size;			//分区大小
};

// 超级块结构体
struct super_block
{
  unsigned short s_ninodes;		//  
  unsigned short s_nzones;		// 逻辑块数。
  unsigned short s_imap_blocks;	// i 节点位图所占用的数据块数。
  unsigned short s_zmap_blocks;	// 逻辑块位图所占用的数据块数。
  unsigned short s_firstdatazone;	// 第一个数据逻辑块号。
  unsigned short s_log_zone_size;	// log(数据块数/逻辑块)。(以2 为底)。
  unsigned long s_max_size;		// 文件最大长度。
  unsigned short s_magic;		// 文件系统魔数。
};

// i节点结构体
struct d_inode
{
  unsigned short i_mode;		// 文件类型和属性(rwx 位)。
  unsigned short i_uid;			// 用户id(文件拥有者标识符)。
  unsigned long i_size;			// 文件大小(字节数)。
  unsigned long i_time;			// 修改时间(自1970.1.1:0 算起,秒)。
  unsigned char i_gid;			// 组id(文件拥有者所在的组)。
  unsigned char i_nlinks;		// 链接数(多少个文件目录项指向该i 节点)。
  unsigned short i_zone[9];		// 直接(0-6)、间接(7)或双重间接(8)逻辑块号。
								// zone 是区的意思,可译成区段,或逻辑块。
};

//目录项结构
struct dir_entry{
	unsigned short inode;	//i节点号
	char name[NAME_LEN];	//文件名
	dir_entry(unsigned short x,char y[NAME_LEN]){
		inode = x;
		for(int ii=0;ii<NAME_LEN;ii++){
			name[ii]=y[ii];
		}
	}
	dir_entry(){}
};
struct super_block sblock;		//超级块
struct par_table_entry pte[4];	//分区表数组
FILE* fd;						//文件指针
char physical_block[PHYSICAL_BLOCK_SIZE]; //存储物理块
char logical_block[LOGICAL_BLOCK_SIZE];  //存储逻辑块
char *inode_bitmap;		//i节点位图指针
char *logical_bitmap;	//逻辑块位图指针
map<unsigned short,unsigned short> inode_father;  //临时存储文件 id节点的父节点 

//读取一个物理块
void get_physical_block(int block_num)
{
	//减1是因为物理盘块是从1开始计数
	fseek(fd, (block_num - 1) * PHYSICAL_BLOCK_SIZE, SEEK_SET);
	fread(physical_block, PHYSICAL_BLOCK_SIZE, 1, fd);
	fflush(stdin);
}

//写入一个物理块 
void write_physical_block(int block_num){
	//减1是因为物理盘块是从1开始计数
	
	fseek(fd, (block_num - 1) * PHYSICAL_BLOCK_SIZE, SEEK_SET);
	fwrite(physical_block, PHYSICAL_BLOCK_SIZE, 1, fd);
	fflush(stdout);
	

}

//读取第一个分区的一个逻辑块
void get_partition_logical_block(int block_num)
{
	//block_num前面加的1表示在第一个分区前还有一个主引导记录(MBR)块,
	//后面加的1是因为物理盘块是从1开始计数的,而逻辑块是从0开始计数的
	get_physical_block(1 + block_num + 1);
	memcpy(logical_block, physical_block, LOGICAL_BLOCK_SIZE);
}

//写入一个逻辑块
void write_partition_logical_block(int block_num)
{
	//block_num前面加的1表示在第一个分区前还有一个主引导记录(MBR)块,
	//后面加的1是因为物理盘块是从1开始计数的,而逻辑块是从0开始计数的
	memcpy(physical_block,logical_block , LOGICAL_BLOCK_SIZE);
	
	write_physical_block(1 + block_num + 1);
	
	
}

//读取分区表
void get_partition_table()
{
	int i = 0;

	//分区表有4个16字节的表项组成,第一个表项的起始地址为START_PARTITION_TABLE
	get_physical_block( 1 );	//分区表在物理盘块的第1块
	memcpy(pte, &physical_block[START_PARTITION_TABLE], sizeof(pte));
	for(i = 0; i < 4; i++)
	{
		printf("**************pattition table%d****************\n", i+1);
		printf("Boot Indicator:%d\n", pte[i].boot_indicator);
		printf("start CHS value:0x%04x\n", pte[i].start_chs_val);
		printf("partition type:%ld\n", pte[i].par_type);
		printf("end CHS value:0x%04x\n", pte[i].end_chs_val);
		printf("start sector:%d\n", pte[i].start_sector);
		printf("partition size:%d\n", pte[i].par_size);
	}
}

//读取第一个分区的超级块
void get_super_block()
{	
	get_partition_logical_block( 1 );
	memcpy(&sblock, logical_block, sizeof(sblock));
	
	printf("**************super block****************\n");
	printf("ninodes:%d\n", sblock.s_ninodes);
	printf("nzones:%d\n", sblock.s_nzones);
	printf("imap_blocks:%d\n", sblock.s_imap_blocks);
	printf("zmap_blocks:%d\n", sblock.s_zmap_blocks);
	printf("firstdatazone:0x%04x\n", sblock.s_firstdatazone);
	printf("log_zone_size:%d\n", sblock.s_log_zone_size);
	printf("max_size:0x%x = %dByte\n", sblock.s_max_size,sblock.s_max_size);
	printf("magic:0x%x\n", sblock.s_magic);
}	

/*************i节点位图相关操作函数*********************/ 
//加载i节点位图
void load_inode_bitmap()
{
	inode_bitmap = (char*)malloc(sblock.s_imap_blocks * LOGICAL_BLOCK_SIZE);
	int i = 0;
	for(i = 0; i < sblock.s_imap_blocks; i++)
	{
		//i节点位图前有1个引导块和一个超级块
		get_partition_logical_block(1 + 1 + i);	
		memcpy(&inode_bitmap[i * LOGICAL_BLOCK_SIZE], &logical_block, LOGICAL_BLOCK_SIZE);
	}
}

//写入i节点位图 
void write_load_inode_bitmap()
{
	
	for(int i = 0; i < sblock.s_imap_blocks; i++)
	{
		
		//i节点位图前有1个引导块和一个超级块
		memcpy(&logical_block, &inode_bitmap[i * LOGICAL_BLOCK_SIZE], LOGICAL_BLOCK_SIZE);
		
		write_partition_logical_block(1 + 1 + i);	
	}
}

//根据i节点位图判断其对应的i节点是否有效
//参数inode_id为i节点的id
//有效返回1,无效返回0
int is_inode_valid(unsigned short inode_id)
{
	if(inode_id > sblock.s_ninodes)
		return 0;
		
	char byte = inode_bitmap[(inode_id - 1) / 8]; //inode_id减1是因为i节点是从1开始计数的
	return (byte >> (7 - (inode_id - 1) % 8) ) & 0x1;	//取一个字节中的某位与1做位运算
}

//修改i节点位图,将i节点位图置为0或1 
bool update_inode_valid(unsigned short inode_id,int val){
	if(inode_id > sblock.s_ninodes)
		return 0; 
	
	char byte = inode_bitmap[(inode_id - 1) / 8]; //inode_id减1是因为i节点是从1开始计数的
	int now_val = ((byte >> (7 - (inode_id - 1) % 8) ) & 0x1);
	if(now_val==1&&val!=1){
		char x = (1<<(7 - (inode_id - 1) % 8) );
		inode_bitmap[(inode_id - 1) / 8] = byte - x; 
		 
	}else if(now_val==0&&val!=0){
		char x = (1<<(7 - (inode_id - 1) % 8) );
		inode_bitmap[(inode_id - 1) / 8] = byte + x; 
	}
	write_load_inode_bitmap();  //对应 i节点写回软盘
	return 1;
}

/*************逻辑块位图相关操作函数*********************/ 
//加载逻辑块位图
void load_logical_bitmap(){
	logical_bitmap = (char*)malloc(sblock.s_zmap_blocks * LOGICAL_BLOCK_SIZE);
	int i = 0;
	for(i = 0; i < sblock.s_zmap_blocks; i++)
	{
		//逻辑块位图前有1个引导块 ,一个超级块 , 三个 i 节点位图逻辑块 
		get_partition_logical_block(1 + 1 + i+sblock.s_imap_blocks);	
		memcpy(&logical_bitmap[i * LOGICAL_BLOCK_SIZE], &logical_block, LOGICAL_BLOCK_SIZE);
	}
}

//写入逻辑块位图 
void write_load_logical_bitmap()
{
	
	for(int i = 0; i < sblock.s_zmap_blocks; i++)
	{
		
		//逻辑块位图前有1个引导块 ,一个超级块 , 三个 i 节点位图逻辑块 
		memcpy(&logical_block, &logical_bitmap[i * LOGICAL_BLOCK_SIZE], LOGICAL_BLOCK_SIZE);
		
		write_partition_logical_block(sblock.s_imap_blocks+1 + 1 + i);	
	}
}

//判断 inode_id 数据逻辑块(位图)是否被占用 
int is_logical_valid(unsigned short inode_id)
{
	
		
	char byte = logical_bitmap[(inode_id - 1) / 8]; //inode_id减1是因为i节点是从1开始计数的
	return (byte >> (7 - (inode_id - 1) % 8) ) & 0x1;	//取一个字节中的某位与1做位运算
}

//inode_id 数据逻辑块位图修改 
bool update_logical_valid(unsigned short inode_id,int val){
	
	char byte = logical_bitmap[(inode_id - 1) / 8]; //inode_id减1是因为i节点是从1开始计数的
	int now_val = ((byte >> (7 - (inode_id - 1) % 8) ) & 0x1);
	if(now_val==1&&val!=1){
		char x = (1<<(7 - (inode_id - 1) % 8) );
		logical_bitmap[(inode_id - 1) / 8] = byte - x;
		
	}else if(now_val==0&&val!=0){
		char x = (1<<(7 - (inode_id - 1) % 8) );
		logical_bitmap[(inode_id - 1) / 8] = byte + x;
		
	}
	write_load_logical_bitmap();   //逻辑块位图写回软盘 
	return 1;
}

//根据i节点id读取i节点信息 
void get_inode(unsigned short inode_id, struct d_inode* inode)
{
	//一个引导块,一个超级块,sblock.s_imap_blocks个i节点位图,sblock.s_zmap_blocks个逻辑块位图	
	//一个i节点占32个字节,一个盘块有LOGICAL_BLOCK_SIZE/32个节点,所以inode_id/(LOGICAL_BLOCK_SIZE/32)
	//减1是因为i节点号是从1开始计数的,而逻辑块号是从0开始计数的
	//inode_blocknum是i节点在逻辑块中的偏移块数
	int inode_blocknum = 1 + 1 + sblock.s_imap_blocks + sblock.s_zmap_blocks + (inode_id - 1) / (LOGICAL_BLOCK_SIZE/32) ;
	get_partition_logical_block(inode_blocknum);
	memcpy((char*)inode, &logical_block[((inode_id - 1) % sizeof(struct d_inode)) * sizeof(struct d_inode)], sizeof(struct d_inode));
}

//根据i节点信息写回软盘 
void write_inode(unsigned short inode_id, struct d_inode inode)
{
	int inode_blocknum = 1 + 1 + sblock.s_imap_blocks + sblock.s_zmap_blocks + (inode_id - 1) / (LOGICAL_BLOCK_SIZE/32) ;
	get_partition_logical_block(inode_blocknum);
	memcpy(&logical_block[((inode_id - 1) % sizeof(struct d_inode)) * sizeof(struct d_inode)],(char*)&inode , sizeof(struct d_inode));
	
	write_partition_logical_block(inode_blocknum);
	
}

/*****************打印,查找 id逻辑块信息**************************/ 
//递归打印 i节点下的目录
void print_inode(unsigned short id, int tab_count, const char* name)
{
	int i, m, n;
	struct d_inode inode;
	struct dir_entry dir;
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(id) != 1)return ;
		
	get_inode(id, &inode);
	tab_count++;
	unsigned short mode = inode.i_mode >> 12; //高4位存放的是文件类型
	//如果是目录文件
	//	if(new_string(name,NAME_LEN)=="file.txt"){
	//		cout<<inode.i_mode<<" "<<mode<<endl;
	//	} 
	if(mode == 4)
	{
		//打印tab键,为了使目录有层次感
		for(i=0; i<tab_count; i++)
		{
			printf("\t");
		}
		//printf("%s\n", name);
		cout<<new_string(name,NAME_LEN)<<" "<<id<<endl;
		//循环读取i节点中的i_zones[]数组
		for(m = 0; m<7; m++)
		{
			//如果数组数据为0,则跳过
			if(inode.i_zone[m] == 0)
				continue;
			
			//一个逻辑块最多存储64个目录项,循环读取64个目录项
			//其中前两项分别为 . 和 .. 
			for(n = 0; n < 64; n++)
			{
				get_partition_logical_block(inode.i_zone[m]);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dir, &logical_block[n * sizeof(dir)], sizeof(dir));
				
				//如果是 .和..则继续循环
				if(n == 0 || n == 1)
					continue;
					
				//如果目录项中没有内容了则不再读取
				if(dir.inode == 0)
					break;
				
				//递归打印子目录
				print_inode(dir.inode, tab_count, dir.name);
				if(new_string(dir.name,NAME_LEN)=="root"){
					//cout<<"this is "<<new_string(dir.name,NAME_LEN)<<" id="<<dir.inode<<"if true"<<is_inode_valid(dir.inode)<<endl;
					//Sleep(2000);
					//exit(0);
				}
			}
		}
	}
	
	//如果是常规文件
	else if(mode == 8)
	{
		for(i=0; i<tab_count; i++)
		{
			printf("\t");
		}
		//puts(name,NAME_LEN);
		cout<<new_string(name,NAME_LEN)<<" "<<id<<endl;
		//printf("%s %d\n", name,id);
		//if(new_string(name,NAME_LEN)=="myfiles"){
		//Sleep(3000);

	}else if(mode = 9){
		
	}
	//如果块设备文件、字符设备文件等其他类型文件,请读者尝试自己实现
}

//查找 id 的i节点的文件夹下的名为 find_name 的子文件,并返回其 i节点id号 
unsigned short find_inode(unsigned short id, string find_name)
{
	int i, m, n;
	struct d_inode inode;
	struct dir_entry dir;
	
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(id) != 1)
		return 0;
		
	get_inode(id, &inode);
	unsigned short mode = inode.i_mode >> 12; //高4位存放的是文件类型
	//如果是目录文件
	//cout<<mode<<endl;
	//mode=4;
	if(mode!=4){
		return 0;
	}

	//循环读取i节点中的i_zones[]数组
	for(m = 0; m<7; m++)
	{
		//cout<<inode.i_zone[m]<<endl;
		//如果数组数据为0,则跳过
		if(inode.i_zone[m] == 0)
			continue;
		
		//一个逻辑块最多存储64个目录项,循环读取64个目录项
		//其中前两项分别为 . 和 .. 
		for(n = 0; n < 64; n++)
		{
			get_partition_logical_block(inode.i_zone[m]);
			//将逻辑块中的数据拷贝到目录项结构体
			memcpy((char*)&dir, &logical_block[n * sizeof(dir)], sizeof(dir));
			
			//如果是 .和..则继续循环
			if(n == 0 || n == 1)
				continue;
				
			//如果目录项中没有内容了则不再读取
			if(dir.inode == 0)
				break;
			
			//递归打印子目录
			//find_inode(dir.inode, tab_count, dir.name,find_name);
			//cout<<"*"<<new_string(dir.name,NAME_LEN)<<"* "<<dir.inode<<"*"<<find_name<<"*\n";
			if(new_string(dir.name,NAME_LEN)==find_name){//表示查找到 
				return dir.inode;
			}
		}
	}
	return 0;
}

//对(id=1 绝对)路径下的文件查找其 i 节点 id 
unsigned short find_root_inode(string find_name,int start_id){  
	if(find_name=="/")return 1;
	if(find_name[find_name.size()-1]!='/')find_name+="/";
	if(find_name[0]!='/')find_name = "/"+find_name;
	//确保其绝对路径为 "/name_1/name_2/name_3" 的形式 
	int last=0;
	int id=start_id;
	
	for(int i=1;i<find_name.size();i++){
		if(find_name[i]=='/'){
			
			//cout<<id<<" "<<string(find_name.begin()+last+1,find_name.begin()+i)<<endl; 
			id=find_inode(id,string(find_name.begin()+last+1,find_name.begin()+i));
			last=i;
			
			if(id==0)return 0;
		}
	} 
	return id;
}

//输出打印name文件(绝对)路径下的文件内容 
void print_file(string name){
	puts("-------------cout-----------------");
	unsigned short id = find_root_inode(name,1);
	if(id==0){
		cout<<"error no file  "<<name<<"\n";
	
	}else if(!print_file(id))cout<<"error no last file  "<<name<<"\n";
	puts("-------------endl-----------------");
}

//重载打印函数,对start_i下的文件内容打印(相对路径) 
void print_file(string name,int start_id){
	puts("-------------cout-----------------");
	unsigned short id = find_root_inode(name,start_id);
	if(id==0){
		cout<<"error no file  "<<name<<"\n";
	
	}else if(!print_file(id))cout<<"error no purpose file  "<<name<<"\n";
	puts("-------------endl-----------------");
}

//打印 id 节点下文件内容 
bool print_file(unsigned short id){
	int i, m, n;
	struct d_inode inode;
	struct dir_entry dir;
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(id) != 1){
		//cout<<"this 1"<<endl;
		return 0;
	}
		
		
	get_inode(id, &inode);
	unsigned short mode = inode.i_mode >> 12; //高4位存放的是文件类型
	//如果是目录文件,打印其子文件夹 
	if(mode == 4)
	{
		//循环读取i节点中的i_zones[]数组
		for(m = 0; m<7; m++)
		{
			//如果数组数据为0,则跳过
			if(inode.i_zone[m] == 0)
				continue;
			
			//一个逻辑块最多存储64个目录项,循环读取64个目录项
			//其中前两项分别为 . 和 .. 
			for(n = 0; n < 64; n++)
			{
				get_partition_logical_block(inode.i_zone[m]);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dir, &logical_block[n * sizeof(dir)], sizeof(dir));
				
				//如果是 .和..则继续循环
				if(n == 0 || n == 1)
					continue;
					
				//如果目录项中没有内容了则不再读取
				if(dir.inode == 0)
					break;
				
				
				puts(dir.name,NAME_LEN);
			}
		}
		return 1;
	}
	//cout<<"----strat----"<<endl;
	for(m = 0; m<7; m++){
		//如果数组数据为0,则跳过
		//cout<<inode.i_zone[m]<<endl;
		if(inode.i_zone[m] == 0)
			break;
		
		if(is_logical_valid(inode.i_zone[m]) != 1){cout<<"file be delete a part\n";return 0;}
		//cout<<m<<" "<<inode.i_zone[m]<<endl;
		get_partition_logical_block(inode.i_zone[m]);
		puts(logical_block,PHYSICAL_BLOCK_SIZE);

	}
	
	if(inode.i_zone[7]){
		
		for(n = 0; n < 512; n++)
		{
			unsigned short dete_id;
			get_partition_logical_block(inode.i_zone[7]);
			//将逻辑块中的数据拷贝到目录项结构体
			memcpy((char*)&dete_id, &logical_block[n*sizeof(dete_id)], sizeof(dete_id));
			//cout<<(dete_id);cout<<endl;
			//cout<<7<<" "<<dete_id<<endl;
			if(dete_id==0)break;
			if(is_logical_valid(dete_id) != 1){cout<<"file be delete a part\n";return 0;}
			
			get_partition_logical_block(dete_id);
			puts(logical_block,PHYSICAL_BLOCK_SIZE);
		}
	}

	if(inode.i_zone[8]){
	
		for(int n1 = 0; n1 < 512; n1++)
		{
			unsigned short dete_id_1;
			get_partition_logical_block(inode.i_zone[8]);
			//将逻辑块中的数据拷贝到目录项结构体
			memcpy((char*)&dete_id_1, &logical_block[n1*2], 2);
			//print_char(dete_id[0]);cout<<endl;
			if(dete_id_1==0)break;
			if(is_logical_valid(dete_id_1) != 1){cout<<"file be delete a part\n";return 0;}
			for(int n2 = 0; n2 < 512; n2++)
			{
				unsigned short dete_id_2;
				get_partition_logical_block(dete_id_1);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dete_id_2, &logical_block[n2*2], 2);
				//print_char(dete_id[0]);cout<<endl;
				if(dete_id_2==0)break;
				if(is_logical_valid(dete_id_2) != 1){cout<<"file be delete a part\n";return 0;}
				get_partition_logical_block(dete_id_2);
				puts(logical_block,PHYSICAL_BLOCK_SIZE);
			}
		}
	}
	return 1;
	
}

/****************删除文件************************/
// 删除  inode_id 文件以及下属所有子文件以及释放下属所有逻辑块 
bool delete_file_inode_valid(unsigned short inode_id){
	int  m, n;
	struct d_inode inode;
	struct dir_entry dir;
	
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(inode_id) != 1)
		return 0;
		
	get_inode(inode_id, &inode);
	
	unsigned short mode = inode.i_mode >> 12; //高4位存放的是文件类型
	//如果是目录文件
	if(mode == 4)
	{
		//循环读取i节点中的i_zones[]数组
		for(m = 0; m<7; m++)
		{
			//如果数组数据为0,则跳过
			if(inode.i_zone[m] == 0)
				continue;
			
			//一个逻辑块最多存储64个目录项,循环读取64个目录项
			//其中前两项分别为 . 和 .. 
			for(n = 0; n < 64; n++)
			{
				get_partition_logical_block(inode.i_zone[m]);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dir, &logical_block[n * sizeof(dir)], sizeof(dir));
				
				//如果是 .和..则继续循环
				if(n == 0 || n == 1)
					continue;
					
				//如果目录项中没有内容了则不再读取
				if(dir.inode == 0)
					break;
				
				//递归打印子目录
				delete_file_inode_valid(dir.inode);
			}
		}
	}
	
	//如果是其他文件
	else{
		
		for(m = 0; m<7; m++)
		{
			//如果数组数据为0,则跳过
			if(inode.i_zone[m] == 0)
				continue;
			
			update_logical_valid(inode.i_zone[m],0);//将对应的数据逻辑位图释放 
			
		}
		if(inode.i_zone[7]){
			
			for(n = 0; n < 512; n++)
			{
				unsigned short dete_id;
				get_partition_logical_block(inode.i_zone[7]);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dete_id, &logical_block[n*2], 2);
				//print_char(dete_id[0]);cout<<endl;
				if(dete_id==0)continue;
				update_logical_valid(inode_id,0);  //释放二级数据逻辑块位图 
			}
			update_logical_valid(inode.i_zone[7],0);//将对应的一级数据逻辑位图释放 
		}
	
		if(inode.i_zone[8]){
			
			
		
			for(int n1 = 0; n1 < 512; n1++)
			{
				unsigned short dete_id_1;
				get_partition_logical_block(inode.i_zone[8]);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dete_id_1, &logical_block[n1*2], 2);
				//print_char(dete_id[0]);cout<<endl;
				if(dete_id_1==0)continue;
				
				for(int n2 = 0; n2 < 512; n2++)
				{
					unsigned short dete_id_2;
					get_partition_logical_block(dete_id_1);
					//将逻辑块中的数据拷贝到目录项结构体
					memcpy((char*)&dete_id_2, &logical_block[n2*2], 2);
					//print_char(dete_id[0]);cout<<endl;
					if(dete_id_2==0)continue;
					update_logical_valid(inode_id,0);////将对应的三级数据逻辑位图释放 
				}
				update_logical_valid(dete_id_1,0);//将对应的二级数据逻辑位图释放
			}
			update_logical_valid(inode.i_zone[8],0);//将对应的一级数据逻辑位图释放 
		}
		
	}
	update_inode_valid(inode_id,0);//最后释放inode_id节点文件的 i节点位图 
	return 1;
}

//删除其父目录文件下的子文件信息 
void delete_inode_father(unsigned short id){
	unsigned short fat = inode_father[id];
	struct d_inode inode;
	struct dir_entry dir;
	
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(fat) != 1)
		return ;
	get_inode(fat, &inode);
	//cout<<fat<<endl;
	for(int i = 0; i<7; i++)
	{
		//如果数组数据为0,则跳过
		if(inode.i_zone[i] == 0)
			continue;
		
		//一个逻辑块最多存储64个目录项,循环读取64个目录项
		//其中前两项分别为 . 和 .. 
		for(int j = 0; j < 64; j++)
		{
			get_partition_logical_block(inode.i_zone[i]);
			//将逻辑块中的数据拷贝到目录项结构体
			memcpy((char*)&dir, &logical_block[j * sizeof(dir)], sizeof(dir));
			
			//如果是 .和..则继续循环
			if(j == 0 || j == 1)
				continue;
				
			//如果目录项中没有内容了则不再读取
			if(dir.inode == 0)
				break;
			
			//找到子目录/文件 
			if(dir.inode==id){
				/*
				因为要删除 1 个逻辑块中的16个字节的信息,
				首先要将该十六个字节内容置为空(避免要删除的信息在最后) 
				然后该逻辑块后面的内容一次向前移 
				*/
				dir.inode=0;
				memset(dir.name,0,sizeof(dir.name));
				memcpy(&logical_block[j * sizeof(dir)],(char*)&dir, sizeof(dir));
				//puts(dir.name);
				j++;
				while(j<64){
					memcpy((char*)&dir, &logical_block[j * sizeof(dir)], sizeof(dir));
					memcpy(&logical_block[(j-1) * sizeof(dir)],(char*)&dir, sizeof(dir));
					j++;
				}
				
				write_partition_logical_block(inode.i_zone[i]);
				return ;
			}
			
		}
	}
}

//对文件绝对路径下name文件执行删除操作 
void delete_file(string name){
	unsigned short id = find_root_inode(name,1);
	
	if(id==0){
		cout<<"error no file "<<name<<"\n";
		return ;
	}
	if(delete_file_inode_valid(id)){  //正式执行删除该文件操作 
		delete_inode_father(id);  //删除父节点(父目录)下的该文件信息 
		cout<<"success\n";
	}else{
		cout<<"no know error\n";
	}
	
}


/***************其他**************************/ 
//将字符类型转换二进制打印 
void print_char(char c){
	for(int i=7;i>=0;i--){
		if((c>>i)&1){
			cout<<"1 ";
		}
		else cout<<"0 ";
	}
}

//打印字符串(限制最大打印长度 
//(对于一些字符串可能会占满字符数组长度上限,
//导致正常打印末尾没有结束符'\0'从而导致访问越界) 
void puts(const char s[],const int ma){
	for(int i=0;i<ma;i++){
		if(s[i]=='\0')break;
		putchar(s[i]);
	}putchar('\n');
}

//char 强制类型转换 string 
//原因同上 
string new_string(const char *s,const int ma){
	string ans="";
	for(int i=0;i<ma;i++){
		if(s[i]=='\0')break;
		ans+=s[i];
	}
	return ans;
	
}

//加载 map<unsigned short,unsigned short> inode_father; 
void load_inode_father(unsigned short id, const char* name)
{
	int i, m, n;
	struct d_inode inode;
	struct dir_entry dir;
	
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(id) != 1)
		return;
		
	get_inode(id, &inode);
	
	unsigned short mode = inode.i_mode >> 12; //高4位存放的是文件类型
	//如果是目录文件
	if(mode == 4)
	{
		//循环读取i节点中的i_zones[]数组
		for(m = 0; m<7; m++)
		{
			//如果数组数据为0,则跳过
			if(inode.i_zone[m] == 0)
				continue;
			
			//一个逻辑块最多存储64个目录项,循环读取64个目录项
			//其中前两项分别为 . 和 .. 
			for(n = 0; n < 64; n++)
			{
				get_partition_logical_block(inode.i_zone[m]);
				//将逻辑块中的数据拷贝到目录项结构体
				memcpy((char*)&dir, &logical_block[n * sizeof(dir)], sizeof(dir));
				
				//如果是 .和..则继续循环
				if(n == 0 || n == 1)
					continue;
					
				//如果目录项中没有内容了则不再读取
				if(dir.inode == 0)
					break;
				//cout<<dir.inode<<" ";
				inode_father[dir.inode] = id;
				
				load_inode_father(dir.inode,dir.name);
			}
		}
	}
}


/**********************新建文件******************/
//申请一个位于i节点内的逻辑块 
unsigned short apply_inode_valid()
{

	for(unsigned short i=2;i<=sblock.s_ninodes;i++){
		if(is_inode_valid(i)!=1){
			update_inode_valid(i,1);
			//cout<<is_inode_valid(i)<<endl;
			return i;
		}
	}
	//申请失败,内存已满。 
	return 0;
}

//申请数据区逻辑块 
unsigned short apply_logical_valid(){
		for(unsigned short i=sblock.s_ninodes;i<=sblock.s_nzones;i++){
		if(is_logical_valid(i)!=1){
			update_logical_valid(i,1);
			//cout<<is_logical_valid(i)<<endl;
			return i;
		}
	}
	return 0;
}


//添加其父目录文件下的子文件 
bool add_inode_father(unsigned short fat,dir_entry chi){
	struct d_inode inode;
	struct dir_entry dir;
	
	
	if(is_inode_valid(fat) != 1)
		return 0;
	//fat=406;
	get_inode(fat, &inode);
	//cout<<fat<<endl;
	for(int i = 0; i<7; i++)
	{
		//如果数组数据为0,添加新的数据块 
		if(inode.i_zone[i] == 0){
			inode.i_zone[i] = apply_logical_valid();
			memset(logical_block,0,sizeof(logical_block));
			memcpy(&logical_block[2 * sizeof(chi)],(char*)&chi, sizeof(chi));
			write_partition_logical_block(inode.i_zone[i]);
			return 1;
		}
			
		//一个逻辑块最多存储64个目录项,循环读取64个目录项
		//其中前两项分别为 . 和 .. 
		for(int j = 0; j < 64; j++)
		{
			get_partition_logical_block(inode.i_zone[i]);
			//将逻辑块中的数据拷贝到目录项结构体
			memcpy((char*)&dir, &logical_block[j * sizeof(dir)], sizeof(dir));
			//if(j>12)for(int k=0;k<1024;k++)print_char(logical_block[k]);cout<<endl;
			//如果是 .和..则继续循环
			if(j == 0 || j == 1)
				continue;
				
			//如果目录项中没有内容了则不再读取
			
			if(dir.inode == 0){
				//dir_entry new_child = dir_entry(chi.inode,chi.name);
				//cout<<chi.inode<<" "<<j<<endl;
				//for(int k=0;k<4;k++)print_char(logical_block[j*2+k-2]);cout<<endl;
				//for(int k=0;k<sizeof(new_child);k++)logical_block[j*2+k]=((char*)& new_child)[k];
				memcpy(&logical_block[j * sizeof(chi)],(char*)& chi, sizeof(chi));
				
				//write_partition_logical_block(inode.i_zone[i]);
				//if(j>12)for(int k=0;k<1024;k++)print_char(logical_block[k]);cout<<endl;
				//if(j+1<64)memcpy(&logical_block[(j+1) * sizeof(dir)],(char*)&dir, sizeof(dir));
				write_partition_logical_block(inode.i_zone[i]);
				return 1;
			}
				
			
			
			
		}
	}
	cout<<"father_files is fulled\n";
	return 0;
} 


//修改文件大小 
bool update_size_file(unsigned short id,int file_size){
	struct d_inode inode;
	get_inode(id, &inode);
	if(file_size<=7){
		for(int i=0;i<file_size;i++){
			inode.i_zone[i]=apply_logical_valid();
		}
	}else if(file_size<=7+1024/2){
		for(int i=0;i<7;i++){
			inode.i_zone[i]=apply_logical_valid();
		}
		inode.i_zone[7]=apply_logical_valid();
		file_size-=7;
		memset(logical_block,0,sizeof(logical_block));
		unsigned short dete_id[512];
		for(int j = 0; j < file_size; j++){
			dete_id[j]=apply_logical_valid();
			//cout<<dete_id[j]<<endl; 
			//memcpy(&logical_block[j*sizeof(dete_id)], (char*)&dete_id, sizeof(dete_id));
			//print_char(dete_id[0]);cout<<endl;
			//cout<<"\t\t"<<j<<" ";for(int k=0;k<6;k++)print_char(logical_block[k]);cout<<endl;
			//write_partition_logical_block(inode.i_zone[7]);
		}
		
		memcpy(&logical_block[0], (char*)&dete_id[0], sizeof(dete_id[0])*file_size);
		//print_char(dete_id[0]);cout<<endl;
		//cout<<"\t\t"<<sizeof(dete_id[0])*file_size<<" ";for(int k=0;k<6;k++)print_char(logical_block[k]);cout<<endl;
		write_partition_logical_block(inode.i_zone[7]);
	}else if(file_size<=7+512+512*512){
		for(int i=0;i<7;i++){
			inode.i_zone[i]=apply_logical_valid();
		}
		inode.i_zone[7]=apply_logical_valid();
		file_size-=7;
		memset(logical_block,0,sizeof(logical_block));
		unsigned short dete_id[512];
		for(int j = 0; j < file_size; j++){
			dete_id[j]=apply_logical_valid();
			//cout<<dete_id[j]<<endl; 
			//memcpy(&logical_block[j*sizeof(dete_id)], (char*)&dete_id, sizeof(dete_id));
			//print_char(dete_id[0]);cout<<endl;
			//cout<<"\t\t"<<j<<" ";for(int k=0;k<6;k++)print_char(logical_block[k]);cout<<endl;
			//write_partition_logical_block(inode.i_zone[7]);
		}
		
		memcpy(&logical_block[0], (char*)&dete_id[0], sizeof(dete_id[0])*file_size);
		//print_char(dete_id[0]);cout<<endl;
		//cout<<"\t\t"<<sizeof(dete_id[0])*file_size<<" ";for(int k=0;k<6;k++)print_char(logical_block[k]);cout<<endl;
		write_partition_logical_block(inode.i_zone[7]);
		
		inode.i_zone[8]=apply_logical_valid();
		file_size-=(7+1024/2);
		memset(logical_block,0,sizeof(logical_block));
		for(int n1 = 0; n1 < (511+file_size)/512; n1++)
		{
			dete_id[n1]=apply_logical_valid();
			
		}
		memcpy(&logical_block[0],(char*)&dete_id[0] , sizeof(dete_id[0])*(511+file_size)/512);
		//print_char(dete_id[0]);cout<<endl;
		write_partition_logical_block(inode.i_zone[8]);
		
		
		for(int n1 = 0; n1 < (511+file_size)/512; n1++)
		{
			int ma_n2=512;
			if(n1==(511+file_size)/512-1){
				ma_n2=file_size%512;
			}
			memset(logical_block,0,sizeof(logical_block));
			unsigned short dete_id_2[512];
			for(int n2 = 0; n2 < ma_n2; n2++)
			{
				dete_id_2[n2]=apply_logical_valid();
			
			}
			memcpy(&logical_block[0],(char*)&dete_id_2[0] , sizeof(dete_id_2[0])*ma_n2);
			//print_char(dete_id[0]);cout<<endl;
			write_partition_logical_block(dete_id[n1]);
			
		}
		
	}else  return 0;
	write_inode(id, inode);
	return 1;
}

//i节点文件写入内存 
bool write_files_inode(unsigned short id,int type_file,int size_file){
	struct d_inode inode;
	get_inode(id, &inode);
	
	inode.i_mode=(type_file<<12);
	inode.i_uid=0;
	inode.i_size= size_file; 
	//inode.i_time=(long)time(NULL);
	inode.i_time=0;
	inode.i_gid=0;
	inode.i_nlinks=0;
	//cout<<(inode.i_mode>>12)<<endl;
	
	for(int i=0;i<9;i++)inode.i_zone[i]=0;
	//memset(inode.i_zone,0,sizeof(inode.i_zone));
	write_inode(id,inode);
	update_size_file(id,size_file);
	return 1;
}

//判断父目录下是否存在名为 child_name 的文件 
bool find_father_id_child_name(unsigned short id, string child_name)
{
	struct d_inode inode;
	struct dir_entry dir;
	
	//如果i节点号对应在i节点位图相应位的值为1,说明此i节点已使用
	//否则说明此i节点无用或已被删除,则直接返回
	if(is_inode_valid(id) != 1)
		return 0;
		
	get_inode(id, &inode);
	for(int m = 0; m<7; m++)
	{
		//如果数组数据为0,则跳过
		if(inode.i_zone[m] == 0)
			continue;
		for(int n = 0; n < 64; n++)
		{
			get_partition_logical_block(inode.i_zone[m]);
			//将逻辑块中的数据拷贝到目录项结构体
			memcpy((char*)&dir, &logical_block[n * sizeof(dir)], sizeof(dir));
			
			//如果是 .和..则继续循环
			if(n == 0 || n == 1)
				continue;
				
			//如果目录项中没有内容了则不再读取
			if(dir.inode == 0)
				break;
			
			if(new_string(dir.name,NAME_LEN)==child_name){
				return 1;
			}
		}
		
	}
	
	return 0;
}

//创建文件夹
bool built_files(string lur,string files_name){
	unsigned short father_id = find_root_inode(lur,1);//在father_id 节点目录下创建文件 
	if(father_id==0){
		return 0;
	}
	if(find_father_id_child_name(father_id,files_name)){
		cout<<" error: no build "<<files_name<<",  "<<files_name<<" was existed\n";
		return 0;
	} 
	unsigned short inode_id = apply_inode_valid();
	
	char name[NAME_LEN];memset(name,0,sizeof(name));
	for(int i=0;i<files_name.size();i++)name[i]=files_name[i];
	name[files_name.size()]='\0';
	dir_entry new_inode_files = dir_entry(inode_id,name);
	if(!add_inode_father(father_id,new_inode_files))return 0;
	write_files_inode(inode_id,4,0);
	
	inode_father[inode_id]=father_id;
	cout<<"success\n";
	return 1;
} 

//创建普通文件
bool built_file(string lur,string files_name,int file_size){
	unsigned short father_id = find_root_inode(lur,1);//在father_id 节点目录下创建文件 
	
	if(father_id==0){
		return 0;
	}
	if(find_father_id_child_name(father_id,files_name)){
		cout<<" error: no build "<<files_name<<",  "<<files_name<<" was existed\n";
		return 0;
	} 
	unsigned short inode_id = apply_inode_valid();
	
	char name[NAME_LEN];memset(name,0,sizeof(name));
	for(int i=0;i<files_name.size();i++)name[i]=files_name[i];
	name[files_name.size()]='\0';
	dir_entry new_inode_files = dir_entry(inode_id,name);
	if(!add_inode_father(father_id,new_inode_files))return 0;
	write_files_inode(inode_id,8,file_size);
	
	inode_father[inode_id]=father_id;
	cout<<"success\n";
	return 1;
}

//初始化函数 
void init(int argc, char* argv[]){
	
	int bit;
	struct d_inode* inode = (struct d_inode*)malloc(sizeof(struct d_inode));
	
	char* path = "harddisk.img";
	
	if(argc>1)path=argv[1];
	fd = fopen(path, "rb+");
	//fw = fopen(path, "wb");
	if(fd==NULL)
		printf("open file failed!\n");
		
	//读取分区表
	get_partition_table();
	//读取超级块
	get_super_block();
	
	//加载i节点逻辑块位图
	load_inode_bitmap();
	//加载数据逻辑块位图 
	load_logical_bitmap(); 
	//i节点位图的第一位对应文件系统的根节点
	//如果第一位为1,则打印根节点
	bit = is_inode_valid(1);
	if(bit == 1){
		
		print_inode(1, -1, "\\");
		load_inode_father(1,"\\");
	}
	else
		printf("root node lost!\n");
	cout<<"-----------------------------------\n";
}

//文件系统入口 
void solve(){
	string scan;
	string now_file;

	while(true){
		cout<<now_file<<"\/> ";
		cin>>scan;
		if(scan=="exit")break;
		if(scan=="print"){
			cin>>scan;
			print_file(now_file+"/"+scan);
		}else if(scan=="dir"){
			print_file(now_file);
		}else if(scan=="cd"){
			cin>>scan;
			
			if(find_root_inode(now_file,1)){
				now_file += "/"+scan;
				
			}else{
				cout<<"no file\n";
			}
		}else if(scan=="delete"){
			cin>>scan;
			delete_file(now_file+"/"+scan);
		}else if(scan=="build"){
			int type,file_size;
			cin>>scan;cin>>type;
			if(type==8){
				cin>>file_size;
				built_file(now_file,scan,file_size);
			}else if(type==4){
				built_files(now_file,scan);
			}else{
				cout<<"no built type file"<<endl;
			}
		}else{
			cout<<" not commond\n";
		}
		
	}
	
}
int main(int argc, char* argv[])
{
	//freopen("1.out","w",stdout);
	init(argc,argv);

	//solve();
	//print_file("/usr/src/linux-0.11.org/mm/memory.c");
	//print_file("/usr/root/hello.c");
	//delete_file("/usr/root/hello.c");
	//delete_file("/usr/root/shoe");
 	//built_files("/usr/root","dir");
	//print_file("/usr/root/dir");
	//built_file("/usr/root","file.txt",10);
	//print_file("/usr/root/file.txt");
	
	return 0;
}



全部评论

相关推荐

头像
不愿透露姓名的神秘牛友
04-08 00:50
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务