📄 main.c
字号:
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, dirpos;
struct inode * inode, * pre_inode;
struct dir tempdir;
struct direct buf[BLOCKSIZ / DIRECTSIZ];
unsigned int block;
dirid = namei( dirname );
if(( dirid == NULL ) || ( dirid == -1 )) // 找不到该目录
{ textcolor(12);
printf( "rmdir: %s: 不存在你要操作的文件或目录\n", dirname );
textcolor(7);
return;
}
inode = iget( dirid );
if( !( inode->i_mode & DIDIR )) // 不是目录
{ textcolor(12);
printf( "rmdir: %s: 错误:不是目录,无法删除。\n", dirname );
textcolor(7);
iput( inode );
return;
}
if( !( access( inode ) & WRITE)) // 没有权限
{ textcolor(12);
printf( "bash: %s: 你没有权限完成此操作\n", dirname );
textcolor(7);
iput( inode );
return;
}
if( inode->i_size > 2 * DIRECTSIZ ) // 目录非空
{ textcolor(12);
printf( "rmdir: %s: 此目录不是空目录,不能删除\n", dirname );
textcolor(7);
iput( inode );
return;
}
printf("目录删除成功!\n\n");
// 初始化缓冲区
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;
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;
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;
int i;
get_inode = iget( dinodeid );
if( get_inode->i_mode & DIREG )// 该文件为普通文件而非目录文件
{
textcolor(12);
printf( "bash: %s: 错误:不是目录,无法删除。\n", dirname );
textcolor(7);
iput( cur_path_inode );
return;
}
// 该用户没有相应的权限,不能进入
if( !access( get_inode ) && dinodeid != ROOTDIR )
{
textcolor(12);
printf( "bash: %s: Permission denied\n", dirname );
textcolor(7);
iput( get_inode );
return;
}
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++ )
bread( get_inode->i_addr[i], &dir.direct[( BLOCKSIZ / DIRECTSIZ ) * i] );
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;
bwrite( block, &dir.direct[i] );
}
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, k;
fd = tmpfile(); // 建立文件
buf = (char * )malloc( 1024*1024 ); // 申请1M空间
if( buf == NULL ) // 申请不成功,返回
{
textcolor(12);
printf( "\nThe system file can't be create!\n" );
textcolor(7);
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, "root" );
strcpy( tempuser[0].password, "root" );
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; // 该项记录本组的空闲盘块数
// 把缓冲区内容写到每组空闲盘块的最后一块中
bwrite( i - NICFREE, block_buf1 );
}
// 最后一组空闲盘块可能不足NICFREE块,故需单独处理
i = i - NICFREE;
for( j = 0; j < FILEBLK - i + 1; j++ )
block_buf1[j] = FILEBLK - j;
block_buf1[NICFREE] = FILEBLK - i + 1; // 最末组的空闲盘块数
bwrite( i, block_buf1 );
// 把超级块写入 block 1#
fseek( fd, BLOCKSIZ, SEEK_SET );
fwrite( &filsys, 1, sizeof( struct filsys ), fd );
return 1;
}
// 系统终止函数:halt()
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 );// 关闭文件,临时文件自动删除
textcolor(13);
printf( "Good bye! See you next time.\n" );
textcolor(7);
}
// 分配空闲磁盘i节点函数iallfre()
static struct dinode block_buf2[BLOCKSIZ / DINODESIZ];
struct inode * ialloc()
{ struct inode * temp_inode;
unsigned int cur_di,temp;
int i;
if( filsys.s_ninode == 0 ) // 没有空闲磁盘i节点
{ textcolor(12);
printf( "No leisure dinode!\n" );
textcolor(7);
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节点所在实际地址
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; // 这里文件必须是一次寻址
if( pinode->i_size % BLOCKSIZ == 0 )
{
for( i = 0; i <= block_num;i++)
bfree(pinode->i_addr[i]);// 回收盘块
}
else
{
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
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 choice()
{
char reg_or_log;
AGAIN:
textcolor(8);
printf( "\nDo you want to register or login? (R/L) " );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -