?? 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 + -