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

📄 os.cpp

📁 设计并实现一个多用户多级目录结构的文件系统
💻 CPP
📖 第 1 页 / 共 3 页
字号:
#include <stdio.h>
#include <string.h>
#define   BSIZE    512    /*  512bytes/块  */
#define   BLKMAX   2048   /*  共2048块  */
#define   BUFFER   1048576  /* 1M*/

#define   READRIG  1
#define   WRITEERR 1
#define   FILES  5
   struct user
    { char u_name[12];      /* 用户名,登录时使用 */
      char u_uid;           /* 用户标识,即文件创建时的文件主 */
      char u_gid;            /* 同组用户标识 */
      struct fcb *u_cdir;   /* 现行工作目录的FCB指针 */
      char u_error;         /* 执行文件管理函数时返回的错误代码 */
      char *u_base;         /* 读/写文件时信息存储区始址 */
      int u_count;          /* 读/写文件的信息字节数 */
      int u_offset;         /* 读/写文件的相对位移量 */
      char u_obuf[8];       /* 文件路径名分量暂存区(查找文件时用) */
      struct fcb *u_pdir;   /* 新文件父目录FCB指针(文件创建时用) */
      struct ofile *u_ofile[FILES];  /* 本用户打开文件表 */
    };
   # define USERNO 5      /* 定义本文件系统最多可接纳五个用户 */
   struct user user[USERNO],*u=new struct user;

#define   NOERROR  -1
#define   READERR  0
#define   NOTFOUND 1

  struct ofile
    { char o_flag;          /* 标志字 */
      char o_count;         /* 访问计数 */
      struct fcb *o_fcbp;   /* 对应打开文件fcb结构指针 */
      int o_offset;      /*文件当前位置*/
    };
   # define FILENO 10       /* 文件系统允许打开文件数量 */
   struct ofile ofile[FILENO]; /* 系统打开文件表ofile */
    //标志字 o-flag 表示的标志定义为:
   # define FREAD  01       /* 文件“读打开”标志 */
   # define FWRITE 02       /* 文件“写打开”标志 */
   # define FNOPEN 00
/*	openf() ─ 为打开文件建立对应的ofile结构的函数
     closef() ─ 为关闭文件建立对应的ofile结构的函数
   openf()主要是在创建或打开文件时,执行完查找(namei())操作, 获得文件的
fcb结构指针后,为该文件分配一 ofile结构,置读/写指针初值等。
    closef() 是在关闭文件时释放 ofile结构(即将 o-count减1,若o-count=0表
示该 ofile结构空闲),并调用 iput()将关闭文件的目录结构写回文件卷内
*/
//-----------------------------------------------------

 struct dir
      { unsigned short d_mode;  /* 文件属性及访问权限 */
        char d_uid;     /* 文件主标识 */
        char d_gid;     /* 文件主同组用户标识 */
        int  d_fsize;   /* 文件大小(字节) */
        char d_name[8]; /* 文件名 */
        unsigned short d_add[8]; /* 存放文件信息的空间地址(块号) */
      };  
    # define DSIZE  32  /* 以上目录结构占用32字节 */


   struct fcb
   { 
	char  f_count;  
    char  f_flag;   
    int   f_blkno;  
    char  f_number; 
    unsigned short f_mode;  
    
    char  f_uid;
	char  f_gid;
    int   f_fsize;
    char  f_name[8];
    int   f_add[8];
   };
    # define FCBMAX  16
    struct fcb fcb[FCBMAX],file_fcb[FILENO]; /* 系统 fcb[] 结构 */
	struct fcb *fp;
    
    # define FLOCK  01  /* fcb访问互斥标志 */
    # define FUPD   02  /* 本fcb代表的文件已修改 */
    # define FCHG   04  /* 本fcb结构中某些信息已被修改 */

    # define IFMT   0070000 /* 文件类型屏蔽字 */
    # define IFDIR  0010000 /* 子目录文件 */
    # define EMPTY 11000 /* 删除的文件目录 */
    # define IFREG  0020000 /* 普通文件 */
    # define IREAD  0400    /* 文件主“读”权限 */
    # define IWRITE 0200    /* 文件主“写”权限 */
    # define IEXEC  0100    /* 文件主“执行”权限 */
    # define GREAD  040     /* 同组用户“读”权限 */  
    # define GWRITE 020     /* 同组用户“写”权限 */
    # define GEXEC  010     /* 同组用户“执行”权限 */
    # define OREAD  04      /* 其它用户“读”权限  */
    # define OWRITE 02      /* 其它用户“写”权限  */
    # define OEXEC  01      /* 其它用户“执行”权限  */

    # define HOST 0
    #define GROUPS 1
    #define OTHERS 2

FILE *vp;
char buffer[2048/8];
int block,blk_offset;
struct dir *dir_struct=new struct dir;
char filebuffer[BSIZE*8];
//------------------------------------------------------
//第一层
/*(1) 块管理层(或称文件卷管理层),设下列主要函数:
       balloc() ─ 块分配函数
       brelse() ─ 块释放函数
       bread() ─  读一块函数
       bwrite() ─ 写一块函数*/
//--------------------------------------------------------
#define STRLENGTH 100
char cur_dir[STRLENGTH];
#define CD  0
#define DIR 1
#define MD  1
#define RD  1
#define CD2 2
#define CD1 3
void printcdir(int oprtype,char *name)
{
	int i,j,t=0;
	if(oprtype==0)
	{
		for(i=0;i<STRLENGTH;i++)
			if(cur_dir[i]!='>')continue;
			else
				if(*name!='\0')
				{
					if(t==0)
					{
						t=1;
						cur_dir[i]='\\';
					}
					else
					{
						cur_dir[i]=*name;
					    name++;
					}
				}
				else
				{
					for(j=0;j<=i;j++)
						printf("%c",cur_dir[j]);
					return;
				}
	}

	if(oprtype==1)
	{
		for(j=0;j<STRLENGTH;j++)
			if(cur_dir[j]!='>')
				printf("%c",cur_dir[j]);
			else break;
		printf("%c",cur_dir[j]);
		return;
	}

	if(oprtype==2)
	{
		for(j=0;j<STRLENGTH;j++)
		{
			if(cur_dir[j]=='\\')
			{
				cur_dir[j]=':';
				t=1;
			}
			if (cur_dir[j]=='>') break;
			if(t==1) cur_dir[j]='>';
		}

        for(j=0;j<STRLENGTH;j++)
			if(cur_dir[j]!='>')
				printf("%c",cur_dir[j]);
			else break;
		printf("%c",cur_dir[j]);
		return;
	}

	if(oprtype==3)
	{
		for(j=0;j<STRLENGTH;j++)
			if(cur_dir[j]=='>') 
				break;
		int k=j;
		for(;j>5;j--)
			if(cur_dir[j]=='\\')
				break;
		for(j;j<=k;j++)
			cur_dir[j]='>';
		
		for(j=0;j<STRLENGTH;j++)
			if(cur_dir[j]!='>')
				printf("%c",cur_dir[j]);
			else break;
		printf("%c",cur_dir[j]);
		return;			
	}
}

