
设计目的:通过具体的文件存储空间的管理、文件的物理结构、目录结构和文件操作的实现,加深对文件系统内部功能和实现过程的理解。
设计内容:模拟一个简单二级文件管理系统
一、实验内容描述
1 实验目标
本实验的目的是通过一个简单多用户文件系统的设计,加深理解文件系统的内部功能及内部实现.
2 实验要求
为DOS系统设计一个简单的二级文件系统.要求做到以下几点:
①可以实现下列命令:
login 用户登录
dir 列文件目录
create 创建文件
delete 删除文件
open 打开文件
close 关闭文件
read 读文件
write 写文件
②列目录时要列出文件名、物理地址、保护码和文件长度.
③源文件可以进行读写保护.
二、程序主要内容
1设计思路
程序中要求每个用户在登陆后才可对其拥有的文件进行操作,用户对于其他用户的文件无操作权.文件操作包括浏览、创建、删除、打开、关闭、阅读、写入、修改模式.其他操作包括新建用户、帮助、用户登入、用户登出、退出系统.
在程序文件夹下有个名为“file”的系统根目录,此目录下包括:一个名为“mfd”的文件,记录所有注册过的帐号及密码;用户文件,以用户名作为文件名,内容为其拥有的文件名及属性;一个名为“keiji”的文件夹.“keiji”文件夹中包括:“file.p”指针文件,记录所有已用的物理地址;一些以物理地址为名的文件,内容为文件内容.
2 数据结构
file结构体系统文件数据结构:
fpaddrint,文件的物理地址、flengthint,文件长度、fmodeint,文件模式 0.只读;1.可写;2.可读写;3.保护、 fname[]char,文件名;
filemode结构体文件状态数据结构:
isopenint,文件当前状态,0.关闭;1.打开、modeint,文件模式 0.只读;1.可写;2.可读写;3.初始化;
user结构体用户信息数据结构:
uname[]char,用户名、upassword[]char,用户密码;
userfile结构体用户文件数据结构:
uname[]char,用户名、ufile[]file,用户拥有的文件数组.
.......
[cpp] view plaincopyprint?
1.#include 2.#include 3.#include 4.#include 5.#include 6.#define MaxUser 100 //定义最大MDF主目录文件 7.#define MaxDisk 512*1024 //模拟最大磁盘空间 8.#define commandAmount 12 //对文件操作的指令数 9.//存储空间管理有关结构体和变量 10.char disk[MaxDisk]; //模拟512K的磁盘存储空间 11.typedef struct distTable //磁盘块结构体 12.{ 13.int maxlength; 14.int start; 15.int useFlag; 16.distTable *next; 17.}diskNode; 18.diskNode *diskHead; 19.struct fileTable //文件块结构体 20.{ 21.char fileName[10]; 22.int strat; //文件在磁盘存储空间的起始地址 23.int length; //文件内容长度 24.int maxlength; //文件的最大长度 25.char fileKind[3]; //文件的属性——读写方式 26.struct tm *timeinfo; 27.bool openFlag; //判断是否有进程打开了该文件 28.//fileTable *next; 29.}; 30. 31.//两级目录结构体 32.typedef struct user_file_directory //用户文件目录文件UFD 33.{ 34.//char fileName[10]; 35.fileTable *file; 36.user_file_directory *next; 37.}UFD; 38.//UFD *headFile; 39.typedef struct master_file_directory //主文件目录MFD 40.{ 41.char userName[10]; 42.char password[10]; 43.UFD *user; 44.}MFD; 45.MFD userTable[MaxUser]; 46.int used=0; //定义MFD目录中用已有的用户数 47. 48.//文件管理 49.void fileCreate(char fileName[],int length,char fileKind[]); //创建文件 50.void fileWrite(char fileName[]); //写文件 51.void fileCat(char fileName[]); //读文件 52.void fileRen(char fileName[],char rename[]); //重命名文件 53.void fileFine(char fileName[]); //查询文件 54.void fileDir(char UserName[]); //显示某一用户的所有文件 55.void fileClose(char fileName[]); //关闭已打开的文件 56.void fileDel(char fileName[]); //删除文件 57.void chmod(char fileName[],char kind[]); //修改文件的读写方式 58.int requestDist(int &startPostion,int maxLength); //磁盘分配查询 59.void initDisk(); //初始化磁盘 60.void freeDisk(int startPostion); //磁盘空间释放 61.void diskShow(); //显示磁盘使用情况 62. 63.//用户管理 .void userCreate(); 65.int login(); 66.int userID=-1; //用户登录的ID号,值为-1时表示没有用户登录 67. 68.int main() 69.{ 70.char order[commandAmount][10]; 71.strcpy(order[0],"create"); 72.strcpy(order[1],"rm"); 73.strcpy(order[2],"cat"); 74.strcpy(order[3],"write"); 75.strcpy(order[4],"fine"); 76.strcpy(order[5],"chmod"); 77.strcpy(order[6],"ren"); 78.strcpy(order[7],"dir"); 79.strcpy(order[8],"close"); 80.strcpy(order[9],"return"); 81.strcpy(order[10],"exit"); 82.strcpy(order[11],"df"); 83.char command[50],command_str1[10],command_str2[10],command_str3[5],command_str4[3]; 84.int i,k,j; 85.int length; 86.initDisk(); //初始化磁盘 87.for(i=0;i .userTable[i].user=(UFD *)malloc(sizeof(UFD)); 90.userTable[i].user->next=NULL; 91.} 92.while(1) 93.{ 94.printf("********************************************/n"); 95.printf(" 1、Creat user/n"); 96.printf(" 2、login/n"); 97.printf("********************************************/n"); 98.printf("Please chooce the function key:>"); 99.int choice; 100.scanf("%d",&choice); 101.if(choice==1) userCreate(); 102.else if(choice==2) userID=login(); 103.else printf("您的输入有误,请重新选择/n"); 104.while(userID!=-1) 105.{ 106.fflush(stdin); 107.printf("———————————————————————————————————————/n"); 108.printf(" create-创建 格式:create a1 1000 rw,将创建名为a1,长度为1000字节可读可写的文件/n"); 109.printf(" rm-删除 格式:rm a1,将删除名为a1的文件/n"); 110.printf(" cat-查看文件内容 格式:cat a1,显示a1的内容/n"); 111.printf(" write-写入 格式:write a1/n"); 112.printf(" fine-查询 格式:fine a1 ,将显示文件 a1的属性/n"); 113.printf(" chmod-修改 格式:chmod a1 r,将文件a1的权限改为只读方式/n"); 114.printf(" ren-重命名 格式:ren a1 b1 ,将a1改名为b1/n"); 115.printf(" dir-显示文件 格式:dir aaa,将显示aaa用户的所有文件/n"); 116.printf(" df-显示磁盘空间使用情况 格式:df/n"); 117.printf(" close-关闭文件 格式:close a1,将关闭文件a1/n"); 118.printf(" return-退出用户,返回登录界面/n"); 119.printf(" exit-退出程序/n"); 120.printf("————————————————————————————————————————/n"); 121.printf("please imput your command:>"); 122.gets(command); 123.int select; 124.for(i=0;command[i]!=' '&&command[i]!='/0';i++) //command_str1字符串存储命令的操作类型 125.command_str1[i]=command[i]; 126.k=i; 127.command_str1[k]='/0'; 128.for(i=0;i 130.if(!strcmp(command_str1,order[i])) 131.{ 132.select=i; 133.break; 134.} 135.} 136.if(i==commandAmount) 137.{ 138.printf("您输入的命令有误,请重新输入/n"); 139.continue; 140.} 141.for(i=k+1,k=0;command[i]!=' '&&command[i]!='/0';i++,k++) //commmand_str2字符串存储文件名或用户名 142.command_str2[k]=command[i]; 143.command_str2[k]='/0'; 144.k=i; 145.switch(select) 146.{ 147.case 0:for(i=k+1,k=0;command[i]!=' ';i++,k++) 148.command_str3[k]=command[i]; 149.command_str3[k]='/0'; 150.k=i; 151.j=1; 152.length=0; //初始化文件长度 153.for(i=strlen(command_str3)-1;i>=0;i--) //把字符串转换为十进制 154.{ 155.length+=(command_str3[i]-48)*j; 156.j*=10; 157.} 158.for(i=k+1,k=0;command[i]!=' '&&command[i]!='/0';i++,k++) 159.command_str4[k]=command[i]; 160.command_str4[k]='/0'; 161.fileCreate(command_str2,length,command_str4);break; 162.case 1:fileDel(command_str2);break; 163.case 2:fileCat(command_str2);break; 1.case 3: 165.fileWrite(command_str2);break; 166.case 4:fileFine(command_str2);break; 167.case 5:for(i=k+1,k=0;command[i]!=' '&&command[i]!='/0';i++,k++) 168.command_str3[k]=command[i]; 169.command_str3[k]='/0'; 170.chmod(command_str2,command_str3);break; 171.case 6:for(i=k+1,k=0;command[i]!='/0';i++,k++) 172.command_str3[k]=command[i]; 173.command_str3[k]='/0'; 174.fileRen(command_str2,command_str3);break; 175.case 7:fileDir(command_str2);break; 176.case 8:fileClose(command_str2);break; 177.case 9:UFD *p; 178.for(p=userTable[userID].user->next;p!=NULL;p=p->next) //退出用户之前关闭所有打的文件 179.if(p->file->openFlag) 180.p->file->openFlag=false; 181.system("cls"); 182.userID=-1;break; 183.case 10:exit(0);break; 184.case 11:diskShow();break; 185.} 186.} 187.} 188.return 0; 1.} 190. 191.void userCreate() 192.{ 193.char c; 194.char userName[10]; 195.int i; 196.if(used 198.printf("请输入用户名:"); 199.for(i=0;c=getch();i++) 200.{ 201.if(c==13) break; 202.else 203.userName[i]=c; 204.printf("%c",c); 205.} 206.userName[i]='/0'; 207.for(i=0;i 209.if(!strcmp(userTable[i].userName,userName)) 210.{ 211.printf("/n"); 212.printf("该用户名已存在,创建用户失败/n"); 213.system("pause"); 214.return; 215.} 216.} 217.strcpy(userTable[used].userName,userName); 218.printf("/n"); 219.printf("请输入密码:"); 220.for(i=0;c=getch();i++) 221.{ 222.if(c==13) break; 223.else 224.userTable[used].password[i]=c; 225.printf("*"); 226.} 227.userTable[userID].password[i]='/0'; 228.printf("/n"); 229.printf("创建用户成功/n"); 230.used++; 231.system("pause"); 232.} 233.else 234.{ 235.printf("创建用户失败,用户已达到上限/n"); 236.system("pause"); 237.} 238.fflush(stdin); 239.} 240. 241.int login() 242.{ 243.char name[10],psw[10]; 244.char c; 245.int i,times; 246.printf("请输入用户名:"); 247.for(i=0;c=getch();i++) 248.{ 249.if(c==13) break; 250.else 251.name[i]=c; 252.printf("%c",c); 253.} 254.name[i]='/0'; 255.for(i=0;i 257.if(!strcmp(userTable[i].userName,name)) 258.break; 259.} 260.if(i==used) 261.{ 262.printf("/n您输入的用户名不存在/n"); 263.system("pause"); 2.return -1; 265.} 266.for(times=0;times<3;times++) 267.{ 268.memset(psw,'/0',sizeof(psw)); 269.printf("/n请输入密码:"); 270.for(i=0;c=getch();i++) 271.{ 272.if(c==13) break; 273.else 274.psw[i]=c; 275.printf("*"); 276.} 277.printf("/n"); 278.for(i=0;i 280.if(!strcmp(psw,userTable[i].password)) 281.{ 282.printf("用户登录成功/n"); 283.system("pause"); 284.break; 285.} 286.} 287.if(i==used) 288.{ 2.printf("您输入的密码错误,您还有%d次输入机会/n",2-times); 290.if(times==2) exit(0); 291.} 292.else break; 293.} 294.fflush(stdin); 295.return i; 296.} 297. 298.void initDisk() 299.{ 300.diskHead=(diskNode *)malloc(sizeof(diskNode)); 301.diskHead->maxlength=MaxDisk; 302.diskHead->useFlag=0; 303.diskHead->start=0; 304.diskHead->next=NULL; 305.} 306.int requestDist(int &startPostion,int maxLength) 307.{ 308.int flag=0; //标记是否分配成功 309.diskNode *p,*q,*temp; 310.p=diskHead; 311.while(p) 312.{ 313.if(p->useFlag==0&&p->maxlength>maxLength) 314.{ 315.startPostion=p->start; 316.q=(diskNode *)malloc(sizeof(diskNode)); 317.q->start=p->start; 318.q->maxlength=maxLength; 319.q->useFlag=1; 320.q->next=NULL; 321.diskHead->start=p->start+maxLength; 322.diskHead->maxlength=p->maxlength-maxLength; 323.flag=1; 324.temp=p; 325.if(diskHead->next==NULL) diskHead->next=q; 326.else 327.{ 328.while(temp->next) temp=temp->next; 329.temp->next=q; 330.} 331.break; 332.} 333.p=p->next; 334.} 335.return flag; 336.} 337. 338.void fileCreate(char fileName[],int length,char fileKind[]) 339.{ 340.//int i,j; 341.time_t rawtime; 342.int startPos; 343.UFD *fileNode,*p; 344.for(p=userTable[userID].user->next;p!=NULL;p=p->next) 345.{ 346.if(!strcmp(p->file->fileName,fileName)) 347.{ 348.printf("文件重名,创建文件失败/n"); 349.system("pause"); 350.return; 351.} 352.} 353.if(requestDist(startPos,length)) 354.{ 355.fileNode=(UFD *)malloc(sizeof(UFD)); 356.fileNode->file=(fileTable *)malloc(sizeof(fileTable)); //这一步必不可少,因为fileNode里面的指针也需要申请地址,否则fileNode->file指向会出错 357.strcpy(fileNode->file->fileName,fileName); 358.strcpy(fileNode->file->fileKind,fileKind); 359.fileNode->file->maxlength=length; 360.fileNode->file->strat=startPos; 361.fileNode->file->openFlag=false; 362.time(&rawtime); 363.fileNode->file->timeinfo=localtime(&rawtime); 3.fileNode->next=NULL; 365.if(userTable[userID].user->next==NULL) 366.userTable[userID].user->next=fileNode; 367.else 368.{ 369.p=userTable[userID].user->next; 370.while(p->next) p=p->next; 371.p->next=fileNode; 372.} 373.printf("创建文件成功/n"); 374.system("pause"); 375.} 376.else 377.{ 378.printf("磁盘空间已满或所创建文件超出磁盘空闲容量,磁盘空间分配失败/n"); 379.system("pause"); 380.} 381.} 382. 383.void freeDisk(int startPostion) 384.{ 385.diskNode *p; 386.for(p=diskHead;p!=NULL;p=p->next) 387.{ 388.if(p->start==startPostion) 3.break; 390.} 391.p->useFlag=false; 392.} 393. 394.void fileDel(char fileName[]) 395.{ 396.UFD *p,*q,*temp; 397.q=userTable[userID].user; 398.p=q->next; 399.while(p) 400.{ 401.if(!strcmp(p->file->fileName,fileName)) break; 402.else 403.{ 404.p=p->next; 405.q=q->next; 406.} 407.} 408.if(p) 409.{ 410.if(p->file->openFlag!=true) //先判断是否有进程打开该文件 411.{ 412.temp=p; 413.q->next=p->next; 414.freeDisk(temp->file->strat); //磁盘空间回收 415.free(temp); 416.printf("文件删除成功/n"); 417.system("pause"); 418.} 419.else 420.{ 421.printf("该文件已被进程打开,删除失败/n"); 422.system("pause"); 423.} 424.} 425.else 426.{ 427.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 428.system("pause"); 429.} 430.} 431. 432.void fileCat(char fileName[]) 433.{ 434.int startPos,length; 435.int k=0; 436.UFD *p,*q; 437.q=userTable[userID].user; 438.for(p=q->next;p!=NULL;p=p->next) 439.{ 440.if(!strcmp(p->file->fileName,fileName)) 441.break; 442.} 443.if(p) 444.{ 445.startPos=p->file->strat; 446.length=p->file->length; 447.p->file->openFlag=true; //文件打开标记 448.printf("*****************************************************/n"); 449.for(int i=startPos;k 451.if(i%50==0) printf("/n"); //一行大于50个字符换行 452.printf("%c",disk[i]); 453.} 454.printf("/n/n*****************************************************/n"); 455.printf("%s已被read进程打开,请用close命令将其关闭/n",p->file->fileName); 456.system("pause"); 457.} 458.else 459.{ 460.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 461.system("pause"); 462.} 463.} 4. 465.void fileWrite(char fileName[]) 466.{ 467.UFD *p,*q; 468.q=userTable[userID].user; 469.int i,k,startPos; 470.for(p=q->next;p!=NULL;p=p->next) 471.{ 472.if(!strcmp(p->file->fileName,fileName)) 473.break; 474.} 475.if(p) 476.{ 477.if(!strcmp(p->file->fileKind,"r")) //判断文件类型 478.{ 479.printf("该文件是只读文件,写入失败/n"); 480.system("pause"); 481.return; 482.} 483.char str[500]; 484.printf("please input content:/n"); 485.gets(str); 486.startPos=p->file->strat; 487.p->file->openFlag=true; //文件打开标记 488.p->file->length=strlen(str); 4.if(p->file->length>p->file->maxlength) 490.{ 491.printf("写入字符串长度大于该文件的总长度,写入失败/n"); 492.system("pause"); 493.return; 494.} 495.for(i=startPos,k=0;k<(int)strlen(str);i++,k++) 496.disk[i]=str[k]; 497.printf("文件写入成功,请用close命令将该文件关闭/n"); 498.system("pause"); 499.} 500.else 501.{ 502.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 503.system("pause"); 504.} 505.} 506. 507.void fileFine(char fileName[]) 508.{ 509.UFD *p,*q; 510.q=userTable[userID].user; 511.for(p=q->next;p!=NULL;p=p->next) 512.{ 513.if(!strcmp(p->file->fileName,fileName)) 514.break; 515.} 516.if(p) 517.{ 518.printf("********************************************/n"); 519.printf("文件名:%s/n",p->file->fileName); 520.printf("文件长度:%d/n",p->file->maxlength); 521.printf("文件在存储空间的起始地址:%d/n",p->file->strat); 522.printf("文件类型:%s/n",p->file->fileKind); 523.printf("创建时间:%s/n",asctime(p->file->timeinfo)); 524.printf("********************************************/n"); 525.system("pause"); 526.} 527.else 528.{ 529.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 530.system("pause"); 531.} 532.} 533. 534.void chmod(char fileName[],char kind[]) 535.{ 536.UFD *p,*q; 537.q=userTable[userID].user; 538.for(p=q->next;p!=NULL;p=p->next) 539.{ 540.if(!strcmp(p->file->fileName,fileName)) 541.break; 542.} 543.if(p) 544.{ 545.strcpy(p->file->fileKind,kind); 546.printf("修改文件类型成功/n"); 547.system("pause"); 548.} 549.else 550.{ 551.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 552.system("pause"); 553.} 554.} 555. 556.void fileRen(char fileName[],char name[]) 557.{ 558.UFD *p,*q; 559.q=userTable[userID].user; 560.for(p=q->next;p!=NULL;p=p->next) 561.{ 562.if(!strcmp(p->file->fileName,fileName)) 563.break; 5.} 565.if(p) 566.{ 567.while(q->next) 568.{ 569.if(!strcmp(q->next->file->fileName,name)) 570.{ 571.printf("您输入的文件名已存在,重命名失败/n"); 572.system("pause"); 573.return; 574.} 575.q=q->next; 576.} 577.strcpy(p->file->fileName,name); 578.printf("重命名成功/n"); 579.system("pause"); 580.} 581.else 582.{ 583.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 584.system("pause"); 585.} 586.} 587. 588.void fileDir(char userName[]) 5.{ 590.UFD *p; 591.int i,k; 592.for(i=0;i 594.if(!strcmp(userTable[i].userName,userName)) 595.{ 596.k=i;break; 597.} 598.} 599.if(i==MaxUser) 600.{ 601.printf("没有找到该用户,请检查输入用户名是否正确/n"); 602.system("pause"); 603.return; 604.} 605.else 606.{ 607.p=userTable[k].user->next; 608.printf("********************************************************************************/n"); 609.printf("文件名 文件长度 文件在磁盘的起始地址 文件类型 创建时间/n"); 610.for(;p!=NULL;p=p->next) 611.printf("%s %d %d %s %s",p->file->fileName, 612.p->file->maxlength,p->file->strat,p->file->fileKind,asctime(p->file->timeinfo)); 613.printf("********************************************************************************/n"); 614.system("pause"); 615.} 616.} 617. 618.void diskShow() 619.{ 620.diskNode *p; 621.int i=0,unusedDisk=0; 622.printf("***************************************************************************/n"); 623.printf(" 盘块号 起始地址 容量(bit) 是否已被使用/n"); 624.for(p=diskHead;p!=NULL;p=p->next,i++) 625.{ 626.if(p->useFlag==false) unusedDisk+=p->maxlength; 627.printf(" %d %d %d %d /n",i,p->start,p->maxlength,p->useFlag); 628.} 629.printf("***************************************************************************/n"); 630.printf("磁盘空间总容量:512*1024bit 已使用:%dbit 末使用:%dbit/n/n",MaxDisk-unusedDisk, 631.unusedDisk); 632.system("pause"); 633.} 634. 635.void fileClose(char fileName[]) 636.{ 637.UFD *p,*q; 638.q=userTable[userID].user; 639.for(p=q->next;p!=NULL;p=p->next) 0.{ 1.if(!strcmp(p->file->fileName,fileName)) 2.break; 3.} 4.if(p) 5.{ 6.p->file->openFlag=false; 7.printf("%s文件已关闭/n",p->file->fileName); 8.system("pause"); 9.} 650.else 651.{ 652.printf("没有找到该文件,请检查输入的文件名是否正确/n"); 653.system("pause"); 654.} 655.}
