linux下简单模拟文件系统

来源:互联网 发布:如何补充胶原蛋白知乎 编辑:程序博客网 时间:2024/05/17 02:56

整体思路:

文件系统基于一个大文件实现
大文件数据分为几个区域来模拟简单的文件系统
1.User:username and password
2.SuperBlock:blockSize,blockNum,inodeNum,blockFree
3.blockBitmap:the use state of block area
4.inodeBitmap:the use state of inode area
5.Inode area:inode * inodeMax(blockNum)
6.Block area:block * blockNum

系统评估:

系统的实现只是很基础的,许多实现细节还有优化的空间,还有一些功能可继续扩展。
待优化:
文件读写具体实现写法;
文件写入的方式;
可扩展:
cd命令任意性;
文件移动;
文件复制;
多用户;
图形化支持;
已实现:
基于标准输入输出流读写;
大文件存储,最多支持二级索引,文件大小上限为64M;
子目录和父目录跳转;
文件重命名;
文件,目录删除;
文件,目录读写权限控制;

code:

FileSystem.h 文件系统定义

#ifndef FILESYSTEM_H#define FILESYSTEM_H#include <time.h>#include <stdio.h>#include <string.h>#include <string>#include <stdlib.h>#include <malloc.h>#include <signal.h>#include <unistd.h>#include <sys/types.h>#define BLOCK_SIZE 1024#define BLOCK_NUM 102400#define SYSTEM_NAME "FileSystem.tzh"#define SUDO     0#define HELP     1#define LS       2#define CD       3#define MKDIR    4#define TOUCH    5#define CAT      6#define WRITE    7#define RM       8#define MV       9#define CP      10#define CHMOD   11#define LOGOUT  12#define EXIT    13#define SYSINFO 14#define CLEAR   15#define ACCOUNT 16using namespace std;/**文件系统块结构*/typedef struct{    unsigned short blockSize;//2B,文件块大小    unsigned int blockNum;//4B,文件块数量    unsigned int inodeNum;//4B,i节点数量,即文件数量    unsigned int blockFree;//4B,空闲块数量}SuperBlock;/**文件i节点结构100B*/typedef struct{    unsigned int id;      //4B,i节点索引    char name[30];        //30B,文件名,最大长度29    unsigned char isDir;  //1B,文件类型 0-file 1-dir    unsigned int parent;  //4B,父目录i节点索引    unsigned int length;  //4B,文件长度,unsigned int最大2^32-1(4GB-1B),目录文件则为子文件项数量    unsigned char type;   //1B,文件权限,0-read-only,1-read-write    time_t time;          //8B,文件最后修改时间,从1970年1月1日00时00分00秒至今所经过的秒数    unsigned int addr[12];//12*4B,文件内容索引,文件前10项为直接索引,目录前11项为直接索引    unsigned int blockId;  //文件项所在的目录数据块的id,便于删除时定位}Inode,*PInode;/**文件部分信息节点,用于简要显示文件信息文件名 文件/目录 文件长度 文件权限 修改时间*/typedef struct {    unsigned int id;     //4B    char name[30];       //30B    unsigned char isDir; //1B    unsigned int blockId; //4B,在目录数据块中的位置0-255}Fcb,*PFcb;typedef struct FCB_LINK_NODE{    Fcb fcb;    struct FCB_LINK_NODE* next;}FcbLinkNode, *FcbLink;/**文件系统用户结构*/typedef struct{    char username[10];//用户名,最大长度9    char password[10];//密码,最大长度9}User;class FileSystem{    public:        FileSystem(char* name);        virtual ~FileSystem();        int init();        //system init        void createFileSystem();        void openFileSystem();        //command        void help();        void ls();        void ls_l();        int cd(char* name);        //file operation        int createFile(char* name, unsigned char isDir);        int read(char* name);        int write(char* name);        int del(char* name);        int mv(char* name, char* newName);        int cp(char* src, char* dst);        int chmod(char* name, unsigned char type);        //system        void login();        void logout();        void exit();        void systemInfo();        void clr();        int account();        void command(void);    protected:    private:        const int blockSize;//文件块大小        const int blockNum; //文件块数量        unsigned char* blockBitmap;//文件块使用图        unsigned char* inodeBitmap;//i节点使用图        //大小        unsigned short userSize;        unsigned short superBlockSize;        unsigned short blockBitmapSize;        unsigned short inodeBitmapSize;        unsigned short inodeSize;        unsigned short fcbSize;        unsigned short itemSize;        //偏移        unsigned long sOffset;     //superBlock偏移        unsigned long bbOffset;    //blockBitmap偏移        unsigned long ibOffset;    //inodeBitmap偏移        unsigned long iOffset;     //i节点区偏移        unsigned long bOffset;     //数据区偏移        unsigned char isAlive;     //系统是否在运行        char name[30];//文件系统名        FILE* fp;//文件系统文件指针        SuperBlock superBlock;//文件系统块信息        string curPath;//当前目录字符串        Inode curInode;//当前目录i节点        FcbLink curLink;//当前目录子文件链指针        User user;//用户        char cmd[5][20];//命令行输入        char* SYS_CMD[17];//系统支持的命令        //user区域操作        void getUser(User* pUser);        void setUser(User user);        //superBlock区域操作        void getSuperBlock(SuperBlock* pSuper);        void updateSuperBlock(SuperBlock super);        //blockBitmap区域操作        unsigned int getAvailableBlockId();        void getBlockBitmap(unsigned char* bitmap);        void updateBlockBitmap(unsigned char* bitmap, unsigned int index);        void updateBlockBitmap(unsigned char* bitmap, unsigned int start, unsigned int count);        //inodeBitmap区域操作        unsigned int getAvailableInodeId();        void getInodeBitmap(unsigned char* bitmap);        void updateInodeBitmap(unsigned char* bitmap, unsigned int index);        void updateInodeBitmap(unsigned char* bitmap, unsigned int start, unsigned int count);        //inode block区域操作        void getInode(PInode pInode, unsigned int id);        void updateInode(Inode inode);        void releaseInode(unsigned int id);        //data block区域操作        //地址或文件项        unsigned int getAvailableFileItem(Inode& inode, unsigned int* availableIndex);        unsigned int getItem(unsigned int blockId, unsigned int index);        void updateItem(unsigned int blockId, unsigned int index, unsigned int value);        void releaseItem(unsigned int blockId, unsigned int id);        //文件内容        int getData(unsigned int blockId, char* buff, unsigned int size, unsigned int offset);        int writeData(unsigned int blockId, char* buff, unsigned int size, unsigned int offset);        void releaseBlock(unsigned int blockId);        //定位操作        unsigned int findChildInode(FcbLink curLink, char* name);        //目录信息链操作        void getFcbLinkNode(FcbLink pNode, Inode inode);        void getFcbLink(FcbLink& curLink, Inode inode);        void appendFcbLinkNode(FcbLink curLink, Inode inode);        void removeFcbLinkNode(FcbLink curLink, Inode inode);        void removeFcbLinkNode(FcbLink curLink, char* name);        void releaseFcbLink(FcbLink& curLink);        //system command        int analyse(char* str);        void stopHandle(int sig);        void updateResource();        void showPath();        //util        void showFileDigest(FcbLink pNode);        void showFileDetail(PInode pInode);        unsigned int waitForInput(char* buff, unsigned int limit);};#endif // FILESYSTEM_H

FileSystem.cpp 文件系统实现

#include "FileSystem.h"/**初始化常量,文件系统名和命令集合finish*/FileSystem::FileSystem(char* name):blockSize(BLOCK_SIZE),blockNum(BLOCK_NUM),blockBitmap(new unsigned char[BLOCK_NUM+1]),inodeBitmap(new unsigned char[BLOCK_NUM+1]),isAlive(0),fp(NULL),curLink(NULL){    userSize = sizeof(User);    superBlockSize = sizeof(SuperBlock);    blockBitmapSize = blockNum;    inodeBitmapSize = blockNum;    inodeSize = sizeof(Inode);    fcbSize = sizeof(Fcb);    itemSize = sizeof(unsigned int);    sOffset = userSize;    bbOffset = sOffset+sizeof(SuperBlock);    ibOffset = bbOffset+blockBitmapSize;    iOffset = ibOffset+inodeBitmapSize;    bOffset = iOffset+sizeof(Inode)*blockNum;    if(name == NULL || strcmp(name, "") == 0)        strcpy(this->name, SYSTEM_NAME);    else        strcpy(this->name, name);    SYS_CMD[0] = new char[5];    strcpy(SYS_CMD[0], "sudo");    SYS_CMD[1] = new char[5];    strcpy(SYS_CMD[1], "help");    SYS_CMD[2] = new char[3];    strcpy(SYS_CMD[2], "ls");    SYS_CMD[3] = new char[3];    strcpy(SYS_CMD[3], "cd");    SYS_CMD[4] = new char[6];    strcpy(SYS_CMD[4], "mkdir");    SYS_CMD[5] = new char[6];    strcpy(SYS_CMD[5], "touch");    SYS_CMD[6] = new char[4];    strcpy(SYS_CMD[6], "cat");    SYS_CMD[7] = new char[6];    strcpy(SYS_CMD[7], "write");    SYS_CMD[8] = new char[3];    strcpy(SYS_CMD[8], "rm");    SYS_CMD[9] = new char[3];    strcpy(SYS_CMD[9], "mv");    SYS_CMD[10] = new char[3];    strcpy(SYS_CMD[10], "cp");    SYS_CMD[11] = new char[6];    strcpy(SYS_CMD[11], "chmod");    SYS_CMD[12] = new char[7];    strcpy(SYS_CMD[12], "logout");    SYS_CMD[13] = new char[5];    strcpy(SYS_CMD[13], "exit");    SYS_CMD[14] = new char[8];    strcpy(SYS_CMD[14], "sysinfo");    SYS_CMD[15] = new char[6];    strcpy(SYS_CMD[15], "clear");    SYS_CMD[16] = new char[8];    strcpy(SYS_CMD[16], "account");}/**释放动态分配的控件finish*/FileSystem::~FileSystem(){    if(blockBitmap != NULL)    {        delete blockBitmap;        blockBitmap = NULL;    }    if(inodeBitmap != NULL)    {        delete inodeBitmap;        inodeBitmap = NULL;    }    if(SYS_CMD[0] != NULL)    {        delete []SYS_CMD;        SYS_CMD[0] = NULL;    }    if(curLink != NULL)    {        releaseFcbLink(curLink);    }}/**系统初始化,启动系统时调用finish*/int FileSystem::init(){    if(isAlive)        return -1;    //signal(SIGINT,stopHandle);    openFileSystem();    login();    command();    return 0;}/**创建文件系统finish*/void FileSystem::createFileSystem(){    printf("create file system...\n");    if ((fp = fopen(name,"wb+"))==NULL)    {        printf("open file %s error...\n",name);        ::exit(-1);    }    //init user    printf("username:");    fgets(user.username, sizeof(user.username), stdin);    if(user.username[strlen(user.username)-1] == '\n')        user.username[strlen(user.username)-1] = '\0';    system("stty -echo");    printf("password:");    fgets(user.password, sizeof(user.password), stdin);    if(user.password[strlen(user.password)-1] == '\n')        user.password[strlen(user.password)-1] = '\0';    system("stty echo");    printf("\n");    printf("username:%s\npassword:%s\n", user.username, user.password);    setUser(user);    //init superBlock    superBlock.blockSize = blockSize;    superBlock.blockNum = blockNum;    //分配一个给root    superBlock.inodeNum = 1;    superBlock.blockFree = blockNum-1;    updateSuperBlock(superBlock);    //init two bitmaps    unsigned long i;    //分配一个给root    blockBitmap[0] = 1;    inodeBitmap[0] = 1;    for(i = 1; i < blockNum; i++)    {        blockBitmap[i] = 0;        inodeBitmap[i] = 0;    }    updateBlockBitmap(blockBitmap, 0, blockBitmapSize);    updateInodeBitmap(inodeBitmap, 0, inodeBitmapSize);    //init inode and block    long len = 0;    len += (inodeSize+ blockSize) * blockNum;    for (i = 0; i < len; i++)    {        fputc(0, fp);    }    //init root dir    //set root inode info    curInode.id = 0;    strcpy(curInode.name, "/");    curInode.isDir = 1;    curInode.parent = inodeSize;    curInode.length = 0;    curInode.type = 0;    time(&(curInode.time));    for(i = 0; i < 12; i++)        curInode.addr[i] = 0;    curInode.blockId = 0;    //write root inode    updateInode(curInode);    fflush(fp);    //get curLink info    getFcbLink(curLink, curInode);    //get current path    curPath = "/";    printf("create file system %s finish.\n", this->name);}/**打开文件系统,若不存在,则创建finish*/void FileSystem::openFileSystem(){    if((fp = fopen(this->name,"rb"))==NULL)    {        createFileSystem();    }    else    {        printf("open file system...\n");        if ((fp=fopen(this->name,"rb+"))==NULL)        {            printf("open file %s error...\n", name);            ::exit(1);        }        rewind(fp);        //read header        getUser(&user);        getSuperBlock(&superBlock);        getBlockBitmap(blockBitmap);        getInodeBitmap(inodeBitmap);        //get current inode        getInode(&curInode, 0);        //get curLink info        getFcbLink(curLink, curInode);        //get current path        curPath = "/";        printf("open file system %s success\n", this->name);    }}/**显示帮助信息finish*/void FileSystem::help(){    printf("command: \n\    help    ---  show help menu \n\    sysinfo ---  show system base information \n\    logout  ---  exit user \n\    account ---  modify username and password \n\    clear   ---  clear the screen \n\    ls      ---  list the digest of the directory's children \n\    ls -l   ---  list the detail of the directory's children \n\    cd      ---  change directory \n\    mkdir   ---  make directory   \n\    touch   ---  create a new file \n\    cat     ---  read a file \n\    write   ---  write something to a file \n\    rm      ---  delete a directory or a file \n\    cp      ---  cp a directory file to another directory or file (not finish)\n\    mv      ---  rename a file or directory \n\    chmod   ---  change the authorizatino of a directory or a file \n\    exit    ---  exit this system\n");}/**列出目录下所有文件(目录)名finish*/void FileSystem::ls(){    //printf("ls %s\n", curInode.name);    FcbLink link = curLink->next;    while(link != NULL)    {        showFileDigest(link);        link = link->next;    }}/**列出目录下所有文件(目录)的详细信息finish*/void FileSystem::ls_l(){    //printf("ls -l %s\n", curInode.name);    FcbLink link = curLink->next;    PInode pInode = new Inode();    while(link != NULL)    {        pInode->id = link->fcb.id;        getInode(pInode, pInode->id);        showFileDetail(pInode);        link = link->next;    }}/**进入目录,暂时只支持进入子目录和返回父目录finish*/int FileSystem::cd(char* name){    //printf("cd from %s to child %s\n", curInode.name, name);    unsigned int id;    //回到父目录    if(strcmp(name, "..") == 0)    {        id = curInode.parent;        if(curInode.id > 0)        {            getInode(&curInode, id);            getFcbLink(curLink, curInode);            int pos = curPath.rfind('/', curPath.length()-2);            curPath.erase(pos+1, curPath.length()-1-pos);        }        return 0;    }    id = findChildInode(curLink, name);    if(id > 0)    {        getInode(&curInode, id);        getFcbLink(curLink, curInode);        curPath.append(name);        curPath.append(1, '/');        return 0;    }    else    {        printf("no such file or directory:%s\n", name);        return -1;    }}/**创建文件或目录flag:0-file,1-dirfinish*/int FileSystem::createFile(char * name, unsigned char isDir){    if(name == NULL || strcmp(name, "") == 0 || findChildInode(curLink, name) > 0)    {        printf("invalid file name:the name is empty,or the file has existed\n");        return -1;    }    //printf("create file %s (isDir=%d) in %s\n", name, isDir, curInode.name);    unsigned int index;    unsigned int dirBlockId = getAvailableFileItem(curInode, &index);    //找到一个可用文件项    if(dirBlockId > 0 || curInode.id == 0)    {        unsigned int blockId = getAvailableBlockId();        //找到一个空闲数据块        if(blockId > 0)        {            //更新superBlock            superBlock.blockFree--;            superBlock.inodeNum++;            //更新blockBitmap            blockBitmap[blockId] = 1;            updateBlockBitmap(blockBitmap, blockId);            unsigned int id = getAvailableInodeId();            //创建i节点            PInode pInode = new Inode();            pInode->id = id;            strcpy(pInode->name, name);            pInode->isDir = isDir;            pInode->parent = curInode.id;            pInode->length = 0;            pInode->type = 1;            time(&(pInode->time));            int i;            pInode->addr[0] = blockId;            for(i = 1; i < 12; i++)                pInode->addr[i] = 0;            pInode->blockId = dirBlockId;            //写入i节点            updateInode(*pInode);            //更新inodeBitmap            inodeBitmap[id] = 1;            updateInodeBitmap(inodeBitmap, id);            //将文件id(i节点索引)写入目录文件            //printf("%d register in dir %d [%d]\n", id, dirBlockId, index);            updateItem(dirBlockId, index, id);            //printf("%d [%d] = %d\n", dirBlockId, index, id);            //更新目录i节点            curInode.length++;            time(&(curInode.time));            updateInode(curInode);            //更新curLink            appendFcbLinkNode(curLink, *pInode);            delete pInode;            //printf("create file %s success:id=%d\n", pInode->name, pInode->id);            return 0;        }        else        {            printf("storage space is not enough, %d\n", blockId);            return -1;        }    }    else    {        printf("the directory can't append file item, %d\n", dirBlockId);        return -1;    }}/**读取文件finish*/int FileSystem::read(char *name){    //printf("read file %s in %s\n", name, curInode.name);    unsigned int id = findChildInode(curLink, name);    if(id > 0)    {        //读取i节点        PInode pInode = new Inode();        getInode(pInode, id);        if(pInode->isDir == 0)        {            unsigned long len = pInode->length;            //remember to delete it            char* buff = new char[blockSize+1];            int i;            unsigned int blockId;            //遍历10个直接索引,读取数据块            for(i = 0; i < 10; i++)            {                blockId = pInode->addr[i];                if(blockId > 0)                {                    if(len > blockSize)                    {                        len -= getData(blockId, buff, blockSize, 0);                        printf("%s", buff);                    }                    else                    {                        len -= getData(blockId, buff, len, 0);                        printf("%s\n", buff);                        //read finish                        delete buff;                        return 0;                    }                }                else                {                    //read finish                    printf("\n");                    delete buff;                    return 0;                }            }            if(len <= 0)            {                //read finish                printf("\n");                delete buff;                return 0;            }            //遍历1个一级索引            unsigned int addrBlockId = pInode->addr[10];            int totalItem = blockSize/itemSize;            if(addrBlockId > 0)            {                //遍历totalItem个直接索引                for(i = 0; i < totalItem; i++)                {                    blockId = getItem(addrBlockId, i);                    if(blockId > 0)                    {                        if(len > blockSize)                        {                            len -= getData(blockId, buff, blockSize, 0);                            printf("%s", buff);                        }                        else                        {                            len -= getData(blockId, buff, len, 0);                            printf("%s\n", buff);                            //read finish                            delete buff;                            return 0;                        }                    }                    else                    {                        //read finish                        printf("\n");                        delete buff;                        return 0;                    }                }            }            else            {                //read finish                printf("\n");                delete buff;                return 0;            }            if(len <= 0)            {                //read finish                printf("\n");                delete buff;                return 0;            }            //遍历一个二级索引            unsigned int addrBlockId2 = pInode->addr[11];            if(addrBlockId2 > 0)            {                //遍历totalItem个一级索引                unsigned j;                for(j = 0; j < totalItem; j++)                {                    addrBlockId = getItem(addrBlockId2, j);                    if(addrBlockId > 0)                    {                        //遍历totalItem个直接索引                        for(i = 0; i < totalItem; i++)                        {                            blockId = getItem(addrBlockId, i);                            if(blockId > 0)                            {                                if(len > blockSize)                                {                                    len -= getData(blockId, buff, blockSize, 0);                                    printf("%s", buff);                                }                                else                                {                                    len -= getData(blockId, buff, len, 0);                                    printf("%s\n", buff);                                    //read finish                                    delete buff;                                    return 0;                                }                            }                            else                            {                                //read finish                                printf("\n");                                delete buff;                                return 0;                            }                        }                    }                    else                    {                        //read finish                        printf("\n");                        delete buff;                        return 0;                    }                }            }            else            {                //read finish                printf("\n");                delete buff;                return 0;            }            return 0;        }        else        {            printf("%s is a directory\n", name);            return -1;        }    }    else    {        printf("no such file or directory\n");        return -1;    }    return 0;}/**写入文件未完成大文件一级、二级索引时写入finish*/int FileSystem::write(char *name){    //printf("write file %s in  %s\n", name, curInode.name);    unsigned int id = findChildInode(curLink, name);    unsigned long len = 0;    unsigned int num;    char ch;    if(id > 0)    {        //读取i节点        PInode pInode = new Inode();        getInode(pInode, id);        if(pInode->isDir == 0)        {            if(pInode->type == 0)            {                printf("file %s is Read-Only file\n", name);                return -1;            }            printf("write %s: use flag \"</>\" to end\n", name);            //remember to delete it            char* buff = new char[blockSize+1];            //写入10个直接索引对应数据块            int i;            unsigned int blockId;            for(i = 0; i < 10; i++)            {                blockId = pInode->addr[i];                if(blockId > 0)                {                    num = waitForInput(buff, blockSize);                    writeData(blockId, buff, num, 0);                    len += num;                    if(num < blockSize)                    {                        pInode->length = len;                        time(&(pInode->time));                        updateInode(*pInode);                        delete buff;                        return 0;                    }                    else                    {                        printf("You have input %ld Byte dat, continue?[Y/N]", len);                        ch = getchar();                        if(ch != 'Y' && ch != 'y')                        {                            pInode->length = len;                            time(&(pInode->time));                            updateInode(*pInode);                            delete buff;                            return 0;                        }                    }                }                else                {                    blockId = getAvailableBlockId();                    if(blockId > 0)                    {                        superBlock.blockFree--;                        updateSuperBlock(superBlock);                        blockBitmap[blockId] = 1;                        updateBlockBitmap(blockBitmap, blockId);                        pInode->addr[i] = blockId;                        time(&(pInode->time));                        updateInode(*pInode);                        num = waitForInput(buff, blockSize);                        writeData(blockId, buff, num, 0);                        len += num;                        if(num < blockSize)                        {                            pInode->length = len;                            time(&(pInode->time));                            updateInode(*pInode);                            delete buff;                            return 0;                        }                        else                        {                            printf("You have input %ld Byte dat, continue?[Y/N]", len);                            ch = getchar();                            if(ch != 'Y' && ch != 'y')                            {                                pInode->length = len;                                time(&(pInode->time));                                updateInode(*pInode);                                delete buff;                                return 0;                            }                        }                    }                    else                    {                        pInode->length = len;                        time(&(pInode->time));                        updateInode(*pInode);                        delete buff;                        return 0;                    }                }            }            //写入1个一级索引            unsigned addrBlockId = pInode->addr[10];            int itemTotal = blockSize/itemSize;            //写入itemTotal个直接索引对应的数据块            if(addrBlockId > 0)            {                 for(i = 0; i < itemTotal; i++)                {                    blockId = getItem(addrBlockId, i);                    if(blockId > 0)                    {                        num = waitForInput(buff, blockSize);                        writeData(blockId, buff, num, 0);                        len += num;                        if(num < blockSize)                        {                            pInode->length = len;                            time(&(pInode->time));                            updateInode(*pInode);                            delete buff;                            return 0;                        }                        else                        {                            printf("You have input %ld Byte dat, continue?[Y/N]", len);                            ch = getchar();                            if(ch != 'Y' && ch != 'y')                            {                                pInode->length = len;                                time(&(pInode->time));                                updateInode(*pInode);                                delete buff;                                return 0;                            }                        }                    }                    else                    {                        blockId = getAvailableBlockId();                        if(blockId > 0)                        {                            superBlock.blockFree--;                            updateSuperBlock(superBlock);                            blockBitmap[blockId] = 1;                            updateBlockBitmap(blockBitmap, blockId);                            updateItem(addrBlockId, i, blockId);                            time(&(pInode->time));                            updateInode(*pInode);                            num = waitForInput(buff, blockSize);                            writeData(blockId, buff, num, 0);                            len += num;                            if(num < blockSize)                            {                                pInode->length = len;                                time(&(pInode->time));                                updateInode(*pInode);                                delete buff;                                return 0;                            }                            else                            {                                printf("You have input %ld Byte dat, continue?[Y/N]", len);                                ch = getchar();                                if(ch != 'Y' && ch != 'y')                                {                                    pInode->length = len;                                    time(&(pInode->time));                                    updateInode(*pInode);                                    delete buff;                                    return 0;                                }                            }                        }                        else                        {                            pInode->length = len;                            time(&(pInode->time));                            updateInode(*pInode);                            delete buff;                            return 0;                        }                    }                }            }            else            {                addrBlockId = getAvailableBlockId();                if(addrBlockId > 0)                {                    superBlock.blockFree--;                    updateSuperBlock(superBlock);                    blockBitmap[addrBlockId] = 1;                    updateBlockBitmap(blockBitmap, addrBlockId);                    pInode->addr[10] = addrBlockId;                    time(&(pInode->time));                    updateInode(*pInode);                    //                    for(i = 0; i < itemTotal; i++)                    {                        blockId = getItem(addrBlockId, i);                        if(blockId > 0)                        {                            num = waitForInput(buff, blockSize);                            writeData(blockId, buff, num, 0);                            len += num;                            if(num < blockSize)                            {                                pInode->length = len;                                time(&(pInode->time));                                updateInode(*pInode);                                delete buff;                                return 0;                            }                            else                            {                                printf("You have input %ld Byte dat, continue?[Y/N]", len);                                ch = getchar();                                if(ch != 'Y' && ch != 'y')                                {                                    pInode->length = len;                                    time(&(pInode->time));                                    updateInode(*pInode);                                    delete buff;                                    return 0;                                }                            }                        }                        else                        {                            blockId = getAvailableBlockId();                            if(blockId > 0)                            {                                superBlock.blockFree--;                                updateSuperBlock(superBlock);                                blockBitmap[blockId] = 1;                                updateBlockBitmap(blockBitmap, blockId);                                updateItem(addrBlockId, i, blockId);                                time(&(pInode->time));                                updateInode(*pInode);                                num = waitForInput(buff, blockSize);                                writeData(blockId, buff, num, 0);                                len += num;                                if(num < blockSize)                                {                                    pInode->length = len;                                    time(&(pInode->time));                                    updateInode(*pInode);                                    delete buff;                                    return 0;                                }                                else                                {                                    printf("You have input %ld Byte dat, continue?[Y/N]", len);                                    ch = getchar();                                    if(ch != 'Y' && ch != 'y')                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                }                            }                            else                            {                                pInode->length = len;                                time(&(pInode->time));                                updateInode(*pInode);                                delete buff;                                return 0;                            }                        }                    }                }                else                {                    pInode->length = len;                    time(&(pInode->time));                    updateInode(*pInode);                    delete buff;                    return 0;                }            }            //写入1个二级索引            unsigned int addrBlockId2 = pInode->addr[11];            int j;            if(addrBlockId2 > 0)            {                //遍历itemTotal个一级索引                for(j = 0; j < itemTotal; j++)                {                    addrBlockId = getItem(addrBlockId2, j);                    if(addrBlockId > 0)                    {                        //遍历itemTotal个直接索引                        for(i = 0; i < itemTotal; i++)                        {                            blockId = getItem(addrBlockId, i);                            if(blockId > 0)                            {                                num = waitForInput(buff, blockSize);                                writeData(blockId, buff, num, 0);                                len += num;                                if(num < blockSize)                                {                                    pInode->length = len;                                    time(&(pInode->time));                                    updateInode(*pInode);                                    delete buff;                                    return 0;                                }                                else                                {                                    printf("You have input %ld Byte dat, continue?[Y/N]", len);                                    ch = getchar();                                    if(ch != 'Y' && ch != 'y')                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                }                            }                            else                            {                                blockId = getAvailableBlockId();                                if(blockId > 0)                                {                                    superBlock.blockFree--;                                    updateSuperBlock(superBlock);                                    blockBitmap[blockId] = 1;                                    updateBlockBitmap(blockBitmap, blockId);                                    updateItem(addrBlockId, i, blockId);                                    time(&(pInode->time));                                    updateInode(*pInode);                                    num = waitForInput(buff, blockSize);                                    writeData(blockId, buff, num, 0);                                    len += num;                                    if(num < blockSize)                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                    else                                    {                                        printf("You have input %ld Byte dat, continue?[Y/N]", len);                                        ch = getchar();                                        if(ch != 'Y' && ch != 'y')                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                    }                                }                                else                                {                                    pInode->length = len;                                    time(&(pInode->time));                                    updateInode(*pInode);                                    delete buff;                                    return 0;                                }                            }                        }                    }                    else                    {                        addrBlockId = getAvailableBlockId();                        if(addrBlockId > 0)                        {                            superBlock.blockFree--;                            updateSuperBlock(superBlock);                            blockBitmap[addrBlockId] = 1;                            updateBlockBitmap(blockBitmap, addrBlockId);                            updateItem(addrBlockId2, j, addrBlockId);                            time(&(pInode->time));                            updateInode(*pInode);                            //                            for(i = 0; i < itemTotal; i++)                            {                                blockId = getItem(addrBlockId, i);                                if(blockId > 0)                                {                                    num = waitForInput(buff, blockSize);                                    writeData(blockId, buff, num, 0);                                    len += num;                                    if(num < blockSize)                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                    else                                    {                                        printf("You have input %ld Byte dat, continue?[Y/N]", len);                                        ch = getchar();                                        if(ch != 'Y' && ch != 'y')                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                    }                                }                                else                                {                                    blockId = getAvailableBlockId();                                    if(blockId > 0)                                    {                                        superBlock.blockFree--;                                        updateSuperBlock(superBlock);                                        blockBitmap[blockId] = 1;                                        updateBlockBitmap(blockBitmap, blockId);                                        updateItem(addrBlockId, i, blockId);                                        time(&(pInode->time));                                        updateInode(*pInode);                                        num = waitForInput(buff, blockSize);                                        writeData(blockId, buff, num, 0);                                        len += num;                                        if(num < blockSize)                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                        else                                        {                                            printf("You have input %ld Byte dat, continue?[Y/N]", len);                                            ch = getchar();                                            if(ch != 'Y' && ch != 'y')                                            {                                                pInode->length = len;                                                time(&(pInode->time));                                                updateInode(*pInode);                                                delete buff;                                                return 0;                                            }                                        }                                    }                                    else                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                }                            }                        }                        else                        {                            pInode->length = len;                            time(&(pInode->time));                            updateInode(*pInode);                            delete buff;                            return 0;                        }                    }                }            }            else            {                addrBlockId2 = getAvailableBlockId();                if(addrBlockId2 > 0)                {                    superBlock.blockFree--;                    updateSuperBlock(superBlock);                    blockBitmap[addrBlockId2] = 1;                    updateBlockBitmap(blockBitmap, addrBlockId2);                    pInode->addr[11] = addrBlockId2;                    time(&(pInode->time));                    updateInode(*pInode);                    //遍历itemTotal一级索引                    for(j = 0; j < itemTotal; j++)                    {                        addrBlockId = getItem(addrBlockId2, j);                        if(addrBlockId > 0)                        {                            //遍历itemTotal个直接索引                            for(i = 0; i < itemTotal; i++)                            {                                blockId = getItem(addrBlockId, i);                                if(blockId > 0)                                {                                    num = waitForInput(buff, blockSize);                                    writeData(blockId, buff, num, 0);                                    len += num;                                    if(num < blockSize)                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                    else                                    {                                        printf("You have input %ld Byte dat, continue?[Y/N]", len);                                        ch = getchar();                                        if(ch != 'Y' && ch != 'y')                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                    }                                }                                else                                {                                    blockId = getAvailableBlockId();                                    if(blockId > 0)                                    {                                        superBlock.blockFree--;                                        updateSuperBlock(superBlock);                                        blockBitmap[blockId] = 1;                                        updateBlockBitmap(blockBitmap, blockId);                                        updateItem(addrBlockId, i, blockId);                                        time(&(pInode->time));                                        updateInode(*pInode);                                        num = waitForInput(buff, blockSize);                                        writeData(blockId, buff, num, 0);                                        len += num;                                        if(num < blockSize)                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                        else                                        {                                            printf("You have input %ld Byte dat, continue?[Y/N]", len);                                            ch = getchar();                                            if(ch != 'Y' && ch != 'y')                                            {                                                pInode->length = len;                                                time(&(pInode->time));                                                updateInode(*pInode);                                                delete buff;                                                return 0;                                            }                                        }                                    }                                    else                                    {                                        pInode->length = len;                                        time(&(pInode->time));                                        updateInode(*pInode);                                        delete buff;                                        return 0;                                    }                                }                            }                        }                        else                        {                            addrBlockId = getAvailableBlockId();                            if(addrBlockId > 0)                            {                                superBlock.blockFree--;                                updateSuperBlock(superBlock);                                blockBitmap[addrBlockId] = 1;                                updateBlockBitmap(blockBitmap, addrBlockId);                                updateItem(addrBlockId2, j, addrBlockId);                                time(&(pInode->time));                                updateInode(*pInode);                                //                                for(i = 0; i < itemTotal; i++)                                {                                    blockId = getItem(addrBlockId, i);                                    if(blockId > 0)                                    {                                        num = waitForInput(buff, blockSize);                                        writeData(blockId, buff, num, 0);                                        len += num;                                        if(num < blockSize)                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                        else                                        {                                            printf("You have input %ld Byte dat, continue?[Y/N]", len);                                            ch = getchar();                                            if(ch != 'Y' && ch != 'y')                                            {                                                pInode->length = len;                                                time(&(pInode->time));                                                updateInode(*pInode);                                                delete buff;                                                return 0;                                            }                                        }                                    }                                    else                                    {                                        blockId = getAvailableBlockId();                                        if(blockId > 0)                                        {                                            superBlock.blockFree--;                                            updateSuperBlock(superBlock);                                            blockBitmap[blockId] = 1;                                            updateBlockBitmap(blockBitmap, blockId);                                            updateItem(addrBlockId, i, blockId);                                            time(&(pInode->time));                                            updateInode(*pInode);                                            num = waitForInput(buff, blockSize);                                            writeData(blockId, buff, num, 0);                                            len += num;                                            if(num < blockSize)                                            {                                                pInode->length = len;                                                time(&(pInode->time));                                                updateInode(*pInode);                                                delete buff;                                                return 0;                                            }                                            else                                            {                                                printf("You have input %ld Byte dat, continue?[Y/N]", len);                                                ch = getchar();                                                if(ch != 'Y' && ch != 'y')                                                {                                                    pInode->length = len;                                                    time(&(pInode->time));                                                    updateInode(*pInode);                                                    delete buff;                                                    return 0;                                                }                                            }                                        }                                        else                                        {                                            pInode->length = len;                                            time(&(pInode->time));                                            updateInode(*pInode);                                            delete buff;                                            return 0;                                        }                                    }                                }                            }                            else                            {                                pInode->length = len;                                time(&(pInode->time));                                updateInode(*pInode);                                delete buff;                                return 0;                            }                        }                    }                }                else                {                    pInode->length = len;                    time(&(pInode->time));                    updateInode(*pInode);                    delete buff;                    return 0;                }            }            pInode->length = len;            time(&(pInode->time));            updateInode(*pInode);            delete buff;            return 0;        }        else        {            printf("%s is a directory\n", name);            return -1;        }    }    else    {        printf("no such file or directory\n");        return -1;    }}/**删除文件finish*/int FileSystem::del(char* name){    //printf("delete file %s in  %s\n", name, curInode.name);    unsigned int id = findChildInode(curLink, name);    if(id > 0)    {        //读取i节点        PInode pInode = new Inode();        getInode(pInode, id);        //删除文件        if(pInode->isDir == 0)        {            if(pInode->type == 0)            {                printf("file %s is Read-Only file\n", name);                return -1;            }            //释放文件内容数据块            int i;            unsigned int blockId;            //遍历10个直接索引,释放数据块            for(i = 0; i < 10; i++)            {                blockId = pInode->addr[i];                //printf("direct addr:%d\n", blockId);                if(blockId > 0)                {                    //更新superBlock                    superBlock.blockFree++;                    updateSuperBlock(superBlock);                    //释放block                    releaseBlock(blockId);                    //更新blockBitmap                    blockBitmap[blockId] = 0;                    updateBlockBitmap(blockBitmap, blockId);                }            }            //遍历1个一级索引            unsigned int addrBlockId = pInode->addr[10];            int totalItem = blockSize/itemSize;            if(addrBlockId > 0)            {                //遍历totalItem个直接索引                for(i = 0; i < totalItem; i++)                {                    blockId = getItem(addrBlockId, i);                    if(blockId > 0)                    {                        //更新superBlock                        superBlock.blockFree++;                        updateSuperBlock(superBlock);                        //释放block                        releaseBlock(blockId);                        //更新blockBitmap                        blockBitmap[blockId] = 0;                        updateBlockBitmap(blockBitmap, blockId);                    }                }                //释放一级索引块                //更新superBlock                superBlock.blockFree++;                updateSuperBlock(superBlock);                //释放block                releaseBlock(addrBlockId);                //更新blockBitmap                blockBitmap[addrBlockId] = 0;                updateBlockBitmap(blockBitmap, addrBlockId);            }            //遍历一个二级索引            unsigned int addrBlockId2 = pInode->addr[11];            if(addrBlockId2 > 0)            {                //遍历totalItem个一级索引                unsigned j;                for(j = 0; j < totalItem; j++)                {                    addrBlockId = getItem(addrBlockId2, j);                    if(addrBlockId > 0)                    {                        //遍历totalItem个直接索引                        for(i = 0; i < totalItem; i++)                        {                            blockId = getItem(addrBlockId, i);                            if(blockId > 0)                            {                                //更新superBlock                                superBlock.blockFree++;                                updateSuperBlock(superBlock);                                //释放block                                releaseBlock(blockId);                                //更新blockBitmap                                blockBitmap[blockId] = 0;                                updateBlockBitmap(blockBitmap, blockId);                            }                        }                        //释放一级索引块                        //更新superBlock                        superBlock.blockFree++;                        updateSuperBlock(superBlock);                        //释放block                        releaseBlock(addrBlockId);                        //更新blockBitmap                        blockBitmap[addrBlockId] = 0;                        updateBlockBitmap(blockBitmap, addrBlockId);                    }                }                //释放二级索引块                //更新superBlock                superBlock.blockFree++;                updateSuperBlock(superBlock);                //释放block                releaseBlock(addrBlockId2);                //更新blockBitmap                blockBitmap[addrBlockId2] = 0;                updateBlockBitmap(blockBitmap, addrBlockId2);            }            //释放i节点            releaseInode(pInode->id);            //更新superBlock            superBlock.inodeNum--;            updateSuperBlock(superBlock);            //更新inodeBitmap            inodeBitmap[pInode->id] = 0;            updateInodeBitmap(inodeBitmap, pInode->id);            //释放目录文件项            releaseItem(pInode->blockId, pInode->id);            //printf("delete file %s\n", pInode->name);        }        //删除目录        else        {            //删除子文件...            cd(name);            FcbLink link = curLink->next;            while(link != NULL)            {                del(link->fcb.name);                link = link->next;            }            cd("..");            if(pInode->type == 0)            {                printf("file %s is Read-Only file\n", name);                return -1;            }            //删除目录文件本身            //释放文件内容数据块            int i;            unsigned int blockId;            //遍历11个直接索引,释放数据块            for(i = 0; i < 11; i++)            {                blockId = pInode->addr[i];                if(blockId > 0)                {                    //更新superBlock                    superBlock.blockFree++;                    updateSuperBlock(superBlock);                    //释放block                    releaseBlock(blockId);                    //更新blockBitmap                    blockBitmap[blockId] = 0;                    updateBlockBitmap(blockBitmap, blockId);                }            }            //遍历1个一级索引            unsigned int addrBlockId = pInode->addr[11];            int totalItem = blockSize/itemSize;            if(addrBlockId > 0)            {                //遍历totalItem个直接索引                for(i = 0; i < totalItem; i++)                {                    blockId = getItem(addrBlockId, i);                    if(blockId > 0)                    {                        //更新superBlock                        superBlock.blockFree++;                        updateSuperBlock(superBlock);                        //释放block                        releaseBlock(blockId);                        //更新blockBitmap                        blockBitmap[blockId] = 0;                        updateBlockBitmap(blockBitmap, blockId);                    }                }                //释放一级索引块                //更新superBlock                superBlock.blockFree++;                updateSuperBlock(superBlock);                //释放block                releaseBlock(addrBlockId);                //更新blockBitmap                blockBitmap[addrBlockId] = 0;                updateBlockBitmap(blockBitmap, addrBlockId);            }            //释放i节点            releaseInode(pInode->id);            //更新superBlock            superBlock.inodeNum--;            updateSuperBlock(superBlock);            //更新inodeBitmap            inodeBitmap[pInode->id] = 0;            updateInodeBitmap(inodeBitmap, pInode->id);            //释放目录文件项            releaseItem(pInode->blockId, pInode->id);            //printf("delete dir %s\n", pInode->name);        }        //更新目录i节点        curInode.length--;        time(&(curInode.time));        updateInode(curInode);        //更新curLink        removeFcbLinkNode(curLink, *pInode);        delete pInode;        return 0;    }    else    {        printf("no such file or directory\n");        return -1;    }}/**重命名文件finish*/int FileSystem::mv(char* name, char* newName){    //printf("rename file %s in %s to %s\n", name, curInode.name, newName);    unsigned int id = findChildInode(curLink, name);    if(id > 0)    {        Inode inode;        getInode(&inode, id);        if(inode.type == 0)        {            printf("file %s is Read-Only file\n", name);            return -1;        }        strcpy(inode.name, newName);        time(&(inode.time));        updateInode(inode);        //update curLink        FcbLink link = curLink->next;        while(link != NULL)        {            if(strcmp(link->fcb.name, name) == 0)            {                strcpy(link->fcb.name, newName);                return 0;            }            link = link->next;        }    }    else    {        printf("no such file or directory:%s\n", name);        return -1;    }}/**复制文件unsurpport because input and output control is difficult*/int FileSystem::cp(char* src, char* dst){    printf("unsurpport command\n");    return 0;}/**修改文件权限:只读/可写finish*/int FileSystem::chmod(char* name, unsigned char type){    //printf("chmod file %s (isDir=%d) in %s to value %d\n", name, isDir, curInode.name, type);    unsigned int id = findChildInode(curLink, name);    if(id > 0)    {        Inode inode;        getInode(&inode, id);        //目录        if(inode.isDir == 1)        {            cd(name);            FcbLink link = curLink->next;            while(link != NULL)            {                chmod(link->fcb.name, type);                link = link->next;            }            cd("..");        }        inode.type = type;        time(&(inode.time));        updateInode(inode);        return 0;    }    else    {        printf("no such file or directory:%s\n", name);        return -1;    }}/**登录文件系统验证finish*/void FileSystem::login(){    char username[10];    char password[10];    while(1)    {        printf("username:");        fgets(username, sizeof(username), stdin);        if(username[strlen(username)-1] == '\n')            username[strlen(username)-1] = '\0';        system("stty -echo");        printf("password:");        fgets(password, sizeof(password), stdin);        if(password[strlen(password)-1] == '\n')            password[strlen(password)-1] = '\0';        system("stty echo");        printf("\n");        if(strcmp(username,user.username)==0 && strcmp(password,user.password)==0)            break;        else        {            printf("username or password is not correct,please try again.\n");        }    }}/**退出账户finish*/void FileSystem::logout(){    //保存数据    updateResource();    printf("%s has logout\n", user.username);    //重新打开系统并进行登录验证,由于命令循环未退出,故会继续接受命令    openFileSystem();    login();}/**退出finish*/void FileSystem::exit(){    //保存数据并彻底退出    printf("Bye!\n");    stopHandle(0);}/**查看文件系统信息finish*/void FileSystem::systemInfo(){    printf("Sum of block number:%d\n",superBlock.blockNum);    printf("Each block size:%d\n",superBlock.blockSize);    printf("Free of block number:%d\n",superBlock.blockFree);    printf("Sum of inode number:%d\n",superBlock.inodeNum);}/**清屏finish*/void FileSystem::clr(){    system("clear");}/**修改账户信息:用户名和密码*/int FileSystem::account(){    char username[10];    char password[10];    system("stty -echo");    printf("old password:");    fgets(password, 10, stdin);    if(password[strlen(password)-1] == '\n')        password[strlen(password)-1] = '\0';    system("stty echo");    printf("\n");    if(strcmp(password,user.password)==0)    {        while(1)        {            printf("new username:");            fgets(username, 10, stdin);            if(username[strlen(username)-1] == '\n')                username[strlen(username)-1] = '\0';            system("stty -echo");            printf("new password:");            fgets(password, 10, stdin);            if(password[strlen(password)-1] == '\n')                password[strlen(password)-1] = '\0';            system("stty echo");            printf("\n");            if(strlen(username) < 2 || strlen(password) < 4)            {                printf("your username or password is too long or too short,please try again\n");            }            else            {                break;            }        }        strcpy(user.username, username);        strcpy(user.password, password);        setUser(user);        printf("modify account info success.\n");        return 0;    }    else    {        printf("password is not correct, you are not permitted to modify account info.\n");        return -1;    }}/**运行文件系统,处理用户命令finish*/void FileSystem::command(){    char input[128];    do    {        showPath();        fgets(input, 128, stdin);        switch(analyse(input))        {            case HELP:                help();                break;            case LS://执行ls或ls-l                if(strcmp(cmd[1], "-l") == 0)                    ls_l();                else                    ls();                break;            case CD:                cd(cmd[1]);                break;            case MKDIR:                createFile(cmd[1],1);                break;            case TOUCH:                createFile(cmd[1],0);                break;            case CAT:                read(cmd[1]);                break;            case WRITE:                write(cmd[1]);                break;            case RM:                if(strcmp(cmd[1], "-r") == 0)                    del(cmd[2]);                else                    del(cmd[1]);                break;            case MV:                mv(cmd[1], cmd[2]);                break;            case CP:                if(strcmp(cmd[1], "-r") == 0)                    cp(cmd[2], cmd[3]);                else                    cp(cmd[1], cmd[2]);                break;            case CHMOD:                if(strcmp(cmd[1], "-r") == 0)                    chmod(cmd[3], cmd[2][0]-'0');                else                    chmod(cmd[2], cmd[1][0]-'0');                break;            case LOGOUT:                logout();                break;            case EXIT:                exit();                break;            case SYSINFO:                systemInfo();                break;            case CLEAR:                clr();                break;            case ACCOUNT:                account();                break;            default:                printf("unsurpport command\n");                break;        }    }while(1);}/**private methods*///user区域操作/**取出user数据finish*/void FileSystem::getUser(User* pUser){    if(fp == NULL || pUser == NULL)    {        return;    }    rewind(fp);    fread(pUser, userSize, 1, fp);}/**更新user数据finish*/void FileSystem::setUser(User user){    if(fp == NULL)    {        return;    }    rewind(fp);    fwrite(&user, userSize, 1, fp);}//superBlock区域操作/**取出superBlock数据finish*/void FileSystem::getSuperBlock(SuperBlock* pSuper){    if(fp == NULL || pSuper == NULL)    {        return;    }    fseek(fp, sOffset, SEEK_SET);    fread(pSuper, superBlockSize, 1, fp);}/**更新superBlock数据finish*/void FileSystem::updateSuperBlock(SuperBlock super){    if(fp == NULL)    {        return;    }    fseek(fp, sOffset, SEEK_SET);    fwrite(&super, superBlockSize, 1, fp);}//blockImage区域操作/**寻找一个空闲的数据块,0号已被分配给根目录,返回值大于0表示找到finish*/unsigned int FileSystem::getAvailableBlockId(){    if(superBlock.blockFree <= 0)    {        printf("no free block\n");        return 0;    }    int i;    for(i = 0; i < blockNum; i++)    {        if(blockBitmap[i] == 0)        {            //printf("find block %d\n", i);            releaseBlock(i);            return i;        }    }    printf("no free block\n");    return 0;}/**取出blockBitmapfinish*/void FileSystem::getBlockBitmap(unsigned char* bitmap){    if(fp == NULL || bitmap == NULL)    {        return;    }    fseek(fp, bbOffset, SEEK_SET);    fread(bitmap, blockBitmapSize, 1, fp);}/**更新blockBitmapfinish*/void FileSystem::updateBlockBitmap(unsigned char* bitmap, unsigned int index){    this->updateBlockBitmap(bitmap, index, 1);    //printf("update blockBitmap index=%d, value=%d\n", index, bitmap[index]);}/**更新blockBitmapfinish*/void FileSystem::updateBlockBitmap(unsigned char* bitmap, unsigned int start, unsigned int count){    if(fp == NULL)    {        return;    }    fseek(fp, bbOffset+start, SEEK_SET);    fwrite(bitmap+start, count, 1, fp);}//inodeImage区域操作/**寻找一个空闲的i节点块,0号已被分配给根目录,返回值大于0表示找到finish*/unsigned int FileSystem::getAvailableInodeId(){    unsigned int i;    for(i = 0; i < blockNum; i++)    {        if(inodeBitmap[i] == 0)        {            //printf("find inode %d\n", i);            return i;        }    }    return 0;}/**取出inodeBitmapfinish*/void FileSystem::getInodeBitmap(unsigned char* bitmap){    if(fp == NULL || bitmap == NULL)    {        return;    }    fseek(fp, ibOffset, SEEK_SET);    fread(bitmap, inodeBitmapSize, 1, fp);}/**更新inodeBitmapfinish*/void FileSystem::updateInodeBitmap(unsigned char* bitmap, unsigned int index){    this->updateInodeBitmap(bitmap, index, 1);}/**更新inodeBitmapfinish*/void FileSystem::updateInodeBitmap(unsigned char* bitmap, unsigned int start, unsigned int count){    if(fp == NULL)    {        return;    }    fseek(fp, ibOffset+start, SEEK_SET);    fwrite(bitmap+start, count, 1, fp);}//inode block区域操作/**取出一条inodefinish*/void FileSystem::getInode(PInode pInode, unsigned int id){    if(fp == NULL || pInode == NULL)    {        return;    }    fseek(fp, iOffset+inodeSize*id, SEEK_SET);    fread(pInode, inodeSize, 1, fp);}/**更新一条inodefinish*/void FileSystem::updateInode(Inode inode){    if(fp == NULL )    {        return;    }    fseek(fp, iOffset+inodeSize*inode.id, SEEK_SET);    fwrite(&inode, inodeSize, 1, fp);}/**释放一条inodefinish*/void FileSystem::releaseInode(unsigned int id){    if(fp == NULL )    {        return;    }    fseek(fp, iOffset+inodeSize*id, SEEK_SET);    int i;    for(i = 0; i < inodeSize; i++)    {        fputc(0, fp);    }}//data block区域操作//地址或文件项/**寻找一个当前目录文件中可用的文件项,返回数据块地址和文件项索引,大于0表示找到finish*/unsigned int FileSystem::getAvailableFileItem(Inode& inode, unsigned int* availableIndex){    //遍历建立子文件或子目录节点    int i;    unsigned int index;    unsigned int blockId;    unsigned int fileItem;    Inode fileInode;    const int itemTotal = blockSize/itemSize;    //遍历11个直接索引    for(i = 0; i < 11; i++)    {        blockId = inode.addr[i];        //直接索引数据块已分配,直接查找        if(blockId > 0 || inode.id == 0)        {            //遍历直接索引下itemTotal个fileItem项(文件i节点索引),查找            for(index = 0; index < itemTotal; index++)            {                fileItem = getItem(blockId, index);                //printf("%d [%d] = %d\n", blockId, index, fileItem);                //读取i子文件或子目录i节点                if(fileItem  == 0)                {                    *availableIndex = index;                    return blockId;                }            }        }        //直接索引数据块未分配,分配成功后立即返回,        else        {            blockId = getAvailableBlockId();            //分配成功            if(blockId > 0)            {                //更新superBlock                superBlock.blockFree--;                updateSuperBlock(superBlock);                //更新blockBitmap                blockBitmap[blockId] = 1;                updateBlockBitmap(blockBitmap, blockId);                //更新i节点                inode.addr[i] = blockId;                updateInode(inode);                //直接返回第0个                *availableIndex = 0;                return blockId;            }            //分配失败            else            {                return 0;            }        }    }    //遍历一级索引1个    unsigned int addrBlockId = inode.addr[11];    //一级索引数据块已分配    if(addrBlockId > 0)    {        //遍历一级索引下itemTotal个直接索引        for(i = 0; i < itemTotal; i++)        {            //直接索引数据块已分配,直接查找            if(blockId > 0)            {                //遍历直接索引下itemTotal个fileItem项(文件i节点索引),查找                for(index = 0; index < itemTotal; index++)                {                    fileItem = getItem(blockId, index);                    //读取i子文件或子目录i节点                    if(fileItem  == 0)                    {                        *availableIndex = index;                        return blockId;                    }                }            }            //直接索引数据块未分配,分配成功后立即返回,            else            {                blockId = getAvailableBlockId();                //分配成功                if(blockId > 0)                {                    //更新superBlock                    superBlock.blockFree--;                    updateSuperBlock(superBlock);                    //更新blockBitmap                    blockBitmap[blockId] = 1;                    updateBlockBitmap(blockBitmap, blockId);                    //更新i节点                    inode.addr[i] = blockId;                    updateInode(inode);                    //直接返回第0个                    *availableIndex = 0;                    return blockId;                }            //分配失败            else            {                return 0;            }        }        }    }    //一级索引数据块未分配    else    {        addrBlockId = getAvailableBlockId();        //一级索引数据块分配成功        if(addrBlockId > 0)        {            //更新superBlock            superBlock.blockFree--;            updateSuperBlock(superBlock);            //更新blockBitmap            blockBitmap[addrBlockId] = 1;            updateBlockBitmap(blockBitmap, addrBlockId);            //更新i节点            inode.addr[11] = addrBlockId;            updateInode(inode);            //一级索引数据块第一项直接索引分配数据块            blockId = getAvailableBlockId();            //分配成功            if(blockId > 0)            {                //更新superBlock                superBlock.blockFree--;                updateSuperBlock(superBlock);                //更新blockBitmap                blockBitmap[blockId] = 1;                updateBlockBitmap(blockBitmap, blockId);                //更新一级索引第一项直接索引数据块                updateItem(addrBlockId, 0, blockId);                //直接返回第0个                *availableIndex = 0;                return blockId;            }        }        //一级索引数据块分配失败        else        {            return 0;        }    }}/**取出一个地址项或文件项,针对目录的操作finish*/unsigned int FileSystem::getItem(unsigned int blockId, unsigned int index){    unsigned int value = 0;    if(fp == NULL)    {        return value;    }    fseek(fp, bOffset+blockSize*blockId+itemSize*index, SEEK_SET);    fread(&value, itemSize, 1, fp);    return value;}/**更新一个地址项或文件项finish*/void FileSystem::updateItem(unsigned int blockId, unsigned int index, unsigned int value){    if(fp == NULL)    {        return;    }    fseek(fp, bOffset+blockSize*blockId+itemSize*index, SEEK_SET);    fwrite(&value, itemSize, 1, fp);}/**释放一个地址项或文件项finish*/void FileSystem::releaseItem(unsigned int blockId, unsigned int id){    int itemTotal = blockSize/itemSize;    int i;    unsigned int itemId;    fseek(fp, bOffset+blockSize*blockId, SEEK_SET);    for(i = 0; i < itemTotal; i++)    {        fread(&itemId, itemSize, 1, fp);        if(itemId == id)        {            //printf("release item id=%d in %d\n", id, blockId);            fseek(fp, -itemSize, SEEK_CUR);            itemId = 0;            fwrite(&itemId, itemSize, 1, fp);            return;        }    }}//文件内容/**取出一个数据块的全部或部分,针对文件的操作finish*/int FileSystem::getData(unsigned int blockId, char* buff, unsigned int size, unsigned int offset){    int len = 0;    if(fp == NULL || buff == NULL || offset >= blockSize)    {        return len;    }    fseek(fp, bOffset+blockSize*blockId, SEEK_SET);    if(size > blockSize-offset)        size = blockSize-offset;    len = fread(buff, size, 1, fp);    return len;}/**写入一个数据块的全部或部分,针对文件的操作finish*/int FileSystem::writeData(unsigned int blockId, char* buff, unsigned int size, unsigned int offset){    int len = 0;    if(fp == NULL || buff == NULL || offset >= blockSize)    {        return len;    }    fseek(fp, bOffset+blockSize*blockId, SEEK_SET);    if(size > blockSize-offset)        size = blockSize-offset;    len = fwrite(buff, size, 1, fp);    return len;}/**释放一个数据块finish*/void FileSystem::releaseBlock(unsigned int blockId){    if(fp == NULL)    {        return;    }    fseek(fp, bOffset+blockSize*blockId, SEEK_SET);    int i;    for (i = 0; i < blockSize; i++)    {        fputc(0, fp);    }    //printf("release block %d\n", blockId);}//定位操作/**寻找目录下的文件或子目录,返回i节点索引,大于0表示找到finish*/unsigned int FileSystem::findChildInode(FcbLink curLink, char* name){    if(curLink == NULL || name == NULL)    {        return 0;    }    FcbLink link = curLink->next;    while(link != NULL)    {        if(strcmp(link->fcb.name, name) == 0)        {            return link->fcb.id;        }        link = link->next;    }    return 0;}//目录信息链操作/**构建一个FcbLinkNodefinish*/void FileSystem::getFcbLinkNode(FcbLink pNode, Inode inode){    if(pNode == NULL)    {        return;    }    pNode->fcb.id = inode.id;    strcpy(pNode->fcb.name, inode.name);    pNode->fcb.isDir = inode.isDir;    pNode->fcb.blockId = inode.blockId;    pNode->next = NULL;}/**建立目录的信息链finish*/void FileSystem::getFcbLink(FcbLink& curLink, Inode inode){    if(curLink != NULL)    {        releaseFcbLink(curLink);    }    //目录本身节点    //printf("start read dir self inode\n");    curLink = new FcbLinkNode();    getFcbLinkNode(curLink, inode);    //printf("end read dir self inode\n");    if(inode.length <= 0)        return;    //遍历建立子文件或子目录节点    int i;    unsigned int index;    unsigned int blockId;    unsigned int fileItem;    Inode fileInode;    FcbLink pNode;    FcbLink link = curLink;    unsigned long len = inode.length;//子文件或子目录数    const int itemTotal = blockSize/itemSize;    //遍历11个直接索引    for(i = 0; i < 11; i++)    {        blockId = inode.addr[i];        if(blockId > 0 || curInode.id == 0)        {            //遍历直接索引下itemTotal个fileItem项(文件i节点索引)            for(index = 0; index < itemTotal; index++)            {                fileItem = getItem(blockId, index);                //读取i子文件或子目录i节点                if(fileItem > 0)                {                    getInode(&fileInode, fileItem);                    pNode = new FcbLinkNode();                    getFcbLinkNode(pNode, fileInode);                    link->next = pNode;                    link = pNode;                    len--;                    //printf("read dir item inode: id=%d, name=%s, index=%d\n", fileItem, fileInode.name, index);                    if(len <= 0)                    {                        return;                    }                }            }        }    }    //遍历一级索引1个    unsigned int addrBlockId = inode.addr[11];    if(addrBlockId > 0)    {        //遍历一级索引下itemTotal个直接索引        for(i = 0; i < itemTotal; i++)        {            blockId = inode.addr[i];            if(blockId > 0)            {                //遍历直接索引下itemTotal个fileItem项(文件i节点索引)                for(index = 0; index < itemTotal; index++)                {                    fileItem = getItem(blockId, index);                    //读取i子文件或子目录i节点                    if(fileItem > 0)                    {                        getInode(&fileInode, fileItem);                        pNode = new FcbLinkNode();                        getFcbLinkNode(pNode, fileInode);                        link->next = pNode;                        link = pNode;                        len--;                        //printf("read dir item inode: id=%d, name=%s, index=%d\n", fileItem, fileInode.name, index);                        if(len <= 0)                            return;                    }                }            }        }    }}/**目录信息链增加一个节点,不能增加根节点finish*/void FileSystem::appendFcbLinkNode(FcbLink curLink, Inode inode){    if(curLink == NULL || inode.id <= 0)    {        return;    }    FcbLink link = curLink;    while(link->next != NULL)    {        link = link->next;    }    FcbLink pNode = new FcbLinkNode();    getFcbLinkNode(pNode, inode);    link->next = pNode;}/**目录信息链删除一个节点,不能删除根节点finish*/void FileSystem::removeFcbLinkNode(FcbLink curLink, Inode inode){    if(curLink == NULL || inode.id <= 0)    {        return;    }    FcbLink link = curLink->next;    FcbLink last = curLink;    while(link != NULL)    {        if(link->fcb.id == inode.id)        {            last->next = link->next;            delete link;            break;        }        last = link;        link = link->next;    }}/**目录信息链删除一个节点,不能删除根节点finish*/void FileSystem::removeFcbLinkNode(FcbLink curLink, char* name){    if(curLink == NULL || name == NULL)    {        return;    }    FcbLink link = curLink->next;    FcbLink last = curLink;    while(link != NULL)    {        if(strcmp(link->fcb.name, name) == 0)        {            last->next = link->next;            delete link;            break;        }        last = link;        link = link->next;    }}/**清空并释放目录信息链finish*/void FileSystem::releaseFcbLink(FcbLink& curLink){    FcbLink link = curLink;    FcbLink tmp;    while(link != NULL)    {        tmp = link->next;        delete link;        link = tmp;    }    curLink = NULL;}//private system methods/**分析命令finish*/int FileSystem::analyse(char* str){    int i;    for(i = 0; i < 5; i++)        cmd[i][0] = '\0';    sscanf(str, "%s %s %s %s %s",cmd[0], cmd[1], cmd[2], cmd[3], cmd[4]);    for(i = 1; i < 17; i++)    {        if(strcmp(cmd[0], SYS_CMD[i]) == 0)        {            return i;        }    }    return 0;}/**停止控制输入捕获,更新并关闭文件,最后直接退出finish*/void FileSystem::stopHandle(int sig){    //printf("\nUpdating resource, please wait...\n");    updateResource();    ::exit(0);}/**更新文件系统头部信息,关闭文件finish*/void FileSystem::updateResource(){    rewind(fp);    fwrite(&user, userSize, 1, fp);    fwrite(&superBlock, superBlockSize, 1, fp);    fwrite(blockBitmap, blockBitmapSize, 1, fp);    fwrite(inodeBitmap, inodeBitmapSize, 1, fp);    fclose(fp);}/**输出当前路径作为命令提示符号finish*/void FileSystem::showPath(){    printf("%s@localhost %s>",user.username, curPath.data());}//util/**显示文件摘要finish*/void FileSystem::showFileDigest(FcbLink pNode){    if(pNode == NULL)        return;    printf("%s",pNode->fcb.name);    if(pNode->fcb.isDir==1)    {        printf("/");    }    printf("\n");}/**显示文件详情finish*/void FileSystem::showFileDetail(PInode pInode){    if(pInode == NULL)        return;    //format output    if(pInode->isDir == 1)    {        printf("%c", 'd');    }    else    {        printf("%c", '-');    }    printf("%c", 'r');    if(pInode->type == 1)    {        printf("%c", 'w');    }    else    {        printf("%c", '-');    }    printf(" %10d", pInode->length);    printf(" %.12s", 4 + ctime(&(pInode->time)));    printf(" %s", pInode->name);    printf("\n");}/**等待数据输入*/unsigned int FileSystem::waitForInput(char* buff, unsigned int limit){    unsigned int len = 0;    char ch[3];    ch[0] = 0;    ch[1] = 0;    while(len < limit)    {        ch[2] = getchar();        if(ch[0] == '<' && ch[1] == '/' && ch[2] == '>')        {            len -= 2;            buff[len] = '\0';            return len;        }        else        {            ch[0] = ch[1];            ch[1] = ch[2];            buff[len] = ch[2];            len++;        }    }    buff[len] = '\0';    return len;}

main.cpp 文件系统调用

#include <iostream>#include "FileSystem.h"using namespace std;int main(int argc, char* argv[]){    FileSystem file(argv[1]);    file.init();    cout << "Hello world!" << endl;    return 0;}

test.c 附:文件系统用户名和密码找回

#include <stdio.h>#include <stdlib.h>int main(int argc, char* argv[]){    FILE* fp = fopen(argv[1], "rb");    char username[10];    char password[10];    fread(username, sizeof(username), 1, fp);    fread(password, sizeof(password), 1, fp);    fclose(fp);    printf("username:%s\npassword:%s\n", username, password);    return 0;}

编译方法:

生成可执行文件system

$ g++ -o system main.cpp FileSystem.cpp

运行方法:

打开或创建systemFile,并以此为基础启动文件系统

$ ./system systemFile

附:

用于忘记文件系统用户名和密码时找回

$ gcc -o test test.c$ ./test systemFile

使用方法(类似于linux终端命令):

帮助(会提示命令操作)

> help 

系统信息

> sysinfo 

退出账户

> logout

修改账户(username,password)

> account 

清屏

> clear 

列出目录下所有文件摘要

> ls 

列出目录下所有文件详情

> ls -l 

进入子目录dir或父目录,暂不支持进入任意层次目录

> cd dir(..) 

创建目录dir

> mkdir dir 

创建文件file

> touch file 

查看文件

> cat file 

写入文件,暂时只支持标准输入,以

> write file 

删除文件file或删除目录dir及其子文件

> rm file(dir) 

暂不支持文件复制

> cp src dst 

重命名文件oldFileName为newFileName

> mv oldFileName newFileName 

修改文件file或目录dir及其子文件读写权限为只读(0)或读写(1)

> chmod 0(1) file(dir) 

退出文件系统

> exit 
0 0