//--------------------------------------------------------
void iget();
void init()
{
	int i, *k=new int;
	char p[12]="dengyu", pass[4]="f";
	if((vp=fopen("buffer","rb+"))==NULL)
	{
		vp=fopen("buffer","wb+");//初始化超级块
		fputc(128,vp);
	
		for(i=1;i<BUFFER;i++)
			fputc(0,vp);
		fclose(vp);

	    vp=fopen("buffer","rb+");
		unsigned short *attribution=new unsigned short;
		*attribution=IFDIR;
		fseek(vp,DSIZE*15,0);
		fwrite(attribution,sizeof(unsigned short),1,vp);
		char name[8]="ROOTDIR";
		fseek(vp,DSIZE*15+8,0);
		fwrite(name,8,1,vp);

		fseek(vp,DSIZE*8,0);
		fwrite(p,12,1,vp);
		fwrite(pass,4,1,vp);

		fclose(vp);
		vp=fopen("buffer","rb+");
	}
    
	//user load
    do
	{
		char name[12];
		char password[4];
	    printf("LOGIN:");
		gets(name);
	    if(strcmp(name,p))
		{
			printf("user wrong\n\n");
			continue;
		}
		printf("password:");
		gets(password);
		if(strcmp(password,pass))
		{
			printf("password wrong\n\n");
			continue;
		}
		break;
	}
	while (1);
	
	//read out useful block
	fread(buffer,2048/8,1,vp);

	//init cur_dir[100]="FILE:>"
	cur_dir[0]='F';cur_dir[1]='I';cur_dir[2]='L';cur_dir[3]='E';
    cur_dir[4]=':';
	for(i=5;i<100;i++)
		cur_dir[i]='>';

	//init struct fcb
	for(i=0;i<FCBMAX;i++)
	{
		fcb[i].f_mode=0;
		file_fcb[i].f_mode=0;
	}
	fp=fcb;
	
	//init struct user
	u->u_uid=HOST;
	u->u_gid=HOST;
	
	fseek(vp,DSIZE*15,0);//vp 指向根目录

	block=0;blk_offset=15;
	iget();// printf("%d ",u->u_cdir->f_add[0]);
	
	u->u_base=NULL;
	u->u_count=0;
	u->u_error=NOERROR;
    for(int j=0;j<5;j++) 
		u->u_ofile[j]=NULL;
	for(i=0;i<BSIZE*8;i++)
		filebuffer[i]=0;

    //init struct ofile*/
	for(i=0;i<FILENO;i++)
    {
		ofile[i].o_count=0;
		ofile[i].o_flag=0;
		ofile[i].o_fcbp=NULL;
		ofile[i].o_offset=0;
	}
}

void bread(int bno,char *buf)   /* 待读出块的块号, 读出块信息缓冲区指针 */
{
	int nbyte;
    fseek(vp,bno*BSIZE,0); /* 将读/写指针移到文件卷指定块的边界处 */
    nbyte=fread(buf,BSIZE,1,vp);  /* 读出一块信息 */
    if(nbyte!=BSIZE)
		u->u_error=READERR;   /* u为当前用户的 user 结构指针 */
}

void  bwrite(int bno,char *buf)
{
	int nbyte;
    fseek(vp,bno*BSIZE,0);
    nbyte=fwrite(buf,BSIZE,1,vp);
    if(nbyte!=BSIZE)
		u->u_error=WRITEERR;
}

int balloc()
{
	
	FILE *f=vp;
	int i,j,k,t=1;	
	for(i=0;i<BLKMAX/8;i++)
	{
		
		if(buffer[i]!=-1)
		{ 
			
			for(j=1;j<BLKMAX/8;j*=2)
			{
				if (buffer[i]==(buffer[i]&(buffer[i]+j)))
				{
					buffer[i]+=j;
					
					for(k=1;k<=8;k++)
					{
						if(t==j) break;
						t*=2;
					}
	
			

					vp=f;
		            return i*8+8-k; //分配的块号
				}
				
			}
			
		}
	}
	if(i==BLKMAX/8)
		vp=f;
	return 0;//没有块分配
}

void brelse(int blk)
{
	char zero[BSIZE+1];
	int bitno,bit_offset,xor=1,i;

	bitno=blk/8;
    bit_offset=blk%8;
	for(i=1;i<8-bit_offset;i++)
		xor*=2;
	if(buffer[bitno]==(buffer[bitno]|xor))
	{
		buffer[bitno]-=xor;
		for(i=0;i<BSIZE;i++)
			zero[i]=0;
		zero[i]='\0';
		bwrite(blk,zero);
	}
}

