您的位置:首页 > 运维架构 > Linux

linux下简单模拟文件系统

2016-03-21 13:32 519 查看

整体思路:

文件系统基于一个大文件实现

大文件数据分为几个区域来模拟简单的文件系统

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 16

using 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-dir
finish
*/
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;
}

/**
取出blockBitmap
finish
*/
void FileSystem::getBlockBitmap(unsigned char* bitmap)
{
if(fp == NULL || bitmap == NULL)
{
return;
}
fseek(fp, bbOffset, SEEK_SET);
fread(bitmap, blockBitmapSize, 1, fp);
}

/**
更新blockBitmap
finish
*/
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]);
}

/**
更新blockBitmap
finish
*/
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;
}

/**
取出inodeBitmap
finish
*/
void FileSystem::getInodeBitmap(unsigned char* bitmap)
{
if(fp == NULL || bitmap == NULL)
{
return;
}
fseek(fp, ibOffset, SEEK_SET);
fread(bitmap, inodeBitmapSize, 1, fp);
}

/**
更新inodeBitmap
finish
*/
void FileSystem::updateInodeBitmap(unsigned char* bitmap, unsigned int index)
{
this->updateInodeBitmap(bitmap, index, 1);
}

/**
更新inodeBitmap
finish
*/
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区域操作
/**
取出一条inode
finish
*/
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);
}

/**
更新一条inode
finish
*/
void FileSystem::updateInode(Inode inode)
{
if(fp == NULL )
{
return;
}
fseek(fp, iOffset+inodeSize*inode.id, SEEK_SET);
fwrite(&inode, inodeSize, 1, fp);
}

/**
释放一条inode
finish
*/
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;
}

//目录信息链操作
/**
构建一个FcbLinkNode
finish
*/
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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  linux 文件系统