模拟的多级文件系统

模拟的多级文件系统,先申请一个100M的大文件作为模拟磁盘,然后在这个模拟磁盘上来实现文件系统的各类功能。
编译环境:ubuntu6.06+gcc
放在VC下编译则需要自己写getpass函数即可。

#include<iostream>
#include<stdio.h>
#include<string>
#include<stdlib.h>
#include<bitset>
#include<time.h>
#define DEV_SIZE    (1024*1024*100)
#define BLOCK_SIZE    1024  //一个块的大小定义为1k
#define DIR_NUM        5120
#define BLOCK_NUM    (5120*16)
#define INODE_NUM    5120
#define USER_NUM    16  //MAX NUMber of users
#define NAME_LEN    16  //文件名/用户名的长度
#define PSD_LEN        16  //密码长度
#define FILE_BLOCKS    16  //每个文件最多占用16个磁盘块
#define MIX_UNIT    8   //最小单元以字节计
#define DIR            1   //表示要创建的是目录
#define FE        0   //表示要创建的是文件
#define ROOT        1    //表示创建位置为根目录下
#define CURENT        0    //表示创建位置为当前目录下
using namespace std;
struct time_info{          //时间结构
    short year;
    short month;
    short day;
    short hour;
    short min;
};
struct dirItem{          //目录项结构
    int number;
    int inode_num; //所对应的的I结点号
    bool dir_or_file;       //true 表示目录,false表示文件
    char name[NAME_LEN];     //目录名称或文件名
    int parent,son,brother;           //用于在磁盘中保存目录的层次结构
    struct dirItem *p_parent,*p_son,*p_brother;    //同样是表示目录间的层次结构,主要用于在内存中的操作
    };
struct inode{          //I结点结构
    int number;  //I节点号
    short mode;  //文件的rwx权限
    char user_name[NAME_LEN]; //文件所属用户
    char user_group;  //用户所在组
    int file_length;  //文件长度,以字节计
    time_info file_creat;   //文件创建时间
    time_info file_edit;    //文件最后编辑时间
    short blocks;     //记录文件存储占用的存储块
    int block[FILE_BLOCKS];    //文件存储用到的块,目前还不支持间接块的使用
};
struct user_info{   //用户信息
    bool flag;  //用户的有效性标识,可用于遍历用户
    char name[NAME_LEN];
    char group; //用户所在组,分两个组,root和user
    int my_dir;  //表示用户目录
    char password[PSD_LEN]; //用户密码
    };
struct sup_blk{            //super block
    int num_of_users;            //记录用户的数目
    user_info users[USER_NUM];   //所有用户的信息
    int num_of_files;  //记录文件系统中文件的总数
    bool dirs[DIR_NUM];       //true 表示该目录项可用,false表示不可用 
    bool blocks[BLOCK_NUM];  //TRUE 表示该块可用,false表示该块不可用 
    bool inodes[INODE_NUM];  //TRUE 表示该I结点可用,false表示该结点不可用
    dirItem dir_items[BLOCK_NUM];   //把目录项的所有内容放到超级块中,以便到时将目录项读入内存建立目录层次
    int first_inode;         //表示第一个inode结点的相对地址
    int first_block;         //第一个用于存储文件的磁盘块的相对地址
};
static sup_blk *super_block;          //全局变量,指向超级块
static FILE *fp;                      //文件指针
static dirItem *head_dir,*dir_active;       //head_dir指向根目录的指针,根目录固定放在dir_items[0]处,dir_active指向当前工作目录
static user_info *user_active;              //当前活跃的用户


class BlockControl
{
public:
    BlockControl(void);
    ~BlockControl(void);
    void Bread(int num);    //读磁盘块,直接输出,参数为磁盘块号          
    void Brelse(int num);    //释放磁盘块,注意还要改写bitmap,最好格式化一下
    void Bwrite(char *buf,int num);    //写第num块,同时记得设置位示图
    int Bwrite(char *buf);        //写块,返回块号同时记得设置位示图
    int is_free(bool *bitmap,int num);  //查找各类位图中的空闲区域,参数num为最大偏移量若没找到,则返回-1
    void set_busy(bool *bitmap,int num); //将对应的区域标志为被占用
    void set_free(bool *bitmap,int num);   //设置为空闲
private:
    int fb;       //super_block->first_block
    char *samp;
};

class FileControl
{
public:
    FileControl(void);
    ~FileControl(void);

    /*建目录或文件,第一个参数为名称,第二个表示创建的是目录1/文件0,*
    *第三个表示位置(根1/当前目录0下),同时还得加入到目录项树中去*/
    int creat_df(char *name,bool dir,bool root);  
    void add_user(user_info *user_new);   //将新建的用户复制到超级块中去
    int find(string name,bool dir);        //查找文件/目录,dir为true时表示目录,为false是表示文件,返回文件或目录所在的目录项编号
    void del(int num);    //删除文件/或目录,参数为对应的目录项编号
    void read_file(int num);    //读文件,参数为对应的目录项编号
    void write_file(string &str,int num);  //向磁盘块里写入添加的信息,从最后一块开始写,参数为目录项编号
private:
    BlockControl bc;   //磁盘块控制
    void ins_dir(dirItem *posi,dirItem *dir_for_ins);
        //将dir_for_ins插入到where的同一级目录中,要进行适当的排序,目录放在前面,文件放在后面
    void gettime(time_info *time);  //获取时间函数
    void cleartime(time_info *time);
};

enum ORDER{CREAT=0,READ,WRITE,DEL,MKDIR,RMDIR,CD,LS,PWD,NEW,SHOW,HELP,LOGOUT,EXIT};
class ICmd {
public:
    ICmd(void);
    ~ICmd(void);
    void show_menu(void);
    void get_order(void);       //接收命令
    void Creat(string filename);  //创建文件
    void Read(string filename);
    void Write(string filename);
    void Del(string filename);
    //void Save(void);              //保存当前编辑的文件,其实可以放到下一层
    void CreatDir(string name);   //创建目录
    void DelDir(string name);    //删除目录
    void Cd(string name);         //参数分几种:..上一级目录,~用户目录,/绝对路径目录,不带/表示直接下一级目录
    void Ls(void);      //列出目录和文件
    void Pwd(void);        //列出用户当前所在的路径
    void NewUser(void);   //增加新用户
    void Show(void);      //列出所有的用户信息
    void Help(void);      //列出帮助信息
    void Logout(void);    //登出,准备换用户名登录
    void Exit(void);      //退出文件系统
private:
    FileControl fc;
    char order[10],param[NAME_LEN];   //命令和参数
    bool logout_flag;      //true 表示登出
    bool exit_flag;        //表示退出文件系统
    void pwd(dirItem *p);  //递归显示路径
    void init_fs(void);    //初始化文件系统
    void init_fs_first(void); //第一次使用文件系统
    void end_fs(void);     //结束文件系统时的一些收尾工作
    int check_user(char *name,char *password); //检查用户是否合法,合法返回用户编号,否则返回-1
    int check_order(void);//检查命令,以整数形式返回命令
    void cr_dir_tree(dirItem *head);  //建目录树

};



BlockControl::BlockControl(void)
{
    char *samp=new char[BLOCK_SIZE];
    for(int i=0;i<BLOCK_SIZE;i++)
        *(samp+i)='/0';
}
BlockControl::~BlockControl(void)
{
    delete [] samp;
}
void BlockControl::Bread(int num)    //读磁盘块,直接输出里面的内容
{
   
    char buf2[BLOCK_SIZE];
    fseek(fp,(super_block->first_block)+num*sizeof(char)*BLOCK_SIZE,SEEK_SET);
    fread(buf2,sizeof(char)*BLOCK_SIZE,1,fp);
    cout<<buf2;
}
void BlockControl::Brelse(int num)         //释放块
{
    fseek(fp,(super_block->first_block)+num*sizeof(char)*BLOCK_SIZE,SEEK_SET);
    fwrite(samp,sizeof(char)*BLOCK_SIZE,1,fp);
    set_free(super_block->blocks,num);
}
void BlockControl::Bwrite(char *buf,int num)
{
    fseek(fp,(super_block->first_block)+num*sizeof(char)*BLOCK_SIZE,SEEK_SET);
    fwrite(buf,sizeof(char)*BLOCK_SIZE,1,fp);
    set_busy(super_block->blocks,num);
}
int BlockControl::Bwrite(char *buf)
{
    int num=is_free(super_block->blocks,BLOCK_NUM);
    fseek(fp,(super_block->first_block)+num*sizeof(char)*BLOCK_SIZE,SEEK_SET);
    fwrite(buf,sizeof(char)*BLOCK_SIZE,1,fp);
    set_busy(super_block->blocks,num);
    return num;
}
int BlockControl::is_free(bool *bitmap,int num)
{
    int no;
    for(no=0;no<num;no++)
        if(*(bitmap+no)) return no;
    return -1;
}
void BlockControl::set_busy(bool *bitmap,int num)
{
    *(bitmap+num)=false;
}
void BlockControl::set_free(bool *bitmap,int num)
{
    *(bitmap+num)=true;
}


FileControl::FileControl(void)
{
}

FileControl::~FileControl(void)
{
}

void FileControl::gettime(time_info *stime){  //获取时间函数
    tm *tim;   //定义tm结构的变量tim
    time_t end;//=time_info();
    end=time((time_t *)NULL);
    tim=localtime(&end);
    stime->year=1900+tim->tm_year;
    stime->month=1+tim->tm_mon;
    stime->day=tim->tm_mday;
    stime->hour=tim->tm_hour;
    stime->min=tim->tm_min;
    return;
}

void FileControl::read_file(int num)
{
    dirItem *tmp;
    tmp=&((super_block->dir_items)[num]);
    inode *tmp_inode=new inode;
    fseek(fp,super_block->first_inode+sizeof(inode)*(tmp->inode_num),SEEK_SET);
    fread(tmp_inode,sizeof(inode),1,fp);
    for(int i=0;i<tmp_inode->blocks;i++)
        bc.Bread((tmp_inode->block)[i]);    //读磁盘块函数,直接输出
    cout<<endl;
    delete tmp_inode;
}
void FileControl::add_user(user_info *user_new)   //将新建的用户复制到超级块中去
{
    int i;
    for(i=0;i<super_block->num_of_users&&(super_block->users)[i].flag;i++);
    (super_block->users)[i].flag=true;
    (super_block->users)[i].group=user_new->group;
    (super_block->users)[i].my_dir=user_new->my_dir;
    strcpy((super_block->users)[i].name,user_new->name);
    strcpy((super_block->users)[i].password,user_new->password);
}
int  FileControl::creat_df(char *name,bool dir,bool root)
/*建目录或文件,第一个参数为名称,第二个表示创建的是目录1/文件0,*
    *第三个表示位置(根1/当前目录0下),同时还得加入到目录项树中去*/
{
    int num_dir=bc.is_free(super_block->dirs,DIR_NUM);
    if(num_dir==-1){
        cout<<"找不到空闲的目录项,退出"<<endl;
        return -1;
    }
    bc.set_busy(super_block->dirs,num_dir);        //设置该目录项已经被占用
    dirItem *tmp_dir=&((super_block->dir_items)[num_dir]);
    int num_inode=bc.is_free(super_block->inodes,INODE_NUM);  //寻找空闲的I节点
    if(num_inode==-1){
        cout<<"找不到空闲的I节点,退出"<<endl;
        return -1;
    }
    bc.set_busy(super_block->inodes,num_inode);           //设置该I节点被占用
    tmp_dir->inode_num=num_inode;       //设置为该目录项对应的I节点
    if(dir)    tmp_dir->dir_or_file=true;    //表示目录
    else {
        tmp_dir->dir_or_file=false;            //表示文件,初步设置i节点
        inode *tmp_inode=new inode;
        //tmp_dir->dir_or_file=false;
        fseek(fp,super_block->first_inode+num_inode*(sizeof(inode)),SEEK_SET);
        fread(tmp_inode,sizeof(inode),1,fp);
        tmp_inode->mode=0755;
        strcpy(tmp_inode->user_name,user_active->name);
        tmp_inode->user_group=user_active->group;
        gettime(&(tmp_inode->file_creat));
        fseek(fp,super_block->first_inode+num_inode*(sizeof(inode)),SEEK_SET);
        fwrite(tmp_inode,sizeof(inode),1,fp);
        delete tmp_inode;
    }
    strcpy(tmp_dir->name,name);
    if(root)    ins_dir(head_dir,tmp_dir);   //若该文件/目录建在根目录下
    else    ins_dir(dir_active,tmp_dir);                   //若该文件/目录建在当前目录下
    return num_dir;
}
void FileControl::cleartime(time_info *st)
{
    st->year=0;
    st->month=0;
    st->day=0;
    st->hour=0;
    st->min=0;
}
void FileControl::del(int num)        //删除目录或文件,参数为目录项的编号
{
    dirItem *tmp_dir=&((super_block->dir_items)[num]);
    if(tmp_dir->inode_num!=-1){
        inode *tmp_node=new inode;
        fseek(fp,super_block->first_inode+tmp_dir->inode_num*sizeof(inode),SEEK_SET);
        fread(tmp_node,sizeof(inode),1,fp);
        for(short int i=0;i<tmp_node->blocks;i++){
            bc.Brelse((tmp_node->block)[i]);
            (tmp_node->block)[i]=-1;
        }
        tmp_node->blocks=0;
        tmp_node->file_length=0;
        tmp_node->mode=0777;
        strcpy(tmp_node->user_name,"");
        tmp_node->user_group='/0';
        cleartime(&(tmp_node->file_creat));//将时间清为零
        cleartime(&(tmp_node->file_edit));
        fseek(fp,super_block->first_inode+tmp_dir->inode_num*sizeof(inode),SEEK_SET);
        fwrite(tmp_node,sizeof(inode),1,fp);
        delete tmp_node;
        bc.set_free(super_block->inodes,tmp_dir->inode_num);
        tmp_dir->inode_num=-1;
    }
    //下面开始将该目录项从链表中删除
    dirItem *father,*son;
    if(tmp_dir==dir_active->p_son){ //当tmp_dir 是其第一个子结点时
        son=tmp_dir->p_brother;
        dir_active->p_son=son;
        if(son!=NULL) dir_active->son=son->number;
        else dir_active->son=-1;
    }
    else {
        for(father=dir_active->p_son;father;father=father->p_brother){
            if(father->p_brother==tmp_dir) break;
        }
        son=tmp_dir->p_brother;
        father->p_brother=son;
        if(son!=NULL) father->brother=son->number;
        else father->brother=-1;
    }
    //删除完毕,下面进行必要的清尾工作
    strcpy(tmp_dir->name,"");
    tmp_dir->p_parent=NULL; tmp_dir->parent=-1;
    tmp_dir->p_brother=NULL; tmp_dir->brother=-1;
    tmp_dir->p_son=NULL;    tmp_dir->son=-1;
    bc.set_free(super_block->dirs,tmp_dir->number);
}
int FileControl::find(string name, bool dir)
//在当前目录下查找文件/目录,dir为true时表示目录,为false是表示文件,返回文件或目录所在的目录项编号
{
    dirItem *tmp_dir=dir_active->p_son;
    for(;tmp_dir!=NULL;tmp_dir=tmp_dir->p_brother)
        if(tmp_dir->dir_or_file==dir&&string(tmp_dir->name)==name)
            return tmp_dir->number;
    return -1;     //当当前目录下面为空时
}
void FileControl::ins_dir(dirItem *posi,dirItem *dir_for_ins)
//将dir_for_ins插入到where的同一级目录中,要进行适当的排序,目录放在前面,文件放在后面
{
    dirItem *tmp_dir1,*tmp_dir2;
    tmp_dir1=posi->p_son;
    dir_for_ins->p_parent=posi;    dir_for_ins->parent=posi->number;
    if(tmp_dir1==NULL){
        posi->p_son=dir_for_ins;    posi->son=dir_for_ins->number;
        //dir_for_ins->p_parent=posi;    dir_for_ins->parent=posi->number;
        dir_for_ins->p_brother=NULL;    dir_for_ins->brother=-1;
        dir_for_ins->p_son=NULL;    dir_for_ins->son=-1;
        return;
    }
    else if(tmp_dir1->p_brother==NULL){
        if(tmp_dir1->dir_or_file){
            tmp_dir1->p_brother=dir_for_ins;   tmp_dir1->brother=dir_for_ins->number;
            //dir_for_ins->p_parent=tmp_dir1;   dir_for_ins->parent=tmp_dir1->number;
            dir_for_ins->p_brother=NULL;     dir_for_ins->brother=-1;
            dir_for_ins->p_son=NULL;   dir_for_ins->son=-1;
            return;
        }
        else {
            posi->p_son=dir_for_ins;    posi->son=dir_for_ins->number;
            //dir_for_ins->p_parent=posi;  dir_for_ins->parent=posi->number;
            dir_for_ins->p_brother=tmp_dir1;    dir_for_ins->brother=tmp_dir1->number;
            dir_for_ins->p_son=NULL;    dir_for_ins->son=-1;
        }
    }
    else{
        for(tmp_dir2=tmp_dir1->p_brother;tmp_dir2->dir_or_file&&tmp_dir2->p_brother;tmp_dir1=tmp_dir2,tmp_dir2=tmp_dir2->p_brother);
        tmp_dir1->p_brother=dir_for_ins;    tmp_dir1->brother=dir_for_ins->number;
        dir_for_ins->p_brother=tmp_dir2;    dir_for_ins->brother=tmp_dir2->number;
        //tmp_dir2->p_parent=dir_for_ins;        tmp_dir2->parent=dir_for_ins->number;
        //dir_for_ins->p_parent=tmp_dir1;        dir_for_ins->parent=tmp_dir1->number;
        dir_for_ins->p_son=NULL;            dir_for_ins->son=-1;
    }
    return;
}
void FileControl::write_file(string &str, int num)
//向磁盘块里写入添加的信息,从最后一块开始写,参数为目录项编号
{
    dirItem *tmp_dir;
    inode *tmp_inode;
    tmp_dir=&((super_block->dir_items)[num]);
    tmp_inode=new inode;
    fseek(fp,super_block->first_inode+sizeof(inode)*(tmp_dir->inode_num),SEEK_SET);
    fread(tmp_inode,sizeof(inode),1,fp);
    char *stch=new char[BLOCK_SIZE];
    bool first=true;          //判断写最后一个块
    int i=0,j=0;
    for(;j<str.length();){
        stch[i++]=str[j++];
        if(i!=BLOCK_SIZE&&j<str.length()) continue;
        stch[i]='/0';
        i=0;
        if(first&&tmp_inode->blocks!=0){
            bc.Bwrite(stch,(stch,tmp_inode->block)[tmp_inode->blocks-1]);
            tmp_inode->file_length=tmp_inode->file_length/BLOCK_SIZE+strlen(stch);
            first=false;
            //fseek(fp,super_block->first_inode+sizeof(inode)*(tmp_dir->inode_num),SEEK_SET);
            //fwrite(tmp_inode,sizeof(inode),1,fp);
            //continue;
        }
        else{
            int num=bc.Bwrite(stch);               //自动申请一个块写,返回块号
            tmp_inode->block[tmp_inode->blocks]=num;
            tmp_inode->blocks++;
            tmp_inode->file_length+=strlen(stch);
        }
    }
    gettime(&(tmp_inode->file_edit));
    fseek(fp,super_block->first_inode+sizeof(inode)*(tmp_dir->inode_num),SEEK_SET);
    fwrite(tmp_inode,sizeof(inode),1,fp);
    delete tmp_inode;
    delete [] stch;
    return;
}


ICmd::ICmd(void)
{
    show_menu();
}
ICmd::~ICmd(void)
{
    end_fs();
}
void ICmd::show_menu(void)
{
    char name[NAME_LEN];
    char *password;
    int user_num;
    cout<<"########################################################################"<<endl;
    cout<<"######################### Welcome to my filesystem #####################"<<endl;
    cout<<"########################                designed by luju ##############"<<endl;
    cout<<"#######################################################################"<<endl;
    init_fs();
    exit_flag=false;     //表示进入文件系统
    logout_flag=false;   //表示换身份进入文件系统
    while(!exit_flag){
        logout_flag=false;   //表示换身份进入文件系统
        for(int i=0;i<3;i++){
            cout<<"login:";
            cin>>name;
            password=getpass("password:");
            user_num=check_user(name,password);     //检查用户是否合法,合法返回用户所在编号,否则返回-1
            if(user_num!=-1) break;
            cout<<"The user doesn't exist or bad password!"<<endl;
            if(i>=2) {
                cout<<"You have tried too many times,you are forbiden to try again."<<endl;
                exit(-1);
            }
        }
        user_active=&(super_block->users[user_num]);
        dir_active=&((super_block->dir_items)[user_active->my_dir]);
        cout<<"Welcome!"<<user_active->name<<endl;
        cout<<"You can type help for help"<<endl;
        while(!logout_flag){
            cout<<user_active->name<<"@";
            if(user_active->group=='r') cout<<"root:";
            else cout<<"user:";
            get_order();  //接收命令
            switch(check_order()){
                case CREAT:
                    Creat(string(param)); break;
                case READ:
                    Read(string(param)); break;
                case WRITE:
                    Write(string(param)); break;
                case DEL:
                    Del(string(param)); break;
                case MKDIR:
                    CreatDir(string(param)); break;
                case RMDIR:
                    DelDir(string(param)); break;
                case CD:
                    Cd(string(param));  break;
                case LS:
                    Ls(); break;
                case PWD:
                    Pwd();break;
                case NEW:
                    NewUser();  break;
                case SHOW:
                    Show();    break;
                case HELP:
                    Help(); break;
                case LOGOUT:
                    Logout();break;   //在这个函数里改变logout_flag即可
                case EXIT:
                    Exit(); break;
                default:
                    cout<<"The order is wrong!You can type help for help"<<endl;
            }
        }
    }
}

void ICmd::get_order(void)
{
    string tmp;
    char buffer[20];
    cin>>buffer;
    for(int i=0;i<20&&buffer[i]!='/0';i++){
        if(buffer[i]>='a'&&buffer[i]<='z') buffer[i]=buffer[i]-32;
    }
    tmp=buffer;       
    strcpy(order,tmp.c_str());
    if(tmp=="CREAT"||tmp=="WRITE"||tmp=="CD"||tmp=="DEL"||tmp=="READ"||tmp=="MKDIR"||tmp=="RMDIR"){
        cin>>tmp;
        strcpy(param,tmp.c_str());
    }
}


//检查用户
int ICmd::check_user(char *name,char *password)
{
    int i,is_find=-1;
    string name1=string(name);
    string name2;
    for(i=0;i<super_block->num_of_users;i++){
        name2=string((super_block->users[i]).name);
        if(name1==name2){
            if(string(password)==string((super_block->users[i]).password)){
                is_find=i;
                break;
            }
        }
    }
    return is_find;
}
int ICmd::check_order(void)
{
    string tmp=string(order);
    if(tmp=="CREAT")    return CREAT;
    if(tmp=="READ")    return READ;
    if(tmp=="WRITE")    return WRITE;
    if(tmp=="DEL")    return DEL;
    if(tmp=="MKDIR")    return MKDIR;
    if(tmp=="RMDIR")    return RMDIR;
    if(tmp=="CD")        return CD;
    if(tmp=="LS")        return LS;
    if(tmp=="PWD")    return PWD;
    if(tmp=="NEW")    return NEW;
    if(tmp=="SHOW")    return SHOW;
    if(tmp=="HELP")    return HELP;
    if(tmp=="LOGOUT")    return LOGOUT;
    if(tmp=="EXIT")        return EXIT;
    return -1;
}
void ICmd::init_fs(void){
    super_block=NULL;
    dir_active=NULL;
    head_dir=NULL;
    user_active=NULL;
    if((fp=fopen("storage","r+"))==NULL){
        init_fs_first();
        fp=fopen("storage","r+");
    }
    super_block=new sup_blk;
    fread(super_block,sizeof(sup_blk),1,fp);
    head_dir=&(super_block->dir_items[0]);
    cr_dir_tree(head_dir);         //建目录树
}
void ICmd::cr_dir_tree(dirItem *head)
{
    if(head==NULL)    return;
    if(head->parent!=-1)
        head->p_parent=&(super_block->dir_items[head->parent]);
    else head->p_parent=NULL;
    if(head->brother!=-1)
        head->p_brother=&(super_block->dir_items[head->brother]);
    else head->p_brother=NULL;
    if(head->son!=-1)
        head->p_son=&(super_block->dir_items[head->son]);
    else head->p_son=NULL;
    cr_dir_tree(head->p_brother);
    cr_dir_tree(head->p_son);
    return;
}
void ICmd::end_fs(void)
{
    rewind(fp);
    fwrite(super_block,sizeof(sup_blk),1,fp);
    //delete super_block;
}
void ICmd::init_fs_first(void)
{
    if((fp=fopen("storage","w+"))==0)
    {
        cout<<"ERROR!Cannot creat a file for the vitual fs.exit"<<endl;
        exit(-1);
    }
    fseek(fp,DEV_SIZE,SEEK_SET);
    fputc('#',fp);  //写入磁盘文件结束标志
    //开始初始化超级块
    super_block=new sup_blk;
    //初始化目录项的位示图和各个目录项
    for(int i=0;i<DIR_NUM;i++)    {
        super_block->dirs[i]=true;
        (super_block->dir_items[i]).number=i;
        (super_block->dir_items[i]).inode_num=-1;
        (super_block->dir_items[i]).name[0]='/0';
        (super_block->dir_items[i]).parent=-1;
        (super_block->dir_items[i]).son=-1;
        (super_block->dir_items[i]).brother=-1;
        (super_block->dir_items[i]).p_parent=NULL;
        (super_block->dir_items[i]).p_son=NULL;
        (super_block->dir_items[i]).p_brother=NULL;
    }
    for(int i=0;i<BLOCK_NUM;i++)    super_block->blocks[i]=true;
    for(int i=0;i<INODE_NUM;i++)    super_block->inodes[i]=true;
    super_block->num_of_users=0;
    super_block->num_of_files=0;
    super_block->dirs[0]=false;     //做根目录项
    (super_block->dir_items[0]).inode_num=0;
    (super_block->dir_items[0]).dir_or_file=true;  //表示目录
    strcpy((super_block->dir_items[0]).name,""); //此目录不属于任何用户
    (super_block->dir_items[0]).parent=-1;
    (super_block->dir_items[0]).brother=-1;
    (super_block->dir_items[0]).son=-1;
    //还要初始化各个目录项和i节点!!!!
    for(int i=0;i<USER_NUM;i++)
        (super_block->users[i]).flag=false;
    super_block->inodes[0]=false;   //根的i节点
    super_block->first_inode=sizeof(sup_blk);
    super_block->first_block=super_block->first_inode+INODE_NUM*(sizeof(inode));
    inode *tmp=new inode;
    tmp->number=0;
    tmp->mode=(short)0755;//初始化权限
    strcpy(tmp->user_name,"");
    tmp->user_group='/0';
    tmp->file_length=0;
    tmp->blocks=0;
    for(int i=0;i<FILE_BLOCKS;i++)
        tmp->block[i]=-1;
    fseek(fp,super_block->first_inode,SEEK_SET);
    fwrite(tmp,sizeof(inode),1,fp);
    for(int i=1;i<INODE_NUM;i++){
        tmp->number=i;
        fwrite(tmp,sizeof(inode),1,fp);
    }
    char tmpch[BLOCK_SIZE];
    for(int i=0;i<BLOCK_SIZE;i++)    tmpch[i]='/0';
    fseek(fp,super_block->first_block,SEEK_SET);
    for(int i=0;i<BLOCK_NUM;i++)
        fwrite(tmpch,sizeof(char)*BLOCK_SIZE,1,fp);
    cout<<"这是你第一次使用该文件系统,你必须首先创建一个用户,且第一个用户默认为管理员"<<endl;
    head_dir=&(super_block->dir_items[0]);
    NewUser();  //创建第一个用户,还须为其创建一个目录
    user_active=NULL;
    fseek(fp,0,SEEK_SET);
    fwrite(super_block,sizeof(sup_blk),1,fp);
    delete tmp;
    delete super_block;
    fclose(fp);
}
void ICmd::NewUser(void)
//需要考虑是否是第一个用户
{
    user_info *newone=new user_info;
    string pass1,pass2;
    cout<<"creat name:";
    cin>>(newone->name);
    while(1){
        pass1=getpass("please input your password:");
        pass2=getpass("please input your password again:");
        if(pass1==pass2) break;
    }
    strcpy(newone->password,pass1.c_str());
    if(super_block->num_of_users==0)   //创建第一个用户,默认为管理员
        newone->group='r';
    else if(user_active->group=='r'){   //只有root组的用户才有选择创建何类型用户的权利,非root组用户只能创建user组用户
        cout<<"please input its group(r/u):";
        cin>>newone->group;
    }
    else newone->group='u';
    newone->flag=true;
    newone->my_dir=fc.creat_df(newone->name,DIR,ROOT);   //建目录或文件,第一个参数为名称,第二个表示创建的是目录/文件,第三个表示位置(根/当前目录下)
    fc.add_user(newone);   //加到超级块中去
    super_block->num_of_users++;
}
void ICmd::Logout(void)
{
    logout_flag=true;
    dir_active=head_dir;
    user_active=NULL;
}
void ICmd::Exit(void){
    logout_flag=true;
    exit_flag=true;
}
void ICmd::Show(void){
    user_info *tmp_user;
    cout<<"/t用户名/t所属组/t用户目录"<<endl;
    for(int i=0;i<USER_NUM;i++){
        tmp_user=&(super_block->users[i]);
        if(tmp_user->flag){
            cout<<"/t"<<tmp_user->name<<"/t"<<tmp_user->group<<"/t/"<<tmp_user->name<<"/"<<endl;
        }   
    }
    return;
}
void ICmd::Cd(string name) //目录转移函数
{
    if(name=="..")    {
        if(dir_active->number)    dir_active=dir_active->p_parent;  //若当前目录不是根目录时执行
    }
    else if(name=="~")    dir_active=&(super_block->dir_items[user_active->my_dir]);
    else if(name=="/")    dir_active=&(super_block->dir_items[0]);    //返回根目录
    else {
        int num=fc.find(name,DIR);     //在当前目录下寻找该目录,返回它的目录项号,否则返回-1
        if(num==-1)    cout<<"ERROR:Cannot find the directory: "<<name<<endl;
        else dir_active=&(super_block->dir_items[num]);
    }
}
void ICmd::Creat(string filename)
{
    char name[20];
    strcpy(name,filename.c_str());
    fc.creat_df(name,FE,CURENT);
}
void ICmd::CreatDir(string name)
{
    char str[20];
    strcpy(str,name.c_str());
    fc.creat_df(str,DIR,CURENT);
}
void ICmd::Del(string filename)
{
    int num=fc.find(filename,FE);
    if(num==-1)    cout<<"ERROR:Cannot find the file: "<<filename<<endl;
    else fc.del(num);    //删除,参数为目录项编号
}
void ICmd::DelDir(string name)
{
    int num=fc.find(name,DIR);
    if(num==-1)    cout<<"ERROR:Cannot find the directory: "<<name<<endl;
    else fc.del(num);
}
void ICmd::Help(void)
{
    cout<<"/t"<<"命 令"<<"/t"<<"参 数"<<"/t/t"<<"功能说明"<<endl
        <<"/t"<<"CREAT"<<"/t"<<"文件名"<<"/t/t"<<"创建文件"<<endl
        <<"/t"<<"READ"<<"/t"<<"文件名"<<"/t/t"<<"读文件"<<endl
        <<"/t"<<"WRITE"<<"/t"<<"文件名"<<"/t/t"<<"在文件尾编辑"<<endl
        <<"/t"<<"DEL"<<"/t"<<"文件名"<<"/t/t"<<"删除文件"<<endl
        <<"/t"<<"MKDIR"<<"/t"<<"路径名"<<"/t/t"<<"创建目录"<<endl
        <<"/t"<<"RMDIR"<<"/t"<<"路径名"<<"/t/t"<<"删除目录"<<endl
        <<"/t"<<"CD"<<"/t"<<"路径名"<<"/t/t"<<"转移工作目录"<<endl
        <<"/t"<<"LS"<<"/t"<<"无"<<"/t/t"<<"列出目录"<<endl
        <<"/t"<<"PWD"<<"/t"<<"无"<<"/t/t"<<"列出用户当前所在目录"<<endl
        <<"/t"<<"NEW"<<"/t"<<"无"<<"/t/t"<<"创建新用户"<<endl
        <<"/t"<<"SHOW"<<"/t"<<"无"<<"/t/t"<<"列出所有用户"<<endl
        <<"/t"<<"HELP"<<"/t"<<"无"<<"/t/t"<<"列出帮助"<<endl
        <<"/t"<<"LOGOUT"<<"/t"<<"无"<<"/t/t"<<"用户登出"<<endl
        <<"/t"<<"EXIT"<<"/t"<<"无"<<"/t/t"<<"退出文件系统"<<endl;
}
void ICmd::Pwd()
{
    pwd(dir_active);
    cout<<endl;
}
void ICmd::pwd(dirItem *p)        //列出工作目录
{
    if(p->number==0){
        cout<<"/";
        return;
    }
    pwd(p->p_parent);
    cout<<p->name<<"/";
}
void ICmd::Ls()
{
    dirItem *tmp;
    inode *tmp_inode=new inode; 
    pwd(dir_active);
    cout<<": 的目录为:"<<endl;
    int dir=0,file=0;
    for(tmp=dir_active->p_son;tmp!=NULL;tmp=tmp->p_brother){
        cout<<tmp->name;
        if(tmp->dir_or_file)    {
            cout<<"/t"<<"< DIR >"<<endl;
            dir++;
        }
        else {
            file++;
            fseek(fp,super_block->first_inode+(sizeof(inode)*tmp->inode_num),SEEK_SET);
            fread(tmp_inode,sizeof(inode),1,fp);
            cout<<"/t"<<tmp_inode->file_length<<" Byte   "<<"created:"<<tmp_inode->file_creat.year<<"-"<<tmp_inode->file_creat.month<<"-"<<tmp_inode->file_creat.day<<" "<<tmp_inode->file_creat.hour<<":"<<tmp_inode->file_creat.min<<"  latest edited:"<<tmp_inode->file_edit.year<<"-"<<tmp_inode->file_edit.month<<"-"<<tmp_inode->file_edit.day<<" "<<tmp_inode->file_edit.hour<<":"<<tmp_inode->file_edit.min<<endl;
        }
    }
    cout<<"总共有"<<dir<<"个目录和"<<file<<"个文件"<<endl;
    delete tmp_inode;
}
void ICmd::Read(string filename)
{
    int num=fc.find(filename,FE);
    if(num==-1)    cout<<"ERROR:Cannot find the file; "<<filename<<endl;
    else fc.read_file(num);
}
void ICmd::Write(string filename)
{
    int num=fc.find(filename,FE);
    char tmp_block[BLOCK_SIZE];
    char buf[100];
    bool flag=false;
    if(num==-1)    {
        cout<<"ERROR:Cannot find the file: "<<filename<<endl;
        return;
    }
    fc.read_file(num);
    inode *tmp_node=new inode;
    fseek(fp,super_block->first_inode+((super_block->dir_items)[num].inode_num)*sizeof(inode),SEEK_SET);
    fread(tmp_node,sizeof(inode),1,fp);   //将文件的I节点读入
    string str;
    if(tmp_node->blocks!=0){
        fseek(fp,super_block->first_block+sizeof(char)*BLOCK_SIZE*(tmp_node->block[tmp_node->blocks-1]),SEEK_SET);
        fread(tmp_block,sizeof(char)*BLOCK_SIZE,1,fp);//读最后一块
        str=tmp_block;
    }
    cout<<endl<<"请输入要添加的内容,以#结束:"<<endl;
    int len;
    for(;;){
        gets(buf);
        len=strlen(buf);
        if(len!=0&&buf[len-1]!='#') {
            buf[len+1]='/0';
            buf[len]='/n';
        }
        else if(len!=0&&buf[len-1]=='#'){
            buf[len]='/0';
            buf[len-1]='/n';
            flag=true;      //表示到了文件输入结束,跳出循环标志
        }
        str=str+buf;
        if(str.length()>=BLOCK_SIZE) break;
        if(flag) break;
    }
    fc.write_file(str,num);       //将文件写入磁盘,从原来的最后一块开始写,参数为目录项编号
}


int main(void)
{
    ICmd ch;
    return 0;
}
1 概述 文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于NAND Flash的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统文件系统由三部分组成:文件系统的接口,对对象操纵和管理的软件集合,对象及属性。从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。 本次实验我们实现了多级目录下的文件管理系统,具备文件系统的文件创建、删除、读写以及目录的创建、删除等操作,并在内存中开辟一块空间,模拟虚拟磁盘,成功地展示出文件系统的功能和属性。 2 课程设计的任务和要求 2.1 设计任务 在下列内容中任选其一: 1、多用户、多级目录结构文件系统的设计与实现; 2、WDM驱动程序开发; 3、存储管理系统的实现,主要包括虚拟存储管理调页、缺页统计等; 4、进程管理系统的实现,包括进程的创建、调度、通信、撤消等功能; 5、自选一个感兴趣的与操作系统有关的问题加以实现,要求难度相当。 2.2 设计要求 1、在深入理解操作系统基本原理的基础上,对于选定的题目,以小组为单位,先确定设计方案; 2、设计系统的数据结构和程序结构,设计每个模块的处理流程。要求设计合理; 3、编程序实现系统,要求实现可视化的运行界面,界面应清楚地反映出系统的运行结果; 4、确定测试方案,选择测试用例,对系统进行测试; 5、运行系统并要通过验收,讲解运行结果,说明系统的特色和创新之处,并回答指导教师的提问; 6、提交课程设计报告。 集体要求: 1.在内存中开辟一个虚拟磁盘空间作为文件存储器,在其上实现一个多用户多目录文件系统。 2.文件物理结构可采用显式链接或其他方法。 3.磁盘空闲空间的管理可选择位示图或其他方法。如果采用位示图来管理文件存储空间,并采用显式链接分配方式,则可以将位示图合并到FAT中。 4.文件目录结构采用多用户多级目录结构,每个目录项包含文件名、物理地址、长度等信息,还可以通过目录项实现对文件的读和写的保护。目录组织方式可以不使用索引结点的方式,但使用索引结点,则难度系数为1.2。 5.设计一个较实用的用户界面,方便用户使用。要求提供以下相关文件操作: (1)具有login (用户登录) (2)系统初始化(建文件卷、提供登录模块) (3)文件的创建: create (4)文件的打开:open (5)文件的读:read (6)文件的写:write (7)文件关闭:close (8)删除文件:delete (9)创建目录(建立子目录):mkdir (10)改变当前目录:cd (11)列出文件目录:dir (12)退出:logout ................................................
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值