//-----------------------------------------------------
//第二层
/*	 namei() ─ 文件查找函数
     iget() ─  取目录结构函数(从文件中读出一指定的目录结构,建立相应fcb)
     iput() ─  存目录结构函数(将一指定fcb结构写回文件卷的目录结构位置内)
     readi() ─ 对指定fcb代表的文件读函数
     writei() ─ 对指定fcb代表的文件写函数

    readi()、writei() 二函数的功能是根据 u-offset、u-count 和 u-base三个
参数,对指定文件 (由 fcb结构指针 fp指定) 进行读/写。实现时,必须先将位移
u-offset 转化为对应的块号 (即: fp->f-add[u-offset/BSIZE])和块内位移(即:
 u-offset%BSIZE),然后再调用笫一层的 bread()或 bwrite()实现真正的读/写;
如 u-count较大(大于 BSIZE-u-offset%BSIZE),必须分多次读/写。*/
//-------------------------------------------------------------
void cdirstruct()
{
    int i;
	for(i=0;i<8;i++)
		dir_struct->d_add[i]=u->u_cdir->f_add[i];
	for(i=0;i<8;i++)
		dir_struct->d_name[i]=u->u_cdir->f_name[i];
	dir_struct->d_fsize=u->u_cdir->f_fsize;
    dir_struct->d_gid=u->u_cdir->f_gid;	
	dir_struct->d_mode=u->u_cdir->f_mode;
    dir_struct->d_uid=u->u_cdir->f_uid;
}

#define BLKZERO  0
void search(char *fname)
{
	int i,j,k;
	for(i=0;i<8;i++)
	{		
		for(j=0;j<16;j++)
		{
			fseek(vp,u->u_cdir->f_add[i]*BSIZE+DSIZE*j,0);			
			fread(dir_struct,DSIZE,1,vp);			         
			
			if(dir_struct->d_mode!=IFDIR)
				continue;

			if(!strcmp(dir_struct->d_name,fname))
			{
				u->u_cdir->f_mode=IFDIR;
				u->u_cdir->f_blkno=u->u_cdir->f_add[i];
				u->u_cdir->f_number=j;				
				
				for(k=0;k<8;k++)
					u->u_cdir->f_add[k]=dir_struct->d_add[k];
                
				u->u_error=NOERROR; 

				return;
			}
		}
	}
	if (i==8) u->u_error=NOTFOUND;
}

void namei(char *route)
{    
	FILE *f=vp;
	int i,oprtype=DIR;
	char *name=new char;

	fp->f_mode=u->u_cdir->f_mode;
	fp->f_blkno=u->u_cdir->f_blkno;
	fp->f_number=u->u_cdir->f_number;
	for(i=0;i<8;i++)
		fp->f_add[i]=u->u_cdir->f_add[i];
	u->u_cdir=fp;

	if(*route=='/'||*route=='\\')
	{
		while(*route!='\0')
		{
			route++;
	    	for(i=0;i<9;i++)
			{
	    		if(*route=='/')break;
				if(*route=='\0')break;
				if(*route=='\\') break;
	    		name[i]=*route;
				route++;
			}			
			name[i]='\0';
	    	
			search(name);

			if(u->u_error==NOTFOUND)//没找到
			{				
				fp--;
				u->u_cdir=fp;
				fp++;
				fp->f_mode=0;
				return;
			}
		}		
		return;
	}

	if(*route!='/'&&*route!='\\')
	{
		
		for(i=0;i<8;i++)
			u->u_cdir->f_add[i]=fcb->f_add[i];
		
		while(*route!='\0')
		{
	    	for(i=0;i<9;i++)
			{
	    		if(*route=='/'||*route=='\\')
				{
					route++;
					break;
				}
				if(*route=='\0') break;
	    		name[i]=*route;
				route++;
			}

			name[i]='\0';
	    	search(name);
	        
			if(u->u_error==NOTFOUND)//没找到
			{
				fp--;
				u->u_cdir=fp;
				fp++;
				fp->f_mode=0;
				return;
			}
		}
	}
}

void iget()//need block and blk_offset
{	
    int i;
	fread(dir_struct,DSIZE,1,vp);

	fp->f_count++;
    fp->f_flag=ofile->o_flag;
	fp->f_blkno=block;
	fp->f_number=blk_offset;
	fp->f_mode=dir_struct->d_mode;
	fp->f_uid=dir_struct->d_uid;
	fp->f_gid=dir_struct->d_gid;
	fp->f_fsize=dir_struct->d_fsize;
	for(i=0;i<8;i++)
		fp->f_name[i]=dir_struct->d_name[i];
	for(i=0;i<8;i++)
		fp->f_add[i]=dir_struct->d_add[i];

	u->u_cdir=fp;

	fp++;

}

void iput()
{

⌨️ 快捷键说明

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