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

📄 unix文件模拟系统.cpp

📁 该模拟的UNIX文件系统应该有以下功能: 多级目录的结构
💻 CPP
📖 第 1 页 / 共 4 页
字号:
	addr = DINODESTART + dinodeid * DINODESIZ;

	// 2. 为之分配一新内存i节点  
	newinode = ( struct inode * )malloc( sizeof( struct inode ));

	// 3. 把磁盘i节点内容复制到内存i节点上  
	fseek( fd, addr, SEEK_SET );
	fread( &( newinode->i_number ), DINODESIZ, 1, fd );

	// 4. 把内存i节点插入到Hash列表hinode上,以便查找  
	if( hinode[inodeid].i_forw != NULL )
	{
		newinode->i_forw = hinode[inodeid].i_forw;
		newinode->i_back = NULL;
		hinode[inodeid].i_forw->i_back = newinode;
		hinode[inodeid].i_forw = newinode;
	}
	else
	{	newinode->i_back = NULL;
		hinode[inodeid].i_forw = newinode;
		newinode->i_forw = NULL;
	}
	// 5. 设置内存i节点各数据  
	newinode->i_count = 1;
	newinode->i_ino = dinodeid;
	return newinode;					// 返回为之分配的内存i节点  
}

// 内存i节点回收函数:iput
void iput( struct inode * pinode )
{	long addr;
	unsigned int block_num,i;
	pinode->i_count--;						// 引用计数减1  
	if( pinode->i_count > 0 )			 	   // 还有进程打开该文件  
		return;							// 不用回收内存i节点  
	else
	{
		if( pinode->i_number != 0 )		 // 磁盘i节点连接计数不为0  
		{	// 修改磁盘i节点,即把内存i节点的数据写回到磁盘i节点  
			addr = DINODESTART + pinode->i_ino * DINODESIZ;
			fseek( fd, addr, SEEK_SET );
			fwrite( &pinode->i_number, 1, sizeof( struct dinode ), fd );
		}
		else
		{
			// 磁盘i节点连接计数为0,删除文件并回收盘块和磁盘i节点  
			block_num = pinode->i_size / BLOCKSIZ;		// 这里文件必须是一次寻址  
		
				for( i = 0; i <= block_num; i++ )
					bfree( pinode->i_addr[i] );	// 回收盘块  
			
			ifree( pinode->i_ino );				// 回收磁盘i节点  
		}

		// 回收内存i节点  
		if( pinode->i_back == NULL )
		{
			if( pinode->i_forw != NULL )
			{
				hinode[pinode->i_ino % NHINO].i_forw = pinode->i_forw;
				pinode->i_forw->i_back = NULL;
			}
			else 
				hinode[pinode->i_ino % NHINO].i_forw = NULL;
		}
		else
		{
			if( pinode->i_forw != NULL )
			{
				pinode->i_forw->i_back = pinode->i_back;
				pinode->i_back->i_forw = pinode->i_forw;
			}
			else
				pinode->i_back->i_forw = NULL;
		}
		free( pinode );
	}
}
//初始化函数:init.c
void init()
{	int i, j;
	// 从block 1# 中读取超级块信息  
	fseek( fd, BLOCKSIZ, SEEK_SET );
	fread( &filsys, 1, sizeof( struct filsys ), fd );
	// 初始化用于查找内存i节点的Hash列表  
	for( i = 0; i < NHINO; i++ )
		hinode[i].i_forw = NULL;
	// 初始化系统打开表  
	for( i = 0; i < SYSOPENFILE; i++ )
	{	sys_ofile[i].f_count = 0;
		sys_ofile[i].f_inode = NULL;
	}
	// 初始化用户信息  
	for( i = 0; i < USERNUM; i++ )
	{	user[i].u_uid = 0;
		user[i].u_gid = 0;
		for( j = 0; j < NOFILE; j++ )
			user[i].u_ofile[j] = SYSOPENFILE + 1;
	}
	// 取得当前路径名与当前目录  
	cur_path_inode = iget( ROOTDIR );
	dir = getdir( ROOTDIR, "/" );
}


