?? filesystem.cpp
字號:
#include <iostream.h>
#include <stdio.h>
#include <string.h>
#include "FileSystem.h"
#include "string2"
#include "Util.h"
SuperBlock sb;
FILE* fd;
hinode hinode[NHINO];
SysOFile sys_ofile[100];
unsigned long FileSystem::mapAddr(unsigned int id) {
unsigned long addr;
addr = this->IN_Start+sizeof(DInode)*(id-1);
return addr;
}
void FileSystem::SaveSuperBlock() {
fseek(fd, 0, 0);
fwrite(&sb, 1, sizeof(SuperBlock), fd);
}
FileSystem::~FileSystem() {}
FileSystem::FileSystem() {
strcpy(this->Disk_Name, "FileSystem.disk");
this->LoginNum = 0;
this->IN_Start = BlockSize * 2;
this->Data_Start = BlockSize * (2 + 400);
this->GroupSize = 50;
}
void FileSystem::ShowList(const char* usn) {
if (!this->CheckLogin(usn)) return;
unsigned int curDir = this->LoginUser[this->UNameI(usn)].CurDirInodeID;
INode* inode = this->IGet(curDir);
Direct dir;
fseek(fd, inode->addr[0]*BlockSize, 0);
fread(&dir, 1, sizeof(Direct), fd);
this->IPut(inode);
int i = 0;
if (curDir != this->LoginUser[this->UNameI(usn)].user.Dino) {
i = 1;
cout << "文件總數: " << dir.size-1 << endl;
} else {
cout << "文件總數: " << dir.size << endl;
}
for (; i<dir.size; i++) {
cout << "名稱:" << dir.files[i].name << '\t';
inode = this->IGet(dir.files[i].Dino);
if (inode->size == 0)
cout << "物理地址:" << this->mapAddr(inode->Dino) << "\t大小:" << "1 KB";
else
cout << "物理地址:" << inode->addr[0]*BlockSize << "\t大小:" << inode->size << " KB";
cout << "\t保護碼:" << inode->type;
int di_mode, one;
for (int j=0; j<4; j++) {
di_mode = inode->mode;
one = di_mode % 2;
di_mode = di_mode / 2;
if (one) cout << 'x';
else cout << '*';
}
cout << endl;
}
}
void FileSystem::MakeDir(const char *usn, const char *name) {
if (!this->CheckLogin(usn)) return;
if (!u.regTest("^[a-zA-Z0-9._]{1,16}$", name)) {
cout << "目錄名稱只能是1至16位字母或數字或點號下劃線組成!" << endl;
return;
}
unsigned int dinodeid = this->NameI(usn, name);
if (dinodeid != 0) {
cout << "相同名稱的文件或目錄已經存在!" << endl;
return;
}
Direct dir;
dir.size = 1;
strcpy(dir.files[0].name, "..");
dir.files[0].Dino = this->LoginUser[this->UNameI(usn)].CurDirInodeID;
unsigned int Bid = this->BAlloc();
if (Bid == 0) {
return;
}
INode* inode = this->IAlloc();
if (inode == NULL) {
this->BFree(Bid);
return;
}
fseek(fd, Bid*BlockSize, 0);
fwrite(&dir, 1, sizeof(Direct), fd);
inode->size = 1;
inode->addr[0] = Bid;
inode->type = 'd';
inode->mode = '0';
Bid = inode->Dino;
this->IPut(inode);
File file;
strcpy(file.name, name);
file.Dino = Bid;
unsigned int curDir = this->LoginUser[this->UNameI(usn)].CurDirInodeID;
INode* inode2 = this->IGet(curDir);
fseek(fd, inode2->addr[0]*BlockSize, 0);
fread(&dir, 1, sizeof(Direct), fd);
dir.files[dir.size] = file;
dir.size++;
fseek(fd, inode2->addr[0]*BlockSize, 0);
fwrite(&dir, 1, sizeof(Direct), fd);
this->IPut(inode2);
cout << "目錄創建成功!" << endl;
}
// 創建文件
void FileSystem::MakeFile(const char *usn, const char *filename) {
if (!this->CheckLogin(usn)) return; // 用戶登錄檢測
if (!u.regTest("^[a-zA-Z0-9._]{1,16}$", filename)) { // 文件名合法性檢測
cout << "文件名稱只能是1至16位字母或數字或點號下劃線組成!" << endl;
return;
}
// 調用 NameI 方法通過名稱找到索引節點編號
unsigned int dinodeid = this->NameI(usn, filename);
if (dinodeid != 0) {
cout << "相同名稱的文件或目錄已經存在!" << endl;
return;
}
// 分配 索引節點
INode* inode = this->IAlloc();
if (inode == NULL) return;
// 填入初始化信息
inode->size = 0;
inode->type = 'f';
inode->mode = '1';
// 初始化文件
File file;
strcpy(file.name, filename);
file.Dino = inode->Dino;
this->IPut(inode);
// 將新文件插入目錄表中
unsigned int curDir = this->LoginUser[this->UNameI(usn)].CurDirInodeID;
INode* inode2 = this->IGet(curDir);
Direct dir;
fseek(fd, inode2->addr[0]*BlockSize, 0);
fread(&dir, 1, sizeof(Direct), fd);
dir.files[dir.size] = file;
dir.size++;
fseek(fd, inode2->addr[0]*BlockSize, 0);
fwrite(&dir, 1, sizeof(Direct), fd);
this->IPut(inode2);
cout << "文件創建成功!" << endl;
}
void FileSystem::IFree(unsigned int dinodeid) {
unsigned int id;
unsigned long addr;
DInode dino;
if (sb.pFI == 100) { // 棧滿
for (int i=0; i<50; i++) { // 取一半存盤
id = sb.FIS[sb.pFI-1];
addr = this->mapAddr(id);
fseek(fd, addr, 0);
fread(&dino, 1, sizeof(DInode), fd);
dino.type = 's';
fwrite(&dino, 1, sizeof(DInode), fd);
}
}
sb.FIS[sb.pFI] = dinodeid;
sb.FINum++;
sb.pFI++;
}
INode* FileSystem::IAlloc() {
INode* temp_inode;
int i, count;
unsigned long addr;
if (sb.FINum == 0) {
cout << "無法再分配更多的 I 結點!" << endl;
return NULL;
}
if (sb.pFI == 0) { // 棧空, 補棧
i = 0;
count = 0;
DInode in;
for (i=0; i<IBlockNum*BlockSize/sizeof(DInode); i++) {
addr = this->mapAddr(i);
fseek(fd, addr, 0);
fread(&in, 1, sizeof(DInode), fd);
if (in.type == 'e') {
sb.FIS[sb.pFI] = in.no;
in.type = 's';
fseek(fd, addr, 0);
fwrite(&in, 1, sizeof(DInode), fd);
sb.pFI++;
count++;
if (count == 50) {
break;
}
}
}
}
unsigned int id = sb.FIS[sb.pFI-1];
temp_inode = this->IGet(id);
//temp_inode->type = 's';
addr = this->mapAddr(id);
fseek(fd, addr, 0);
fwrite(&temp_inode->di_number, 1, sizeof(DInode), fd);
sb.pFI--;
sb.FINum--;
sb.SysMod = 0;
this->SaveSuperBlock();
return temp_inode;
}
INode* FileSystem::IGet(unsigned int dinodeid) {
int inodeid = dinodeid % NHINO;
int existed = 0;
long addr;
INode *temp, *newinode;
if (hinode[inodeid].iForw != NULL) {
// 如果 HASH 表中該 HASH 隊列不為空, 查找節點
temp = hinode[inodeid].iForw;
while (temp) {
if (temp->i_ino == inodeid) {
// 如果找到該索引節點
existed = 1;
temp->Icount++;
return temp;
} else {
temp = temp->iForw;
}
}
}
// HASH 表中不存在該節點, 則計算對應磁盤 I節點 地址
addr = this->mapAddr(dinodeid);
// 分配內存, 并從磁盤載入信息
newinode = (INode*)malloc(sizeof(INode));
fseek(fd, addr, 0);
fread(&newinode->di_number, 1, sizeof(DInode), fd);
// 將該節點置入 HASH 表中
newinode->iForw = hinode[inodeid].iForw;
newinode->iBack = newinode;
if (newinode->iForw != NULL) {
newinode->iForw->iBack = newinode;
}
hinode[inodeid].iForw = newinode;
// 填好初始化信息
newinode->Icount = 1;
newinode->flag = 0; // 標記是否被更新
newinode->i_ino = inodeid;
// newinode->di_size=3*(DIRSIZ+2);
// if(dinodeid == 3) newinode->di_size=BLOCKSIZ;
return newinode;
}
void FileSystem::IPut(INode* pinode) {
unsigned long addr;
addr = this->mapAddr(pinode->Dino);
fseek(fd, addr, 0);
fwrite(&pinode->di_number, 1, sizeof(DInode), fd);
if (pinode->Icount > 1) {
pinode->Icount--;
return;
}
if (pinode->iForw == NULL) {
pinode->iBack->iForw = NULL;
} else {
pinode->iForw->iBack = pinode->iBack;
pinode->iBack->iForw = pinode->iForw;
}
/*
if (pinode->di_number != 0) {
addr = this->mapAddr(pinode->Dino);
fseek(fd, addr, 0);
fwrite(&pinode->di_number, 1, sizeof(DInode), fd);
} else {
for (int i=0; i<pinode->size; i++) {
this->BFree(pinode->addr[i]);
}
//this->IFree(pinode->Dino);
}
if (pinode->iForw == NULL) {
pinode->iBack->iForw = NULL;
} else {
pinode->iForw->iBack = pinode->iBack;
pinode->iBack->iForw = pinode->iForw;
}
this->IFree(pinode->Dino);*/
}
unsigned int FileSystem::NameI(const char *usn, const char *name) {
if (0==strcmp("/", name)) {
return this->LoginUser[this->UNameI(usn)].user.Dino;
} else if (0==strcmp(".", name)) {
return this->LoginUser[this->UNameI(usn)].CurDirInodeID;
} else {
unsigned int curDir = this->LoginUser[this->UNameI(usn)].CurDirInodeID;
INode* inode = this->IGet(curDir);
Direct dir;
fseek(fd, inode->addr[0] * BlockSize, 0);
fread(&dir, 1, sizeof(Direct), fd);
this->IPut(inode);
for (int i=0; i<dir.size; i++) {
if (strcmp(dir.files[i].name, name)==0) {
return dir.files[i].Dino;
}
}
return 0;
}
}
void FileSystem::ChangeDir(const char *usn, const char *name) {
if (!this->CheckLogin(usn)) return;
int dinodeid = this->NameI(usn, name);
if (dinodeid==0) {
cout << "目錄不存在!" << endl;
return;
}
INode* inode = this->IGet(dinodeid);
if (inode == NULL) {
cout << "目錄不存在!" << endl;
return;
}
if (inode->type != 'd') {
cout << "目錄不存在!" << endl;
return;
}
// cout << "當前目錄:" << name << endl;
int uid = this->UNameI(usn);
this->LoginUser[uid].CurDirInodeID = dinodeid;
}
bool FileSystem::Login(const char *usn, const char *pwd) {
if (this->LoginNum > 3) {
cout << "當前系統太多人登錄,請稍后登錄!" << endl;
return 0;
}
int i;
for (i=0; i<this->LoginNum; i++) {
if (strcmp(usn, this->LoginUser[i].user.usn)==0) {
cout << "您已經登陸,不用重復登錄!" << endl;
return 0;
}
}
for (i=0; i<4; i++) {
if (strcmp(this->AllUser[i].usn, usn)==0 && strcmp(this->AllUser[i].pwd, pwd)==0) {
cout << "登錄成功!" << endl;
this->LoginUser[this->LoginNum].user = this->AllUser[i];
this->LoginNum++;
LoginUser[this->LoginNum].CurDirInodeID = this->AllUser[i].Dino;
this->ChangeDir(usn, "/");
return 1;
}
}
cout << "你輸入的用戶名或者密碼不正確!" << endl;
return 0;
}
void FileSystem::Logout(const char *usn) {
if (!this->CheckLogin(usn)) return;
int j, k;
for (int i=0; i<this->LoginNum; i++) {
if (strcmp(this->LoginUser[i].user.usn, usn)==0) {
int uid = this->UNameI(usn);
for (k=0; k<100; k++) {
if (sys_ofile[k].f_count > 0 && sys_ofile[k].uid == uid) {
this->Close(usn, k);
}
}
for (j=i; j<3; j++) {
this->LoginUser[j] = this->LoginUser[j+1];
}
this->LoginNum--;
cout << "登出成功!" << endl;
return;
}
}
}
int FileSystem::CheckLogin(const char *usn) {
for (int i=0; i<this->LoginNum; i++) {
if (strcmp(this->LoginUser[i].user.usn, usn)==0) {
return 1;
}
}
cout << "對不起,您還未登錄,請先登錄!" << endl;
return 0;
}
void FileSystem::Load() {
fd = fopen(this->Disk_Name, "r+w+b");
if (fd == NULL) {
cout << "文件系統無法加載!" << endl;
exit(0);
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -