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