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

📄 unix文件模拟系统.cpp

📁 该模拟的UNIX文件系统应该有以下功能: 多级目录的结构
💻 CPP
📖 第 1 页 / 共 4 页
字号:
				dirnum++;
			}
			else
			{	printf( "<FILE>" );								// 普通文件  
				filenum++;
			}
				printf( "\t\t" );	
			// 显示读写执行权限  
			for( j = 0; j < 3; j++ )
			{   if( di_mode % 2 )
					printf( "r" );							// 读权限  
				else
					printf( "-" );
				di_mode = di_mode / 2;						
				if( di_mode % 2 )							// 写权限  
					printf( "w" );
				else
					printf( "-" );
				di_mode = di_mode / 2;
				if( di_mode % 2 )							// 执行权限  
					printf( "x" );
				else
					printf( "-" );
				di_mode = di_mode / 2;
			}
			printf( "	%d	%d	%d	%s\n",	
// 分别显示文件主uid,gid,文件大小和文件名  
				inode->i_uid, inode->i_gid, inode->i_size, dir.direct[i].d_name );
			iput( inode );
		}
	}
	printf( "\n		%d files\n", filenum);		// 显示文件数  
	printf( "		%d directories\n", dirnum);			// 显示目录数  
}
//创建目录函数:mkdir
void mkdir( char * dirname )
{	int i, dirid, dirpos;
	struct inode * inode;
	struct dir tempdir;
	struct direct buf[BLOCKSIZ / DIRECTSIZ];
	unsigned int block;
	dirid = namei( dirname );
	if( dirid == -1 )
	{	printf( "mkdir: cannot make directory '%s': No such file or directory\n", dirname );
		return;
	}
	if( dirid != NULL )
	{	printf( "mkdir: cannot make directory '%s': File exists\n", dirname );
		return;
	}
	inode = ialloc();
	dirid = inode->i_ino;
	if( pre_dinodeid == cur_path_inode->i_ino )	
// 如果所要创建的目录的父目录为当前目录  
	{
		dirpos = iname( dir, end_path_name );
		strcpy( dir.direct[dirpos].d_name, end_path_name );
		dir.direct[dirpos].d_ino = dirid;
		dir.size++;
	}
	else	// 所要创建的目录的父目录不是当前目录  
	{	tempdir = getdir( pre_dinodeid, " " );
		dirpos = iname( tempdir, end_path_name );
		strcpy( tempdir.direct[dirpos].d_name, end_path_name );
		tempdir.direct[dirpos].d_ino = dirid;
		tempdir.size++;
		putdir( pre_dinodeid, tempdir );
	}
	for( i = 0; i < BLOCKSIZ / DIRECTSIZ; i++ )      // 初始化缓冲区  
	{	buf[i].d_ino = 0;
		strcpy( buf[i].d_name, " " );
	}
	// 把新建的目录内容写入缓冲区  
	strcpy( buf[0].d_name, ".." );
	buf[0].d_ino = pre_dinodeid;
	strcpy( buf[1].d_name, "." );
	buf[1].d_ino = dirid;
	// 写磁盘i节点相关信息  
	inode->i_size = 2 * DIRECTSIZ;
	inode->i_number = 1;
	inode->i_mode = DEFAULTMODE | DIDIR;
	inode->i_uid = user[user_id].u_uid;
	inode->i_gid = user[user_id].u_gid;
	block = balloc();
	inode->i_addr[0] = block;
	//bwrite( block, buf );// 把缓冲区内容写入新分配的盘块中  
     fseek( fd, DATASTART + BLOCKSIZ * block, SEEK_SET );
	    fwrite( buf , 1, BLOCKSIZ, fd );

	iput( inode );
}

// 改变目录函数:chdir() 
void chdir( char * dirname )
{	unsigned int dirid;
	char buf[DIRSIZ];
	int i, len;
	dirid = namei( dirname );			// 获得当前目录的磁盘i节点号  
	if(( dirid == NULL ) || ( dirid == -1 ))			// 没有该目录  
	{	printf( "bash: %s: No such file or directory\n",dirname );
		return;
	}
	len = strlen( dirname );
	while( len )
	{	i = 0;
		while( len ) 
		{
			buf[i] = * dirname;
			if( buf[i] == '/' )
			{
				buf[i] = '\0';
				dirname++;
				len--;
				break;
			}
			i++;
			dirname++;
			len--;
		}
		if( !len )
			buf[i] = '\0';
		if( buf[0] == '\0' )
		{
			buf[0] = '/';
			buf[1] = '\0';
		}

		putdir( cur_path_inode->i_ino, dir );	// 把当前目录写回到磁盘  
		iput( cur_path_inode );
		dir = getdir( dirid, buf );		// 取得所要进入的目录的目录结构  
		cur_path_inode = iget( dirid );
		if( strcmp( buf, "/" ) == 0 )
			cur_dir_id = 0;
		else if(strcmp( buf, ".." ) == 0 )
		{if( cur_dir_id )
				cur_dir_id--;
		}
		else if( strcmp( buf, "." ) != 0 )
		{
			cur_dir_id++;
			strcpy( cur_direct[cur_dir_id].d_name, buf );
			cur_direct[cur_dir_id].d_ino = dirid;
		}
	}
}

// 删除目录函数:rmdir() 
void rmdir( char * dirname )
{
	int i, dirid;
	struct inode * inode;
	struct dir tempdir;
	struct direct buf[BLOCKSIZ / DIRECTSIZ];

	dirid = namei( dirname );
	if(( dirid == NULL ) || ( dirid == -1 ))	// 找不到该目录  
	{	printf( "rmdir: %s: No such file or directory\n", dirname );
		return;
	}
	inode = iget( dirid );
	if( !( inode->i_mode & DIDIR ))				// 不是目录  
	{	printf( "rmdir: %s: is not D irectory,can  not  delete\n", dirname );
		iput( inode );
		return;
	}
	if( !( access( inode ) & WRITE))				// 没有权限  
	{	printf( "bash: %s: Permission denied\n", dirname );
		iput( inode );
		return;
	}
	if( inode->i_size > 2 * DIRECTSIZ )			    // 目录非空  
	{   printf( "rmdir: %s: Directory not empty\n", dirname );
		iput( inode );
		return;
	}
	// 初始化缓冲区  
	for( i = 0; i < BLOCKSIZ / DIRECTSIZ; i++ )
	{   buf[i].d_ino = 0;
		strcpy( buf[i].d_name, " " );
	}
	// 如果删除的目录在当前目录下  
	if( pre_dinodeid == cur_path_inode->i_ino )
	{for( i = 0; i < dir.size; i++ )
		{	if( dir.direct[i].d_ino == dirid )
			break;
		}
		for( ; i < dir.size - 1; i++ )
		{
			dir.direct[i].d_ino =dir.direct[i + 1].d_ino;
			strcpy(dir.direct[i].d_name , dir.direct[i + 1].d_name);
		}
		dir.direct[i].d_ino = 0;
		strcpy( dir.direct[i].d_name, " " );
		dir.size--;
	}
	else	// 删除的目录不在当前目录下  
	{
		// 取得所删除目录的父目录  
		tempdir = getdir( pre_dinodeid, " " );
		for( i = 0; i < tempdir.size; i++ )       // 找到所要删除的目录  
		{
			if( tempdir.direct[i].d_ino == dirid )
				break;
		}
		for( ; i < tempdir.size - 1; i++ )           // 删除
		{   tempdir.direct[i].d_ino =tempdir.direct[i + 1].d_ino;
			strcpy(tempdir.direct[i].d_name ,tempdir.direct[i + 1].d_name);
		}
		tempdir.direct[i].d_ino = 0;			// 清空盘块号  
		strcpy( tempdir.direct[i].d_name, " " );			// 清空目录名  
		tempdir.size--;										// 父目录的目录数减1  

		putdir( pre_dinodeid, tempdir );				// 把父目录写回磁盘  
	}

	inode->i_number--;										// i节点联接计数减1  
	iput( inode );
}

//	获得指定的目录内容函数:dirgetput()	
struct dir getdir( unsigned int dinodeid, char * dirname )
{	struct inode * get_inode;
	struct dir dir;
	 unsigned int  i;
	get_inode = iget( dinodeid );
	if( get_inode->i_mode & DIREG )      // 该文件为普通文件而非目录文件 
	{
		printf( "bash: %s: 错误:不是目录,无法删除。\n", dirname );
		iput( cur_path_inode );
		exit(0);
	}
	// 该用户没有相应的权限,不能进入  
	if( !access( get_inode )
		&& dinodeid != ROOTDIR )
	{
		printf( "bash: %s: Permission denied\n", dirname );
		iput( get_inode );
		exit(0);
	}
	dir.size = get_inode->i_size / DIRECTSIZ;
	for( i = 0; i < DIRNUM; i++ )
	{
		strcpy( dir.direct[i].d_name, " " );
		dir.direct[i].d_ino = DIEMPTY;
	}
	// 读盘块内容  
	for( i = 0; i < dir.size / ( BLOCKSIZ / DIRECTSIZ ) + 1; i++ )
	
	{fseek( fd, DATASTART + BLOCKSIZ * get_inode->i_addr[i], SEEK_SET );
	    fwrite( &dir.direct[( BLOCKSIZ / DIRECTSIZ ) * i] , 1, BLOCKSIZ, fd );
	}

	iput( get_inode );
	return dir;
}

void putdir( unsigned int dinodeid, struct dir dir)     // 把目录内容回写到盘块函数 
{	struct inode * inode;
	unsigned int block;
	int i;
	inode = iget( dinodeid );
	for( i = 0; i < inode->i_size / BLOCKSIZ + 1; i++ )
		bfree( inode->i_addr[i] );
	for( i = 0; i < dir.size; i += BLOCKSIZ / DIRECTSIZ)
	{
		block = balloc();
		inode->i_addr[i] = block;
	fseek( fd, DATASTART + BLOCKSIZ * block, SEEK_SET );
	fwrite(&dir.direct[i] , 1, BLOCKSIZ, fd );	
	

       

	}
	inode->i_size = dir.size * DIRECTSIZ;
	iput( inode );
}

int format()  //命令format.c
{
	struct inode * inode;
	struct user tempuser[USERNUM];
	struct dinode dinode_buf;
	struct direct dir_buf[BLOCKSIZ / DIRECTSIZ];
	unsigned int block_buf1[BLOCKSIZ / sizeof( int )];
	char * buf;
	int i, j;
	fd = tmpfile();		// 建立文件  
	buf = (char * )malloc( 1024*1024 );			// 申请1M空间  
	if( buf == NULL )					// 申请不成功,返回  
	{
		printf( "\nThe system file can't be create!\n" );
		return 0;
	}
	fseek( fd, 0, SEEK_SET );
	fwrite( buf, 1, 1024*1024, fd );
	
	free ( buf );	// 设置磁盘i节点缓冲区,DIEMPTY表示空闲  
	dinode_buf.di_mode = DIEMPTY;
	fseek( fd, DINODESTART, SEEK_SET );
	for( i = 0; i < DINODEBLK * BLOCKSIZ / DINODESIZ; i++ )
	{
		fseek( fd, DINODESTART + DINODESIZ * i, SEEK_SET );
		fwrite( &dinode_buf, 1, sizeof( dinode_buf ), fd );
	}

	inode = iget( 0 );					// 0#磁盘i节点不用  
	inode->i_mode = DIEMPTY;
	iput( inode );

	inode = iget( 1 );					// 1#放用户名表  
	inode->i_number = 1;
	inode->i_mode = DIREG;
	inode->i_size = sizeof( struct user ) * USERNUM;
	inode->i_addr[0] = 1;

	// 用户imacih是超级用户  
	strcpy( tempuser[0].u_name, "user" );
	strcpy( tempuser[0].password, "password" );
	tempuser[0].u_default_mode = SUPERMODE;		// 超级用户  
	tempuser[0].u_gid = 1;
	tempuser[0].u_uid = 1;

	for( i = 1; i < USERNUM; i++ )
	{
		strcpy( tempuser[i].u_name, " " );
		tempuser[i].u_uid = 0;
	}
	fseek( fd, DATASTART + BLOCKSIZ * inode->i_addr[0], SEEK_SET );
	fwrite( tempuser, 1, inode->i_size, fd );
	iput( inode );

	inode = iget( 2 );					// 2#用于存储根目录  
	inode->i_number = 1;
	inode->i_mode = DEFAULTMODE | DIDIR;
	inode->i_size = 2 * DIRECTSIZ;
	inode->i_addr[0] = 2;
	strcpy( dir_buf[0].d_name, ".." );
	dir_buf[0].d_ino = 2;
	strcpy( dir_buf[1].d_name, "." );
	dir_buf[1].d_ino = 2;
	fseek( fd, DATASTART + BLOCKSIZ * inode->i_addr[0], SEEK_SET );
	fwrite( dir_buf, 1, inode->i_size, fd );
	iput( inode );

	// 初始化超级块  
	filsys.s_ninode = DINODEBLK * BLOCKSIZ / DINODESIZ - 3;	        // 空闲磁盘i节点数  
	filsys.s_nfree = FILEBLK - 3;					// 空闲文件块数  

	// 初始化空闲磁盘i节点堆栈  
	for( i = 0; i < NICINOD; i++ )
	{
		filsys.s_inode[i] = 3 + i;			// 从3#起空闲,前面3个已用  
	}
	filsys.s_pinode = 0;			// 当前空闲磁盘i节点指针  
	filsys.s_rinode = NICINOD + 3;	   // 下一准备装入空闲i节点栈的i节点号  

	// 初始化空闲盘块堆栈  

	// 把第1组空闲盘块放进空闲盘块堆栈  
	for( i = 0; i < NICFREE; i++ )
		filsys.s_free[i] = 3 + NICFREE - 1 - i;

	filsys.s_pfree = NICFREE - 1;		 // 当前空闲盘块堆栈指针  

	for( i = 3 + NICFREE * 2 - 1; i < FILEBLK; i += NICFREE )
	{
		for( j = 0; j < NICFREE; j++ )
		{
	// 往缓冲区写与成组链接法组织空闲盘块有关的信息:下一组盘块空闲块号与块数  
			block_buf1[j] = i - j;
		}
		block_buf1[NICFREE] = NICFREE;	// 该项记录本组的空闲盘块数  

		// 把缓冲区内容写到每组空闲盘块的最后一块中  
		

			fseek( fd, DATASTART + BLOCKSIZ * (i - NICFREE), SEEK_SET );
	fwrite(block_buf1, 1, BLOCKSIZ, fd );
	}

	// 最后一组空闲盘块可能不足NICFREE块,故需单独处理  
	i = i - NICFREE;
	for( j = 0; j < FILEBLK - i + 1; j++ )
		block_buf1[j] = FILEBLK - j;
	block_buf1[NICFREE] = FILEBLK - i + 1;		// 最末组的空闲盘块数  


	fseek( fd, DATASTART + BLOCKSIZ * i, SEEK_SET );
	fwrite(block_buf1, 1, BLOCKSIZ, fd );

	// 把超级块写入 block 1#  
	fseek( fd, BLOCKSIZ, SEEK_SET );
	fwrite( &filsys, 1, sizeof( struct filsys ), fd );

	return 1;
}
// 系统终止函数:halt()
void  halt()
{//	struct inode * inode;
	int i,j;                             	
// 保存当前目录 
	putdir(cur_path_inode->i_ino, dir);  	
// 释放所有用户打开表和系统打开表 
	for( i = 0; i < USERNUM; i++ )
		if( user[i].u_uid != 0 )
			for( j = 0; j < NOFILE; j++ )
				if( user[i].u_ofile[j] != SYSOPENFILE + 1 )
					close( j );
	// 保存超级块信息 
	fclose( fd );// 关闭文件,临时文件自动删除 
	printf( "Good bye! See you next time.\n" );
}
// 分配空闲磁盘i节点函数iallfre()
static struct dinode block_buf2[BLOCKSIZ / DINODESIZ];
struct inode * ialloc()
{	struct inode * temp_inode;
	unsigned int cur_di;
	int i;
	if( filsys.s_ninode == 0 )				// 没有空闲磁盘i节点  
	{	printf( "No leisure dinode!\n" );
		return NULL;
	}
	if( filsys.s_pinode == NICINOD )			// 空闲磁盘i节点栈空  
	{	cur_di = filsys.s_rinode;					
		if( filsys.s_ninode >= NICINOD )	
// 空闲磁盘i节点数可装满空闲i节点栈  
		{
			filsys.s_pinode = 0;
			// 把下一组磁盘i节点读进空闲磁盘i节点栈  
			while( filsys.s_pinode < NICINOD )
			{
				fseek (fd, DINODESTART + cur_di * DINODESIZ, SEEK_SET);
				fread (block_buf2, 1, BLOCKSIZ, fd);
				for( i = 0; ( i < BLOCKSIZ / DINODESIZ ) && ( filsys.s_pinode < NICINOD ); )
				{
					if( block_buf2[i].di_mode == DIEMPTY )	// 该磁盘i节点空闲  
					{
						filsys.s_inode[filsys.s_pinode] = cur_di;	// 把该i节点装入空闲栈  
						filsys.s_pinode++;	// 栈指针下移一位  
					}
					i++, cur_di++;
				}
			}
			filsys.s_pinode = 0;								// 置空闲i节点指针为0  
		}
		else			// 剩下的空闲磁盘i节点不能装满栈区  
		{
			// 计算出空闲栈指针装入i节点的第一个位置  
			filsys.s_pinode = NICINOD - filsys.s_ninode;
			while( filsys.s_pinode < NICINOD )
			{			
				fseek( fd, DINODESTART + cur_di * DINODESIZ, SEEK_SET );
				fread( block_buf2, 1, BLOCKSIZ, fd );
				for( i = 0; ( i < BLOCKSIZ / DINODESIZ ) && ( filsys.s_pinode < filsys.s_ninode ); )
				{
					if( block_buf2[i].di_mode==DIEMPTY )
					{
						filsys.s_inode[filsys.s_pinode] = cur_di;
						filsys.s_pinode++;
					}
					i++, cur_di++;
				}
			}
			filsys.s_pinode = NICINOD - filsys.s_ninode;
		}
	}

	// 分配内存i节点  
	temp_inode = iget( filsys.s_inode[filsys.s_pinode] );

	// 从磁盘i节点读取数据到内存i节点  
	fseek( fd, DINODESTART + filsys.s_inode[filsys.s_pinode] * DINODESIZ, SEEK_SET );
	fwrite( &temp_inode->i_number, 1, sizeof(struct dinode), fd );
	filsys.s_pinode++;							// 栈指针下移一位  
	filsys.s_ninode--;				// 空闲磁盘i节点又少了一个  

	return temp_inode;
}
// 回收磁盘i节点函数  
void ifree(unsigned int dinodeid)
{
	filsys.s_ninode++;							// 空闲磁盘i节点加1  
	if( filsys.s_pinode != 0 )					        // 空闲磁盘i节点栈未满  
	{
		// 直接回收  
		filsys.s_pinode--;
		filsys.s_inode[filsys.s_pinode] = dinodeid;
	}
	else					// 空闲磁盘i节点栈已满  
	{
		if( dinodeid < filsys.s_rinode )	// 磁盘i节点号小于铭记i节点号  
		{
			filsys.s_inode[0] = dinodeid;	// 回收  
			filsys.s_rinode = dinodeid;	
// 把新回收的i节点作为铭记i节点  
		}
	}
}

// 内存i节点分配函数:igetput
struct inode * iget( unsigned int dinodeid )
{	int inodeid;
	long addr;
	struct inode * temp, * newinode;
	inodeid = dinodeid % NHINO;			// 用Hash查找法查找内存i节点时用  
	// 用Hash法查找内存i节点  
	for( temp = hinode[inodeid].i_forw; temp != NULL; temp = temp->i_forw )								
	{	if( temp->i_ino == dinodeid )			        // 该文件已被打开  
		{	temp->i_count++;			// 引用计数加1  
			return temp;					// 可以退出  
		}
	}



	// 文件还没有被打开,以下步骤为之分配内存i节点  

	// 1. 计算该文件的磁盘i节点所在实际地址  

⌨️ 快捷键说明

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