📄 unix文件模拟系统.cpp
字号:
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 + -