void main()
{	char reg_or_log;
	cur_dir_id = 0;
   
 	if( fd != NULL )				// 文件已经存在,不用格式化  
	{	
		init();							// 读取磁盘数据  
	}
	else								// 文件已经存在,要进行格式化  
	{ if( format() == 0 )					        // 格式化  
		exit(0);						// 格式化不成功  
	
		init();							// 读取磁盘数据  
	}
AGAIN:
     printf( "请注册(R,r)\n登陆(L,l)\n");

	 while(1)
	{	cin>>reg_or_log;
		// 注册新用户  
		if(( reg_or_log == 'r' ) || ( reg_or_log == 'R' ))
		{
			reg();	
			goto AGAIN;
		}
		// 登陆已有用户  
		else if(( reg_or_log == 'l' ) || ( reg_or_log == 'L' ))
		{
		
			if( login() == 0)			 // 登陆不成功  
				goto AGAIN;
			break;
		}
	}
	strcpy(cur_direct[cur_dir_id].d_name, "/" );		// 当前路径名,"/"表示根目录  
	cur_direct[cur_dir_id].d_ino = ROOTDIR;	  // 当前路径的i节点号  
	  printf("             模拟UNIX文件系统的设计及实现                       \n");


   message();


	// 接受用户操作  
	while(1)
	{if( cmdexp() == 1 )			// 当用户quit时, cmdexp()返回1  
			break;
	}
	halt();							// 终止本文件系统  
}
//目录查找函数namei.c						 
 
char end_path_name[DIRSIZ];				// 路径最后的目录或文件名  
char * path;
int len;
int namei( char * name )
{	struct inode * inode;
	struct direct dir_buf[BLOCKSIZ / DIRECTSIZ];
	unsigned int i, j, id, dinodeid;
	pre_dinodeid = 0;
	path = name;
	len = strlen( name );
	getpath();
	if( end_path_name[0] == '\0' )			// 从根目录起  
	{	pre_dinodeid = ROOTDIR;
		dinodeid = ROOTDIR;
	}
	else if( strcmp( end_path_name, ".." ) == 0 )	        // 从上一级目录起  
	{if( cur_dir_id != 0 )
			id = cur_dir_id - 1;
		else id = 0;
		dinodeid = cur_direct[id].d_ino;
	}
	else						// 从当前目录起  
	{
		if( strcmp( end_path_name, "." ) == 0 )	// 当前目录  
			getpath();
		for( i = 0; i < dir.size; i++ )
		{	// 在当前目录中查找,当前目录已经读入内存  
			if(( !strcmp( dir.direct[i].d_name, end_path_name )) && ( dir.direct[i].d_ino != 0 ))
			{	dinodeid = dir.direct[i].d_ino;
				if( len == 0 )		// path搜索完毕  
				{	pre_dinodeid = cur_path_inode->i_ino;
					return dinodeid;
				}
				else			// path还没有搜索完  
					break;
			}
		}
		if( i == dir.size )				// 找不到  
		{if( len == 0 )					// 是最后路径  
		{  pre_dinodeid = cur_path_inode->i_ino;
			 return NULL;
			}
			else
				return -1;		// 找不到中间路径  
		}
	}

HERE:
	if( len )
	{   getpath();					// 再取得下一路径  
		inode = iget( dinodeid );
		for( i = 0; i < ( inode->i_size / DIRECTSIZ ) / ( BLOCKSIZ / DIRECTSIZ ); i++ )
		{
	fseek(fd, DATASTART + BLOCKSIZ * inode->i_addr[i], SEEK_SET );
	fread(dir_buf, 1, BLOCKSIZ, fd );



			for( j = 0; j < BLOCKSIZ / DIRECTSIZ; j++ )		// 找到  
				if( strcmp( dir_buf[j].d_name, end_path_name ) == 0 )
				{	iput( inode );
					pre_dinodeid = dinodeid;
					dinodeid = dir_buf[j].d_ino;
					goto HERE;
				}
			}
		fseek( fd, DATASTART + BLOCKSIZ * inode->i_addr[i], SEEK_SET );
		fread( dir_buf, 1, inode->i_size % BLOCKSIZ, fd );
		for( j = 0; j < ( inode->i_size % BLOCKSIZ ) / DIRECTSIZ; j++ )
		{	// 找到   
			if( strcmp( dir_buf[j].d_name, end_path_name ) == 0 )
			{	iput( inode );
				pre_dinodeid = dinodeid;
				dinodeid = dir_buf[j].d_ino;
				goto HERE;
			}
		}
		if( len == 0 )				// 路径最后找不到  
		{	pre_dinodeid = dinodeid;
			return NULL;
		}
		else
		{	pre_dinodeid = dinodeid;
			return -1;			// 路径中间找不到  
		}
	}
	return dinodeid;					// 可找到路径  
}

