?? unix文件模擬系統.cpp
字號:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream.h>
#define BLOCKSIZ 512 /* 磁盤塊大小 */
#define MAXBLOCK 2048 /* 磁盤總塊數 */
#define SYSOPENFILE 40 /* 系統打開表最大數 */
#define DIRNUM 128 /* 文件數目 */
#define DIRSIZ 14 /* 文件名長度 */
#define USERNAMESIZ 12 /* 用戶名長度 */
#define PWDSIZ 12 /* 密碼長度 */
#define PWDNUM 32 /* 允許密碼個數 */
#define NOFILE 16 /* 用戶打開表最大數 */
#define NADDR 13 /* 物理塊號數 */
#define NHINO 64 /* 查找內存i節點的Hash表桶數 */
#define USERNUM 8 /* 允許的最大用戶數 */
#define DINODESIZ 64 /* 磁盤i節點大小 */
#define DINODEBLK 128 /* 磁盤i節點占用盤塊數 */
#define FILEBLK MAXBLOCK - DINODEBLK -2 /* 文件區占用磁盤塊數 */
#define NICFREE 50 /* 空閑塊堆棧可裝入的物理塊數 */
#define NICINOD 50 /* 空閑磁盤i節點堆棧可裝入的i節點數 */
#define DINODESTART 2 * BLOCKSIZ /* 磁盤i節點開始地址 */
#define DATASTART (2 + DINODEBLK) * BLOCKSIZ /* 文件區開始地址 */
#define DIEMPTY 000000 /* 空閑磁盤i節點 */
#define DIREG 001000 /* 普通文件 */
#define DIDIR 002000 /* 子目錄文件 */
#define UREAD 000001 /* 文件主"讀"權限 */
#define UWRITE 000002 /* 文件主"寫"權限 */
#define UEXE 000004 /* 文件主"執行"權限 */
#define GREAD 000010 /* 同組用戶"讀"權限 */
#define GWRITE 000020 /* 同組用戶"寫"權限 */
#define GEXE 000040 /* 同組用戶"執行"權限*/
#define OREAD 000100 /* 其它用戶"讀"權限 */
#define OWRITE 000200 /* 其它用戶"寫"權限 */
#define OEXE 000400 /* 其它用戶"執行"權限*/
#define READ 000001 /* 文件"讀打開"標志 */
#define WRITE 000002 /* 文件"寫打開"標志 */
#define EXICUTE 000004 /* 文件"執行"標志 */
/* 超級用戶權限,對所有文件可進行所有操作 */
#define SUPERMODE 000777
/* 一般用戶"默認"模式,對其它文件可"讀",對自己的文件可"寫"可"執行" */
#define NORMALMODE 000117
/* 文件或目錄的默認"模式,所有用戶均可"讀",文件主可"寫" */
#define DEFAULTMODE 000113
/* openmode */
#define O_RDONLY 000001 /* 只讀 */
#define O_WRONLY 000002 /* 只寫 */
#define O_RDWR 000003 /* 讀/寫 */
#define O_APPEND 010000 /* 讀/寫指針指到文件尾 */
#define O_TRUNC 020000 /* 如果文件存在,清空文件 */
#define O_CREAT 040000 /* 如果文件不存在,創建文件 */
#define ROOTDIR 2 /* 根目錄所在磁盤i節點號 */
#define SEEK_SET 0 /* fseek調用參數,指針指向文件首 */
/* 文件系統(內存i節點)數據結構 */
struct inode
{
struct inode * i_forw; /* 前向指針 */
struct inode * i_back; /* 后向指針 */
unsigned int i_ino; /* 磁盤i節點標志 */
unsigned int i_count; /* 引用計數 */
unsigned short i_number; /* 關聯文件數,當為0時,則刪除該文件 */
unsigned short i_mode; /* 文件屬性與存取權限 */
unsigned short i_uid; /* 文件主標識 */
unsigned short i_gid; /* 同組用戶標識 */
unsigned short i_size; /* 文件大小 */
unsigned int i_addr[NADDR]; /* 物理塊號 */
};
/* 磁盤i節點數據結構 */
struct dinode
{
/* 磁盤i節點的所有變量在內存i節點中都有相應的變量與之相適應 */
unsigned short di_number; /* 關聯文件數 */
unsigned short di_mode; /* 文件屬性與存取權限 */
unsigned short di_uid; /* 文件主標識 */
unsigned short di_gid; /* 同組用戶標識 */
unsigned short di_size; /* 文件大小 */
unsigned int di_addr[NADDR]; /* 物理塊號 */
};
/* 查找內存i節點的hash表數據結構 */
struct hinode
{
struct inode * i_forw; /* hash 表指針 */
};
/* 超級塊數據結構 */
struct filsys
{
unsigned int s_ninode; /* 空閑磁盤i節點數 */
unsigned int s_nfree; /* 空閑盤塊數 */
unsigned short s_pfree; /* 空閑盤塊指針 */
unsigned short s_pinode; /* 空閑磁盤i節點棧指針 */
unsigned int s_rinode; /* 銘記磁盤i節點,記錄下一組要裝入的磁盤i節點號 */
unsigned int s_free[NICFREE]; /* 空閑盤塊堆棧 */
unsigned int s_inode[NICINOD]; /* 空閑磁盤i節點堆棧 */
};
/* 目錄數據結構 */
struct direct
{
char d_name[DIRSIZ]; /* 文件名 */
unsigned short d_ino; /* 磁盤i節點號 */
};
#define DIRECTSIZ sizeof( struct direct ) /* 目錄結構長度 */
/* 目錄數據結構 */
struct dir
{
struct direct direct[DIRNUM]; /* 目錄項 */
unsigned short size; /* 當前目錄大小 */
};
/* 系統打開表數據結構 */
struct file
{
char f_flag; /* 文件操作標志 */
unsigned int f_count; /* 引用計數 */
struct inode * f_inode; /* 指向內存i節點 */
unsigned long f_off; /* 讀/寫指針 */
};
/* 用戶打開表數據結構 */
struct user
{
char u_name[USERNAMESIZ]; /* 用戶名,登陸時用 */
char password[PWDSIZ]; /* 用戶密碼,登陸時用 */
unsigned short u_default_mode; /* 用戶默認模式 */
unsigned short u_uid; /* 用戶標志 */
unsigned short u_gid; /* 用戶組標志 */
unsigned short u_ofile[NOFILE]; /* 用戶打開文件表 */
};
/* 下為全局變量 */
struct hinode hinode[NHINO]; /* 查找內存i節點的hash表 */
struct dir dir; /* 當前目錄(在內存中全部讀入) */
struct file sys_ofile[SYSOPENFILE]; /* 系統打開表 */
struct filsys filsys; /* 內存中的超級塊 */
struct user user[USERNUM]; /* 登陸用戶表 */
FILE *fd; /* 虛擬磁盤的文件指針 */
struct inode * cur_path_inode; /* 當前目錄路徑 */
int user_id; /* 當前用戶的ID */
struct direct cur_direct[NOFILE]; /* 路徑 */
unsigned short cur_dir_id; /* 當前目錄指針 */
unsigned short access( struct inode * inode );
unsigned int balloc();
void bfree( unsigned int block_num );
void bread( unsigned int ino, char * buf );
void bwrite( unsigned int ino, char * buf );
int cmdexp();
void chmod( char * pathname, char * modename );
void getcmd();
int clearbuf();
void _dir();
void mkdir( char * dirname );
void chdir( char * dirname );
void rmdir( char * dirname );
struct dir getdir( unsigned int dinodeid, char * dirname );
void putdir( unsigned int dinodeid, struct dir dir);
int format();
void halt();
struct inode * ialloc();
void ifree(unsigned int dinodeid);
struct inode * iget( unsigned int dinodeid );
void iput( struct inode * pinode );
void init();
void edlin( char * filename );
void list( char * filename );
int write( int fh, char * buf, unsigned int nbyte );
int read( int fh, char * buf, unsigned int nbyte );
void close( int cfd );
int login ();
void _delete( char * filename );
int quit();
void reg();
unsigned short iname( struct dir dir, char * name );
int namei( char * name );
void getpath();
unsigned int pre_dinodeid; // 所搜索路徑的父目錄i節點
void message()
{
printf("mkdir命令 功能:創建一個目錄 語法:mkdir dir-name\n");
printf("rmdir命令 功能:刪除一個目錄 語法:rmdir dir-name\n");
printf("cd 命令 功能:改變工作目錄 語法:cd [directory]\n");
printf("ls 命令 功能: 列出所有目錄與文件 語法:ls [目錄或是文件]\n");
printf("create命令 功能:創建一個文件 語法:create file-name\n");
printf("rm命令 功能:刪除不需要的文件 語法:rm file-name\n");
printf("cat命令 功能:顯示一個文件 語法:cat file-name\n");
printf("help命令 功能:幫助信息 語法:help\n");
printf("exit 命令 功能:退出程序 語法:exit\n");
}
// 用戶權限檢測函數:access()
unsigned short access( struct inode * inode )
{ unsigned short can = 0;
// 該用戶可讀檢測
if(( inode->i_mode & OREAD ) ||
(( inode->i_mode & GREAD ) &&
( user[user_id].u_gid == inode->i_gid )) ||
((inode->i_mode & UREAD) &&
( user[user_id].u_uid == inode->i_uid )))
can = can | READ;
// 該用戶可寫檢測
if(( inode->i_mode & OWRITE ) ||
(( inode->i_mode & GWRITE ) &&
(user[user_id].u_gid == inode->i_gid )) ||
(( inode->i_mode & UWRITE) &&
( user[user_id].u_uid == inode->i_uid )))
can = can | WRITE;
// 該用戶可執行檢測
if(( inode->i_mode & OEXE ) ||
(( inode->i_mode & GEXE ) &&
( user[user_id].u_gid == inode->i_gid )) ||
(( inode->i_mode & UEXE) &&
( user[user_id].u_uid == inode->i_uid )))
can = can | EXICUTE;
return can;
}
//空閑盤塊分配函數:balloc()
static unsigned int block_buf0[BLOCKSIZ];
unsigned int balloc()
{ unsigned int free_block, free_block_num;
unsigned int i;
if( filsys.s_nfree == 0 ) // 磁盤已滿,無空閑盤塊
{ printf( "Disk has no space\n" );
return -1;
}
free_block = filsys.s_free[filsys.s_pfree]; // 取得當前空閑盤塊
if( filsys.s_pfree == 0 ) // 已經是棧底
{
fseek( fd, DATASTART + BLOCKSIZ * filsys.s_free[filsys.s_pfree], SEEK_SET );
fread(block_buf0, 1, BLOCKSIZ, fd );
free_block_num = block_buf0[NICFREE]; // 讀取該空閑盤塊組的盤塊數
// 把盤塊組放到空閑盤塊號棧上
for( i = 0; i < free_block_num; i++ )
filsys.s_free[i] = block_buf0[i];
filsys.s_pfree = free_block_num - 1; // 指針指向棧頂
}
else
filsys.s_pfree--; // 棧指針下移一位
filsys.s_nfree--; // 空閑盤塊少1
return free_block; // 返回空閑盤塊號數
}
// 空閑盤塊回收函數:bfree
void bfree( unsigned int block_num )
{ int i;
filsys.s_pfree++; // 棧指針上移一位
if( filsys.s_pfree == NICFREE ) // 空閑盤塊堆棧已滿
{ block_buf0[NICFREE] = NICFREE;
// 空閑盤塊堆棧的盤塊數NICFREE記入緩沖區
for( i = 0; i < NICFREE; i++ )
block_buf0[i] = filsys.s_free[i];
// 把空閑盤塊數據寫入緩沖區
filsys.s_pfree = 0; // 棧指針指向棧底
fseek( fd, DATASTART + BLOCKSIZ * block_num, SEEK_SET );
fwrite( block_buf0 , 1, BLOCKSIZ, fd );
}
filsys.s_free[filsys.s_pfree] = block_num; // 回收盤塊
filsys.s_nfree++; // 空閑盤塊多1
}
// 讀相應盤塊號的數據函數:bread
void bread( unsigned int ino, char * buf )
{ fseek( fd, DATASTART + BLOCKSIZ * ino, SEEK_SET );
fread( buf, 1, BLOCKSIZ, fd );
}
// 寫相應盤塊號的數據函數:bwrite
void bwrite( unsigned int ino, char * buf )
{
fseek( fd, DATASTART + BLOCKSIZ * ino, SEEK_SET );
fwrite( buf, 1, BLOCKSIZ, fd );
}
// 命令解釋層函數cmdexp()
char input_buf[20]; //命令行輸入緩沖區
int over; //命令行結束標記
int cmdexp()
{ char buf[5];
over = 0;
// 顯示命令提示行
printf("[%s@localroot]#", user[user_id].u_name, cur_direct[cur_dir_id].d_name );
// 讀取用戶輸入
getcmd();
// 顯示當前目錄
if(strcmp( input_buf, "ls" ) == 0 )
{ _dir();
clearbuf();
return 0;
}
// 改變當前目錄
if (strcmp( input_buf, "cd" ) == 0 )
{ getcmd();
chdir( input_buf );
clearbuf();
return 0;
}
// 創建目錄(建立子目錄)
if( strcmp( input_buf, "mkdir" ) == 0 )
{
if( over )
{ printf( "mkdir: too few arguments\n" ); // mkdir命令參數不足
clearbuf();
return 0;
}
getcmd();
if( input_buf[0] == '\0' )
{ printf( "mkdir: too few arguments\n" );
clearbuf();
return 0;
}
mkdir( input_buf );
while( !over )
{
getcmd();
if( input_buf[0] != '\0' )
mkdir( input_buf );
}
clearbuf();
return 0;
}
// 刪除目錄
if( strcmp( input_buf, "rmdir" ) == 0 )
{
if( over )
{ printf( "rmdir: too few arguments\n" );
clearbuf();
return 0;
}
getcmd();
if( input_buf[0] == '\0' )
{ printf( "rmdir: too few arguments\n" );
clearbuf();
return 0;
}
rmdir( input_buf );
while( !over )
{ getcmd();
if( input_buf[0] != '\0' )
rmdir( input_buf );
}
clearbuf();
return 0;
}
// 顯示文件
if(strcmp( input_buf, "cat" ) == 0 )
{if( over )
{ printf( "list: too few arguments\n" );
clearbuf();
return 0;
}
getcmd();
if( input_buf[0] == '\0' )
{ printf( "list: too few arguments\n" );
clearbuf();
return 0;
}
list( input_buf );
while( !over )
{ getcmd();
if( input_buf[0] != '\0' )
list( input_buf );
}
clearbuf();
return 0;
}
// 刪除文件
if( strcmp( input_buf, "rm" ) == 0 )
{if( over )
{ printf( "delete: too few arguments\n" );
clearbuf();
return 0;
}
getcmd();
if( input_buf[0] == '\0' )
{ printf( "delete: too few arguments\n" );
clearbuf();
return 0;
}
_delete( input_buf );
while( !over )
{ getcmd();
if( input_buf[0] != '\0' )
_delete( input_buf );
}
clearbuf();
return 0;
}
// 建立新文件并編輯
if( strcmp( input_buf, "create" ) == 0 )
{ getcmd();
edlin( input_buf );
clearbuf();
return 0;
}
// 改變目錄或文件屬性
if( strcmp( input_buf, "chmod" ) == 0 )
{ getcmd();
strcpy( buf, input_buf );
getcmd();
chmod( input_buf, buf );
clearbuf();
return 0;
}
if( strcmp( input_buf, "exit" ) == 0 )
{ quit();
clearbuf();
return 1;
}
if( strcmp(input_buf, "help" ) == 0 )
{
message();
clearbuf();
return 0;
}
// 找不到該命令
if( input_buf[0] != '\0' )
{
printf( "%s: command not found\n", input_buf );
clearbuf();
return 0;
}
return 0;
}
// 取得命令函數:getcmd()
void getcmd()
{ int i;
i = 0;
// 取得命令
while( !over )
{ input_buf[i] = getchar();
if( input_buf[i] == ' ' )
{ if( i == 0 ) // 命令行的開始是空格,應舍去
i--;
else
{
input_buf[i]='\0';
break;
}
}
else
if( input_buf[i] == '\n' )
{
over = 1;
input_buf[i]='\0';
break;
}
i++;
}
}
// 清空緩沖區
int clearbuf()
{ while( !over )
{ if( getchar() =='\n' )
break;
}
return 0;
}
//顯示目錄函數dir()
extern char end_path_name[DIRSIZ]; // 最后路徑名字
void _dir()
{
unsigned int di_mode;
int i, j, filenum, dirnum;
struct inode * inode;
filenum = 0; // 文件計數
dirnum = 0; // 目錄計數
printf("CURRENT DIRECTORY :\n" );
printf("<DIRECTORY||FILE> access uid gid size name\n" );
for( i = 2; i < dir.size; i++ )
{
if( dir.direct[i].d_ino != DIEMPTY )
{ inode = iget( dir.direct[i].d_ino );
di_mode = inode->i_mode;
if( di_mode & DIDIR )
{ printf( "<DIRECTORY>" ); // 目錄文件
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -