⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 多用户多级目录文件系统.cpp

📁 多用户多级目录的文件系统,(1)具有login (用户登录) (2)系统初始化(建文件卷、提供登录模块) (3)文件的创建: create (4)文件的打开:open (5)文件的读:read
💻 CPP
📖 第 1 页 / 共 2 页
字号:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <time.h>

const unsigned FILE_SYS_SIZE = 1024 * 1024;	//模拟文件系统的容量设为1M
const unsigned BITMAP_LEN = 64;				//位示图的长度 512/8
const unsigned BLOCK_SIZE = 512;			//一个文件块的大小
const unsigned BLOCK_COUNT = 512;			//文件系统中文件块的数量
const unsigned NAME_LEN = 11;			    //最长文件名的长度
const unsigned PASSWORD_LEN = 11;			//用户密码的最大长度
const unsigned LOGIN_COUNT = 5;		        //用户登录尝试次数
const unsigned COMMAND_LEN = 200;			//命令行最大长度
const unsigned PRO_SET_COMM_COU = 10;	    //预设命令数

const char *PRO_SET_COMM[] = {"create", "open", "read", "write", "close", "delete", "mkdir", "cd", "dir", "logout"};

//文件元素可供操作性权限
typedef enum 
{
	pub,				//任何人可做任何操作
	protect,			//非创建者或ADMIN,只可以察看
	pri					//非创建者或ADMIN,不可以做任何操作
} FileAccess;

//文件元素类型
typedef enum
{
	file,				//文件
	dir					//文件夹
} FileType;

//用户类型
typedef enum
{
	admin,				//管理者,拥用所有权限
	comm				//一般用户
} UserType;

//文件状态
typedef enum
{
	closed,
	opened,
	reading,
	writing
} FileStatus;


//一个文件索引结构
typedef struct 
{
	unsigned Index;						//文件元素索引编号
	char FileName[NAME_LEN];		    //文件元素名
	char ParentName[NAME_LEN];	        //父节点名
	unsigned FileBlockId;				//文件元素所在物理块编号
	unsigned FileLevel;					//文件元素所在层次,层+文件元素名为一个文件元素的逻辑位置
	unsigned effect;					//是否有效,0-无效,1-有效
} FileIndexElement;

//文件索引结构或目录表项
typedef struct
{
	FileIndexElement *FIStart;		//文件系统中的文件索引起始位置
	unsigned FILen;					//文件索引的最大长度
	unsigned FICount;				//文件索引数量	
} FileIndex;

//文件块的结构
typedef struct fb
{
	unsigned FileBlockId;		//文件块编号
	unsigned BLOCK_SIZE;		//文件块的容量
	char *FileBlockAddr;		//文件块地址
	struct fb *next;			//下一个文件块的地址
} FileBlock;

//文件系统的位示图结构
typedef struct 
{
	unsigned BITMAP_LEN;		//文件位示图长度
	char *BMStart;			    //位示图的起始指针
} BitMap;

//文件系统结构
typedef struct 
{
	char *FSStart;					//文件系统的起始地址
	unsigned SuperBlockSize;	    //文件系统的容量
	BitMap bm;						//文件系统中的位示图
	unsigned BLOCK_COUNT;			//文件系统中文件块的数量
	FileBlock *head;				//文件系统中文件块首地址
	FileIndex FI;					//文件系统中的文件索引
} SuperBlock;

typedef struct 
{
	char *UserName;					//用户名称
	UserType ut;					//用户类型
} User;

//文件系统中的元素结构,包括文件和文件夹
typedef struct fse
{
	struct fse *parent;					//指向自己的父亲节点
	unsigned FileLevel;					//文件元素所在层次,层+文件元素名为一个文件元素的逻辑位置
	char FileName[NAME_LEN];		    //文件元素名
	unsigned FileBlockId;				//文件元素所在物理块编号
	unsigned FileElemLen;				//文件元素的长度
	FileType Type;						//文件元素类型
	FileAccess Access;					//文件元素可供操作的权限
	User Creator;						//文件创建者
	char CreateTime[18];				//创建时间,日期格式:MM/DD/YY HH:MI:SS
	char LastModTime[18];				//最后一次修改时间
	char *FileData;						//一个文件的数据开始地址,文件夹时该值为NULL
	FileStatus fileStu;					//如果是一个文件表示文件当前的状态
} FSElement;

//系统当前状态
typedef struct
{
	User CurrentUser;				//当前用户
	unsigned FileLevel;				//用户所在文件系统层
	FSElement *CurrParent;			//当前层的父节点
	char *CurrentPath;				//当前路径
} CurrentStatus;

SuperBlock FS;		//一个全局文件系统的变量
CurrentStatus CS;	//当前系统状态
FSElement *base;	//文件元素的根

bool InitFileSys();
/*
* 函数介绍:寻找第一个空白的文件块ID
* 输入参数:无
* 输出参数:无
* 返 回 值:返回第一个空白块的ID
*/
unsigned FindBlankFileBlockId()
{
	unsigned char c;
	for (unsigned i = 0; i < FS.bm.BITMAP_LEN / 8; i++)
	{
		c = FS.bm.BMStart[i] | 0x7F;
		if (c == 0x7F)
		{
			return i * 8;		//一个字节左边第一位为0,表示该区域未使用
		}

		c = FS.bm.BMStart[i] | 0xBF;
		if (c == 0xBF)
		{
			return i * 8 + 1;		
		}

		c = FS.bm.BMStart[i] | 0xDF;
		if (c == 0xDF)
		{
			return i * 8 + 2;		
		}
		c = FS.bm.BMStart[i] | 0xEF;
		if (c == 0xEF)
		{
			return i * 8 + 3;		
		}
		c = FS.bm.BMStart[i] | 0xF7;
		if (c == 0xF7)
		{
			return i * 8 + 4;		
		}
		c = FS.bm.BMStart[i] | 0xFB;
		if (c == 0xFB)
		{
			return i * 8 + 5;		
		}
		c = FS.bm.BMStart[i] | 0xFD;
		if (c == 0xFD)
		{
			return i * 8 + 6;		
		}
		c = FS.bm.BMStart[i] | 0xFE;
		if (c == 0xFE)
		{
			return i * 8 + 7;		
		}
	}
	return BLOCK_COUNT + 1;
}
/*
* 函数介绍:寻找第一个文件块地址
* 输入参数:fileblockid 文件块ID
* 输出参数:无
* 返 回 值:返回文件块的地址
*/
char * FindBlankFileBlock(unsigned fileblockid)
{
	FileBlock *fblock = FS.head;
	while (fblock->next != NULL)
	{
		if (fblock->FileBlockId == fileblockid)
		{
			return fblock->FileBlockAddr;
		}
		else
		{
			fblock = fblock->next;
		}
	}
	return NULL;
}
/*
* 函数介绍:得到当前时间的字符串
* 输入参数:时间字符串的指针
* 输出参数:无
* 返 回 值:void
*/
void GetCurrentTime(char *currtime)
{
	char dbuffer [9];
	char tbuffer [9];
	_strdate(dbuffer);
	_strtime(tbuffer);
	strcpy(currtime, dbuffer);
	strcat(currtime, " ");
	strcat(currtime, tbuffer);
}
/*
* 函数介绍:更新文件索引
* 输入参数:fileblockid 文件块ID
* 输出参数:无
* 返 回 值:无
*/
void AddFileIndex(unsigned fileblockid, unsigned filelevel, char *filename, char *parentname)
{
	FS.FI.FIStart[FS.FI.FICount].FileBlockId = fileblockid;
	FS.FI.FIStart[FS.FI.FICount].FileLevel = filelevel;
	strcpy(FS.FI.FIStart[FS.FI.FICount].FileName, filename);
	if (parentname == NULL)
	{
		memset(FS.FI.FIStart[FS.FI.FICount].ParentName, '\0', NAME_LEN);
	}
	else
	{
		strcpy(FS.FI.FIStart[FS.FI.FICount].ParentName, parentname);
	}
	FS.FI.FIStart[FS.FI.FICount].Index = FS.FI.FICount;
	FS.FI.FIStart[FS.FI.FICount].effect = 1;
	FS.FI.FICount ++;
}
/*
* 函数介绍:更新位示图
* 输入参数:fileblockid 文件块ID
* 输出参数:无
* 返 回 值:无
*/
void UpdateBitMap(unsigned fileblockid)
{
	//计复所在位示图的位置
	int dirInBitmap = ((int)(fileblockid / 8));
	int dirInChar = fileblockid % 8;

	char *c = &(FS.bm.BMStart[dirInBitmap]);
	char xor;
	switch (dirInChar)
	{
	case 0:
		xor = 0x80;
		break;
	case 1:
		xor = 0x40;
		break;
	case 2:
		xor = 0x20;
		break;
	case 3:
		xor = 0x10;
		break;
	case 4:
		xor = 0x08;
		break;
	case 5:
		xor = 0x04;
		break;
	case 6:
		xor = 0x02;
		break;
	case 7:
		xor = 0x01;
		break;
	}
	*c = *c ^ xor;
}
/*
* 函数介绍:创建一个文件元素
* 输入参数:acc 文件元素可操作权限,filename 文件元素名称,type 文件元素类型,filecontent 文件内容
* 输出参数:无
* 返 回 值:返回一个文件元素的指针
*/
FSElement * CreateFileElement(FileAccess acc, char *filename, FileType type, char *filecontent, FSElement *parent)
{
	//查找第一个空白文件块ID
	unsigned blankFileBlockId = FindBlankFileBlockId();
	if (blankFileBlockId >= BLOCK_COUNT)
	{
		printf("未找到一个文件块的id\n");
		return NULL;
	}

	//查找第一个空白块的地址
	char *blank = FindBlankFileBlock(blankFileBlockId);
	if (blank == NULL)
	{
		printf("未找到一个文件块的地址\n");
		return NULL;
	}

	FSElement *fs = (FSElement *)blank;

	fs->Access = acc;
	fs->Creator = CS.CurrentUser;
	GetCurrentTime(fs->CreateTime);
	fs->FileBlockId = blankFileBlockId;
	fs->FileLevel = CS.FileLevel;
	strcpy(fs->FileName, filename);
	strcpy(fs->LastModTime, fs->CreateTime);
	fs->Type = type;
	fs->parent = parent;	

	if (type == dir)
	{
		fs->FileElemLen = sizeof(FSElement);
		fs->FileData = NULL;
	}
	else
	{		
		fs->FileElemLen = (unsigned)strlen(filename);
		fs->fileStu = closed;
		fs->FileData = (char *)fs + sizeof(FSElement);
		if (filecontent == NULL)
		{
		}
		else
		{
			strcpy(fs->FileData, filecontent);
		}
	}	

	//更新索引	
	if (parent == NULL)
	{
		AddFileIndex(blankFileBlockId, CS.FileLevel, filename, NULL);	
	}
	else
	{
		AddFileIndex(blankFileBlockId, CS.FileLevel, filename, parent->FileName);
	}

	//更新BITMAP
	UpdateBitMap(blankFileBlockId);
	return fs;
}

/*
* 函数介绍:创建文件块链表
* 输入参数:datahead 第一块数据的地址,blockcap 一个文件块的大小,len 链表的长度
* 输出参数:无
* 返 回 值:返回链表的头指针
*/
FileBlock * CreateFileBlockList(char *datahead, unsigned blockcap, unsigned len)
{
	if (datahead == NULL || len == 0)
	{
		return NULL;
	}
	FileBlock *head;
	FileBlock *pnew;
	FileBlock *pold;

	head = pold = pnew = (FileBlock *)malloc(sizeof(FileBlock));
	for ( unsigned i = 0; i < len; i++)
	{
		pold->FileBlockId = i;
		pold->BLOCK_SIZE = BLOCK_SIZE;
		pold->FileBlockAddr = datahead + i * blockcap;
		memset(pold->FileBlockAddr, '\0', blockcap);
		if (i != len - 1)
		{
			pnew = (FileBlock *)malloc(sizeof(FileBlock));
		}
		else
		{
			pnew = NULL;
		}
		pold->next = pnew;	
		pold = pnew;

	}
	return head;
}
/*
* 函数介绍:初始化模拟文件系统
* 输入参数:无
* 输出参数:无
* 返 回 值:true-初始化成功,false-初始化失败
*/
bool InitFileSys()
{
	//初始化模拟的文件系统
	if ((FS.FSStart = (char *)malloc(FILE_SYS_SIZE)) == NULL)
	{
		return false;		
	}

	FS.SuperBlockSize = FILE_SYS_SIZE;
	FS.bm.BITMAP_LEN = BITMAP_LEN;
	FS.bm.BMStart = FS.FSStart;

	//设置位示图为未使用
	memset(FS.bm.BMStart, '\0', FS.bm.BITMAP_LEN);

	//初始化文件系统索引
	FS.FI.FIStart = (FileIndexElement *)(FS.FSStart + BITMAP_LEN);
	//因为是模拟系统,暂定一个文件或文件夹最多占用一个文件块,一个文件块只放一个文件元素
	FS.FI.FILen   = sizeof(FileIndexElement) * BLOCK_COUNT + sizeof(unsigned) * 2;	
	FS.FI.FICount = 0;
	memset(FS.FI.FIStart, '\0', FS.FI.FILen);

	//初始化文件块
	FS.BLOCK_COUNT = BLOCK_COUNT;
	FS.head = CreateFileBlockList((FS.FSStart + FILE_SYS_SIZE - BLOCK_SIZE * BLOCK_COUNT), 
		      BLOCK_SIZE, FS.BLOCK_COUNT);//区域的后BLOCK_SIZE * BLOCK_COUNT个单元用来存储数据

	if (FS.head == NULL)
	{
		return false;
	}


	//初始化系统当前状态
	CS.CurrentUser.UserName = (char *)calloc(10,sizeof(char));
	strcpy(CS.CurrentUser.UserName, "man");
	CS.CurrentUser.ut = admin;
	CS.CurrParent = NULL;
	CS.FileLevel = 0;
	CS.CurrentPath = (char *)calloc(1000, sizeof(char));

	//创建一个根目录
	base = CreateFileElement(pub, "root", dir, NULL, NULL);
	if (base == NULL)
	{
		return false;
	}
	else
	{
		return true;
	}
}
/*
* 函数介绍:系统登录模块
* 输入参数:无
* 输出参数:无
* 返 回 值:true 登录成功,false 登录失败
*/
bool Login()
{
	char username[10];
	char password[PASSWORD_LEN];
	int c;

	for (c = 0; c < LOGIN_COUNT; c++)
	{
		int i = 0;
		memset(password, '\0', PASSWORD_LEN);
		memset(username, '\0', 10);
		printf("login:");
		gets(username);

		printf("password:");
		while (i < PASSWORD_LEN && (password[i++] = getch()) != 0x0d) {};
		password[strlen(password) - 1] = '\0';

		if ((strcmp(username, "user1") == 0 && strcmp(password, "user1") == 0) ||
			(strcmp(username, "user2") == 0 && strcmp(password, "user2") == 0) ||
			(strcmp(username, "user3") == 0 && strcmp(password, "user3") == 0) ||
			(strcmp(username, "user4") == 0 && strcmp(password, "user4") == 0) ||
			(strcmp(username, "user5") == 0 && strcmp(password, "user5") == 0) ||

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -