Linux 文件系統實現代碼

/*
 * main.cpp
 *
 * 
 */
#include <iostream>
#include <stdlib.h>
#include<string.h>
#include<curses.h>
using namespace std;
typedef struct User
{
	string name[30];
	string passwd[30];
	int n;
} User, u;
typedef struct Priv
{
	char read;
	char write;
	char execute;
} Priv, priv[3];
//記錄文件信息。name表示第幾塊,用disk模擬
typedef struct DataStock
{
	int name;  //第幾盤塊號
	int stock_num;
	struct DataStock *next;
} DataStock, *ds;
// 一個節點信息,可能是一個目錄或者一個文件。
// 如果是一個目錄,那麼下面會有子目錄childnode, inode_num,
//記錄子目錄項的數目
typedef struct Inode
{
	int inode_num;
	int type; 			//文件類型,文件/目錄  0/1
	float size;
	Priv *priv;
	char* owneruser;
	struct tm *createtime;
	struct Inode** childnode;
	struct DataStock *datastock;
} Inode;
//一個目錄項,
typedef struct Dentry
{
	string name;
	struct Inode *inode;
} Dentry;

int number = 1000;

//默認路徑是/home, 用戶名是" ".
string rootDirect = "/home";
string currentUser = " ";
string currentPath = rootDirect;

User user;
Dentry dentry[1000];
int of_record = 0;
int record = -1;


//磁盤塊
int disk_record = 0;//記錄使用了多少磁盤塊
int disk_stock = 3; //三個字節爲一個盤塊
string *disk = new string[number]; //模擬磁盤存儲  1000個磁盤塊
int firstempty = 0;

// 命令行
int command_number = 10;
int command_record = 0;
string *commandsave = new string[command_number];
int umask_direct = 775;
int umask_file = 664;
void test()
{
	for (int i = 0; i < disk_record; i++)
	{
		cout << disk[i];
	}
}
void showDisk()
{
	for (int i = 0; i < disk_record; i++)
	{
		cout << "第" << i << "個磁盤塊:" << disk[i] << endl;
	}
}
void output()
{
	cout << "[" << currentUser << "@" << "localhost" << currentPath << "]#";
}
//數據塊節點初始化
DataStock *initializeStock()
{
	DataStock *head;
	head = (DataStock*) malloc(sizeof(DataStock));
	head->name = -1;
	head->next = NULL;
	return head;
}
//inode節點初始化
// 跟蹤 // initalizeInode(1,"home",-1)
Inode *initializeInode(int type, string u, int p)
{
	Inode *inode = NULL;
	inode = (Inode*) malloc(sizeof(Inode));
	inode->childnode = (Inode**) malloc(100 * sizeof(Inode*));
	inode->inode_num = 0;
	inode->type = type;
	inode->datastock = initializeStock();
	inode->size = 0;
	if(p == 0)
		inode->owneruser = (char*) u.data();
	else
		inode->owneruser = (char*) currentUser.data();
	time_t ctime;
	time(&ctime);
	inode->createtime = localtime(&ctime);
//權限初始化
	Priv *priv = (Priv*) malloc(sizeof(Priv));
	if(type == 0) //文件
	{
		priv[0].read = 'r';
		priv[0].write = 'w';
		priv[0].execute = '-';
		priv[1].read = 'r';
		priv[1].write = 'w';
		priv[1].execute = '-';
		priv[2].read = 'r';
		priv[2].write = '-';
		priv[2].execute = '-';
	}
	else
	{ //目錄
		priv[0].read = 'r';
		priv[0].write = 'w';
		priv[0].execute = 'x';
		priv[1].read = 'r';
		priv[1].write = 'w';
		priv[1].execute = 'x';
		priv[2].read = 'r';
		priv[2].write = '-';
		priv[2].execute = '-';
	}
	inode->priv = priv;
	return inode;
}
//根據目錄項名字找對應的目錄項
Dentry findDentry(char *dentryname)
{
	Dentry temp;
	for (int i = 0; i <= record; i++)
	{
		if(strcmp((char*) dentry[i].name.data(), dentryname) == 0)
		{
			temp = dentry[i];
			break;
		}
	}
	return temp;
}
//根據inode節點找相對應的目錄項
Dentry searchDentry(Inode *inode)
{

	Dentry temp;
	for (int i = 0; i <= record; i++)
	{
		if(dentry[i].inode == inode)
		{
			temp = dentry[i];
			break;
		}
	}
	return temp;
}
//得到當前路徑,如/home/root/sxw,最終返回結果爲sxw
// i+1 - endname.size() 爲路徑名
int getEndPath(string endname)
{
	std::cout<<"endname = "<<endname<<std::endl;
	int i = 0;
	for (i = endname.size(); i >= 0; i--)
	{
		if(endname[i] != '/')
		{
			continue;
		}
		break;
	}
	return (i + 1);
}
int judge(string path)
{

	int result = 0;
	int position = getEndPath(currentPath);
	char* dentryname =
			(char*) currentPath.substr(position, currentPath.size()).data();
	Dentry parent_dt = findDentry(dentryname);
	Inode *parent_inode = parent_dt.inode;
	Inode *child_inode = NULL;
	Dentry child_dt;
	for (int i = 0; i < parent_inode->inode_num; i++)
	{
		if((child_inode = parent_inode->childnode[i]) != NULL)
		{
			child_dt = searchDentry(child_inode);
			if(child_dt.name == path)
			{
				if(child_dt.inode->type == 0)
				{
					result = -1;
				} else
				{
					result = 1;
					break;
				}
			}
		}
	}
	return result;
}
void split(string command, string end[], char flag)
{
	int count = 0;
	int j = 0;
	for (int i = 0; i <= command.size(); i++)
	{
		if(command[i] == flag || i == command.size())
		{
			end[j] = command.substr(count, i - count);
			count = i + 1;
			j++;
		}
	}
}
void chagePriv(Inode *inode, string seond_result[], char f, int flag)
{
	if(f == '+')
	{
		if(seond_result[1] == "r")
			inode->priv[flag].read = 'r';
		else if(seond_result[1] == "w")
			inode->priv[flag].write = 'w';
		else if(seond_result[1] == "x")
			inode->priv[flag].execute = 'x';
	} else
	{
		if(seond_result[1] == "r")
			inode->priv[flag].read = '-';
		else if(seond_result[1] == "w")
			inode->priv[flag].write = '-';
		else if(seond_result[1] == "x")
			inode->priv[flag].execute = '-';
	}
}
void chomd(string command)
{
	string result[3];
	string seond_result[2];
	split(command, result, ' ');
	int results = judge(result[2]);
	if(results == 0)
	{
		cout << "your input is not found!!" << endl;
		return;
	} else
	{
		split(result[1], seond_result, result[1][1]);
		Dentry parent_dt = findDentry((char*) result[2].data());
		Inode *inode = parent_dt.inode;
		if(strcmp((char*) currentUser.data(), inode->owneruser) == 0
				|| currentUser == "root")
		{
			if(seond_result[0] == "u")
				chagePriv(inode, seond_result, result[1][1], 0);
			else if(seond_result[0] == "g")
				chagePriv(inode, seond_result, result[1][1], 1);
			else if(seond_result[0] == "o")
				chagePriv(inode, seond_result, result[1][1], 2);
		} else
		{
			cout << "sorry,當前用戶不允許授權!" << endl;
		}
	}
}
//權限判斷
// target -1 爲長路徑,  其他爲段路徑。 flag rwx 012
bool isLeagl(string filename, int target, int flag)
{
	if(currentUser == "root")
		return true;
	int user = 0;
	char* dentryname;
	if(target == -1)
	{
		int position = getEndPath(currentPath);
		dentryname =
				(char*) currentPath.substr(position, currentPath.size()).data();
	} else
		dentryname = (char*) filename.data();
	Dentry dt = findDentry(dentryname);
	Inode *inode = dt.inode;

	if(strcmp((char*) currentUser.data(), inode->owneruser) != 0)
	{
		user = 2;
	}
	switch (flag)
	{
	case 0:
		if(inode->priv[user].read == '-')
		{
			cout << "對不起,權限不夠!" << endl;
			return false;
		}
		break;
	case 1:
		if(inode->priv[user].write == '-')
		{
			cout << "對不起,權限不夠!" << endl;
			return false;
		}
		break;
	case 2:
		if(inode->priv[user].execute == '-')
		{
			cout << "對不起,權限不夠!" << endl;
			return false;
		}
		break;
	}
	return true;
}
//創建文件,目錄
/*
 * 跟蹤
createDirect("home", 1, -1); 創建/home
createDirect("root", 1, -1); 創建/home/root
 type = 0,創建文件,type = 1 創建目錄*/
void createDirect(string directname, int type,int p)
{
	Inode *inode = NULL;
	if(directname == "home")
	{
		inode = initializeInode(type, directname, p);
		record++;
		dentry[record].name = directname;
		dentry[record].inode = inode;
	}
	else
	{
		if(isLeagl(directname, -1, 1))
		{
			//從當前路徑得出文件/目錄名稱
			int position = getEndPath(currentPath);
			//home
			char* dentryname = (char*) currentPath.substr(position,
					currentPath.size()).data();
			Dentry dt = findDentry(dentryname);
			record++;
			Inode *temp = NULL;
			temp = initializeInode(type, directname, p);
			dt.inode->childnode[dt.inode->inode_num] = temp;
			dt.inode->inode_num++;
			dentry[record].name = directname;
			dentry[record].inode = temp;
// test();
		}
		else
			return;
	}
}
void readFile(string filename)
{
	if(isLeagl(filename, 1, 0))
	{
		int result = judge(filename);
		if(result == 1)
		{
			cout << "your input is not file!!" << endl;
			return;
		} else if(result == 0)
		{
			cout << "your input is not found!!" << endl;
			return;
		} else
		{
			Dentry dt = findDentry((char*) filename.data());
			Inode *inode = dt.inode;
			DataStock *ds = inode->datastock;
			while (ds->next != NULL)
			{
				DataStock *temp = ds->next;
				ds = temp;
				int name = temp->name;
				cout << disk[name];
			}
		}
		cout << endl;
	} else
		return;
}
void writeFile(string filename)
{
	if(isLeagl(filename, 1, 1))
	{
		int result = judge(filename);
		if(result == 1)
		{
			cout << "your input is not file!!" <<endl;
			return;
		} else if(result == 0)
		{
			cout << "your input is not found!!" << endl;
			return;
		} else
		{
			Dentry dt = findDentry((char*) filename.data());
			Inode *inode = dt.inode;
			string content = " ";
			getline(cin, content);
			int size = content.size();
			// 我修改了盤塊
			float stock_num = (size / disk_stock) + (size%disk_stock ? 1: 0);
			inode->size += size;
			DataStock *first = inode->datastock;
			while (first->next != NULL)
			{
				first = first->next;
			}
			DataStock *head = first;
			//補充要增加的內容
			int count = 0;
			for (int i = 0; i < number; i++)
			{
				if(i >= disk_record)
					disk_record++;
				//向文件追加內容和大小
				if(disk[i] == "")
				{
					DataStock *temp = (DataStock*) malloc(sizeof(DataStock));
					temp->name = i;
					temp->next = NULL;
					head->next = temp;
					head = temp;
					if(stock_num > 1)
					{
						disk[i] = content.substr(count, disk_stock);
						stock_num--;
						count = disk_stock + count;
					} else
					{
						disk[i] = content.substr(count, content.size());
						break;
					}
				}
			}
//修改文件夾的大小
			int position = getEndPath(currentPath);
			char* dentryname = (char*) currentPath.substr(position,
					currentPath.size()).data();
			Dentry parent_dt = findDentry(dentryname);
			Inode *parent_inode = parent_dt.inode;
			parent_inode->size = 0;
			for (int i = 0; i < parent_inode->inode_num; i++)
			{
				parent_inode->size += parent_inode->childnode[i]->size;
			}
		}
// test();
	} else
		return;
}
//向前pos移動一個節點
void moveInode(Inode *inode, int pos)
{
	if(pos != inode->inode_num - 1)
	{
		for (; pos < inode->inode_num - 1; pos++)
		{
			inode->childnode[pos] = inode->childnode[pos + 1];
		}
		inode->inode_num--;
	} else
	{
		inode->inode_num--;
		return;
	}
	return;
}
//刪除文件,目錄操作  0/1
void deleteDirect(string directname, int type)
{
	if(isLeagl(directname, -1, 1))
	{
		int result = judge(directname);
		if(result == 0)
		{
			cout << "your input is not found!!" << endl;
			return;
		} else
		{
			int position = getEndPath(currentPath);
			char* dentryname = (char*) currentPath.substr(position,
					currentPath.size()).data();
			Dentry parent_dt = findDentry(dentryname);
			Dentry current_dt = findDentry((char*) directname.data());
			Inode *parent_inode = parent_dt.inode;
			Inode *current_inode = current_dt.inode;
			for (int i = 0; i < parent_inode->inode_num; i++)
			{
				if(parent_inode->childnode[i] == current_inode)
				{
					parent_inode->childnode[i] = NULL;
					moveInode(parent_inode, i);
					if(type == 0)
					{
						DataStock *ds = current_inode->datastock;
// free(current_inode);
						while (ds->next != NULL)
						{
							DataStock *temp = ds->next;
							ds = temp;
							int name = temp->name;
							disk[name] = "";
							memset((char*) disk[name].data(), 0, 3);
						}
					}
				}
			}
		}
// test();
	} else
		return;
}
//實現ls命令操作列舉出當前目錄下的所有文件,目錄的詳細信息
void dir()
{
	int position = getEndPath(currentPath);
	char* dentryname =
			(char*) currentPath.substr(position, currentPath.size()).data();
	Dentry parent_dt = findDentry(dentryname);
	Inode *parent_inode = parent_dt.inode;
	Inode *child_inode = NULL;
	Dentry child_dt;
	string file_type;
	for (int i = 0; i < parent_inode->inode_num; i++)
	{
		if((child_inode = parent_inode->childnode[i]) != NULL)
		{
			child_dt = searchDentry(child_inode);
			if(child_inode->type == 0)
				file_type = "文件";
			else if(child_inode->type == 1)
				file_type = "目錄";
			cout << file_type << '\t';
			for (int i = 0; i < 3; i++)
			{
				cout << child_dt.inode->priv[i].read
						<< child_dt.inode->priv[i].write
						<< child_dt.inode->priv[i].execute << '\t';
			}
			cout << child_dt.inode->owneruser << '\t' << child_dt.inode->size
					<< "字節" << '\t' << (child_dt.inode->createtime->tm_mon + 1)
					<< "月" << '\t' << child_dt.inode->createtime->tm_mday
					<< '\t' << child_dt.inode->createtime->tm_hour << ":"
					<< child_dt.inode->createtime->tm_min << '\t'
					<< child_dt.name << '\t' << endl;
		}
	}
}
//string cinPasswd(){
// initscr();
// char ch;
// string str="";
// while((ch=getchar())!='\r')
// {
// cout<<"*";
// str+= ch;
// }
// endwin();
// return str;
//}
//用戶登錄
void login(string username)
{
	bool record = false;
	cout << "input your passwd please!!" << endl;
	output();
	string temp;
	cin >> temp;
	for (int i = 0; i < user.n; i++)
	{
		if((user.name[i]) == username)
		{
			if(user.passwd[i] == temp)
			{
				currentUser = username;
				record = true;
				cout << username << " login successfully!" << endl;
				cin.ignore();
				return;
			}
		}
	}
	if(!record)
	{
		cout << "sorry!" << " " << username << " " << "not found" << endl;
	}
	return;
}
void logout(string username)
{
	currentUser = user.name[0];
	cout << "current user logout successfully!!" << endl;
}
//實現在root用戶下添加新用戶
void addUser(string username)
{
	if(currentUser != "root")
	{
		cout << "sorry!current user is not root!!" << endl;
		return;
	} else
	{
		string passwd;
		cout << "input your passwd please!!" << endl;
		output();
		cin >> passwd;
		user.name[user.n] = username;
		user.passwd[user.n] = passwd;
		user.n++;
		cout << "add user successfully!!" << endl;
		cin.ignore();
		createDirect(username, 1, 0);
		return;
	}
}
//實現cd操作進入下個目錄
void intoNext(string path)
{
	if(path == "..")
	{
		int position = getEndPath(currentPath);
		currentPath = currentPath.substr(0, position - 1);
	} else
	{
		int result = judge(path);
		if(result == -1)
			cout << "sorry!your entry is not direct" << endl;
		else if(result == 1)
			currentPath = currentPath + "/" + path;
		else if(result == 0)
			cout << "your entry is not found!" << endl;
	}
}
void help()
{
	cout << "ls 列舉當前目錄下所有目錄項" << endl;
	cout << "pwd 顯示當前目錄結構 " << endl;
	cout << "adduser uu 添加新用戶uu " << endl;
	cout << "login root root用戶登錄 " << endl;
	cout << "logout 當前用戶登出 " << endl;
	cout << "create ss 創建文件ss " << endl;
	cout << "rm ss 刪除文件ss " << endl;
	cout << "mkdir ss 創建目錄ss " << endl;
	cout << "rmdir ss 刪除目錄ss " << endl;
	cout << "read ss 讀文件ss " << endl;
	cout << "write ss 寫文件ss " << endl;
	cout << "chmod o+w ss 給ss的other用戶賦予寫的權限 " << endl;
}
void showWindow()
{
	cout << '\t'
			<< "***************************************************************"
			<< endl;
	cout << '\t' << "**" << " " << "**" << endl;
	cout << '\t' << "**" << " Linux二級文件系統設計 " << "**" << endl;
	cout << '\t' << "**" << " " << "**" << endl;
	cout << '\t' << "**" << " 1,實現文件/目錄的創建,刪除,打開,關閉,讀取,授權等操作 " << "**" << endl;
	cout << '\t' << "**" << " " << "**" << endl;
	cout << '\t' << "**" << " 2.模擬linux下如cd,ls,pwd,adduser,chmod等基本命令 " << "**"
			<< endl;
	cout << '\t' << "**" << " " << "**" << endl;
	cout << '\t' << "**" << " 3.文件存儲使用內存模擬外存實現,具體操作請使用help命令查詢 " << "**"
			<< endl;
	cout << '\t'
			<< "***************************************************************"
			<< endl;
}
//實現pwd操作,顯示當前目錄
void showPath()
{
	cout << currentPath << endl;
}
//程序啓動時初始化root用戶,創建home和root目錄
void Initialize()
{
	user.name[0] = "root";
	user.passwd[0] = "linux";
	user.n++;
	currentUser = user.name[0];
	createDirect("home", 1, -1);
	createDirect("root", 1, -1);
}
void saveCommand(string command)
{
	if(command_record == number)
	{
		command_record = 0;
		commandsave[command_record] = command;
		commandsave[command_record++] = "";
	}
	commandsave[command_record] = command;
	command_record++;
}
void Up_BackOpreation(string command)
{
	if(command == "w")
	{
		if(command_record != 0)
			command_record--;
		else if(command_record == 0 && commandsave[command_number] != "")
			command_record = command_number;
	} else if(command == "s")
	{
		if(commandsave[command_record + 1] != "")
			command_record++;
		else if(command[command_record + 1] == command_number)
			command_record = 0;
		;
	}
	cout << command[command_record];
}
int commandSolve(string input)
{
	std::cout<<"input ="<<input<<std::endl;
	string first = input.substr(0, input.find(" "));
	string second = input.substr(input.find(" ") + 1, input.size());

	if(first == "create")   	//創建文件
		createDirect(second, 0, -1);
	else if(first == "mkdir")	//創建目錄
		createDirect(second, 1, -1);
	else if(first == "read")    //讀文件
		readFile(second);
	else if(first == "write")    //寫文件
		writeFile(second);
	else if(first == "rmdir")    //刪除目錄
		deleteDirect(second, 1);
	else if(first == "rm")       //刪除文件
		deleteDirect(second, 0);
	else if(first == "chmod")    //修改文件權限
		chomd(input);
	else if(first == "login")    //登錄
		login(second);
	else if(first == "logout")   //退出當前用戶,變爲root用戶
		logout(currentUser);
	else if(first == "adduser")  //增加用戶
		addUser(second);
	else if(first == "pwd")     //顯示當前路徑
		showPath();
	else if(first == "cd")      //切換目錄
		intoNext(second);
	else if(first == "ls")      // list列出當前目錄信息
		dir();
	else if(first == "help")    //help
		help();
	else if(input == "showdisk")//查看目前磁盤使用情況
		showDisk();
	else if(input == "")
		return 0;
	else
	{
		cout << "command error!" << endl;
	}
	return 0;
}
int main()
{
	showWindow();
	Initialize();
	string input = " ";
	while (true)
	{
		output();
		getline(cin, input);
		commandSolve(input);
	}
	return 0;
}


發佈了146 篇原創文章 · 獲贊 240 · 訪問量 46萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章