// 分配空闲目录结构  
unsigned short iname( struct dir dir, char * name )
{if( dir.size == DIRNUM )
	{	printf( "Current directory is full\n" );
		return 0;
	}
	return dir.size;
}
// 识别路径
void getpath()
{	int i;
	i = 0;
	while( len ) 
	{	end_path_name[i] = * path;
		if( end_path_name[i] == '/' )
		{	end_path_name[i] = '\0';
			path++;
			len--;
			break;
		}
		i++;
		path++;
		len--;
	}
	if( !len )
		end_path_name[i] = '\0';
}

//用户注册函数:reg()
void reg()
{	char regname[USERNAMESIZ + 50], regpsw[PWDSIZ], regpsw2[PWDSIZ];
	struct inode * inode;
	struct user tempuser[USERNUM];
	int i, newid;
	// 读取磁盘中的用户表  
	inode = iget( 1 );
	fseek( fd, DATASTART + BLOCKSIZ * inode->i_addr[0], SEEK_SET );
	fread( tempuser, 1, sizeof( struct user ) * USERNUM, fd );
	// 查找是否到达最大用户数  
	for( newid = 0; newid < USERNUM; newid++)
	{if( tempuser[newid].u_uid == 0 )
		break;
	}
	// 已达最大用户数,不能再注册  
	if( newid == USERNUM )
	{	printf( "已经达到8个用户了!\n" );
	
		return;
	}

	// 输入用户名, 按Esc键可重新输入, 还没有输入字符时,按回车取消注册  
	printf( "用户名:" );

	cin>>regname;

  // 输入密码  
	printf( "密码:" );

		cin>>regpsw;
	

	// 再次输入密码  
	printf( "再输入密码:" );

     cin>>regpsw2;

	// 检查用户名是否存在  
	for( i = 0; i < newid; i++ )
	{if( strcmp( tempuser[i].u_name, regname ) == 0 )
		{	printf( "该用户已经存在!\n" );
         
			return;
		}
	}

	// 检查两次输入的密码是否匹配
	if( strcmp( regpsw, regpsw2 ) != 0 )
	{	iput( inode );
		printf( "2次输入的密码不相同!\n" );
	
		return;
	}
	// 初始化注册用户信息  
	strcpy( tempuser[newid].u_name, regname );
	strcpy( tempuser[newid].password, regpsw );
	tempuser[newid].u_default_mode = NORMALMODE;
	tempuser[newid].u_gid = 1;
	tempuser[newid].u_uid = newid + 1;
	
// 保存新注册的用户信息于磁盘  
	fseek( fd, DATASTART + BLOCKSIZ * inode->i_addr[0], SEEK_SET );
	fwrite( tempuser, 1, sizeof( struct user ) * USERNUM, fd );
	iput( inode );
	printf( "注册成功!\n" );
}

// 用户登陆  
int login ()
{	char username[USERNAMESIZ + 50], userpsw[PWDSIZ];
	struct inode * inode;
	struct user tempuser[USERNUM];
	int i;
	// 输入用户名  	// 按Esc键可重新输入, 还没有输入字符时,按回车取消登陆  

	printf( "用户名:" );cin>>username;


	// 输入密码  
	printf( "密码: " );cin>>userpsw;
		

	inode = iget( 1 );
	fseek( fd, DATASTART + BLOCKSIZ * inode->i_addr[0], SEEK_SET );
	fread( tempuser, 1, sizeof( struct user ) * USERNUM, fd );

	// 检查是否存在该用户  
	for( i = 0; i < USERNUM; i++ )
	{if( strcmp( tempuser[i].u_name, username ) == 0 )
			break;
	}
	if( i == USERNUM )							// 没有该用户  
	{
		printf( "没有该用户!\n" );
	
	
	
		return 0;							// 登陆失败  
	}

	// 检查密码是否正确  

	// 密码不正确  
	if( strcmp( tempuser[i].password, userpsw ) != 0 )
	{
		printf( "密码不正确!\n" );
	
		return 0;							// 登陆失败  
	}

	// 正常登陆  
	user_id = i;
	strcpy( user[user_id].u_name, tempuser[i].u_name );
	user[user_id].u_uid = tempuser[i].u_uid;
	user[user_id].u_gid = tempuser[i].u_gid;
	user[user_id].u_default_mode = tempuser[i].u_default_mode;
	printf( "登陆成功!\n" );
	return 1;
}

// 用户退出函数  
int quit()
{
	int i;

	for (i = 0; i < NOFILE; i++)
		if (user[user_id].u_ofile[i] != SYSOPENFILE + 1)
			close( i );
	return 1;
}
//********************************************** 
//												 
//					syscall.c						 
//												 
//********************************************** 


extern char end_path_name[DIRSIZ];

// 建立文件  
int creat( char * pathname, unsigned short mode )
{
	unsigned int di_ith, di_ino;
	struct inode * inode, * pre_inode;
	struct dir tempdir;
	int i, j;

	di_ino = namei( pathname );

	if( di_ino == -1 )
	{
		printf( "No such directory or file\n" );
		return -1;
	}
	if( di_ino != NULL )				// 该文件名已经存在  
	{
		inode = iget( di_ino );			
		if( !( access( inode ) | WRITE ))		// 该文件不能写  
		{
			iput( inode );
			printf( "You have no access to creat\n" );
			return -1;
		}

		// 以下重写一个文件  

		// 释放原有文件的磁盘块  
		for( i = 0; i < inode->i_size / BLOCKSIZ + 1; i++ )
			bfree( inode->i_addr[i] );
		inode->i_size = 0;
		
		// 该文件已经打开  
		for( i = 0; i < SYSOPENFILE; i++ )
			if( sys_ofile[i].f_inode == inode )
			{
				sys_ofile[i].f_off = 0;
				for( j = 0; j < NOFILE; j++ )
				{
					if( user[user_id].u_ofile[j] == i )
						return j;
				}
			}

			// 该文件还没有打开  
		for( i = 0; i < NOFILE; i++ )
			if( user[user_id].u_ofile[i] == SYSOPENFILE + 1 )
			{
				user[user_id].u_uid = inode->i_uid;
				user[user_id].u_gid = inode->i_gid;
				for( j = 0; j < SYSOPENFILE; j++ )
					if( sys_ofile[j].f_count == 0 )
					{
						user[user_id].u_ofile[i] = j;
						sys_ofile[j].f_off = 0;
						sys_ofile[j].f_count = 1;
						sys_ofile[j].f_inode = inode;
						sys_ofile[j].f_flag = inode->i_mode;
					}
				return i;
			}
	}
	else													// 文件不存在,建立新文件  
	{
		pre_inode = iget( pre_dinodeid );
		if( !( access( pre_inode ) | WRITE ))	// 父目录不能写  
		{
			iput( pre_inode );
			printf( "You have no access to creat\n" );
			return -1;
		}
		inode = ialloc();
		inode->i_addr[0] = balloc();

		// 父目录为当前目录  
		if( pre_dinodeid == cur_path_inode->i_ino )
		{
			di_ith = iname( dir, end_path_name );
			strcpy( dir.direct[di_ith].d_name, end_path_name );
			dir.direct[di_ith].d_ino = inode->i_ino;
			dir.size++;
		}
		else			// 父目录不是当前目录  
		{
			tempdir = getdir( pre_dinodeid, " " );
			di_ith = iname( tempdir, end_path_name );
			strcpy( tempdir.direct[di_ith].d_name, end_path_name );
			tempdir.direct[di_ith].d_ino = inode->i_ino;
			tempdir.size++;
			putdir( pre_dinodeid, tempdir );
		}

		// 设置i节点信息  
		inode->i_mode = mode | DIREG;
		inode->i_uid = user[user_id].u_uid;
		inode->i_gid = user[user_id].u_gid;
		inode->i_size = 0;
		inode->i_number = 1;
		
		// 找空闲的系统打开表项  
		for( i = 0; i < SYSOPENFILE; i++ )
		{
			if( sys_ofile[i].f_count == 0 )
				break;
		}
		if( i == SYSOPENFILE )

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -