实验四 文件系统实验报告

实验四 文件系统实验

一 .   目的要求 

1、用高级语言编写和调试一个简单的文件系统,模拟文件管理的工作过程。从而对各种文件操作命令的实质内容和执行过程有比较深入的了解。

2、要求设计一个 n个用户的文件系统,每次用户可保存m个文件,用户在一次运行中只能打开一个文件,对文件必须设置保护措施,且至少有Create、delete、open、close、read、write等命令。

二 .   例题:

1、设计一个10个用户的文件系统,每次用户可保存10个文件,一次运行用户可以打开5个文件。

2、程序采用二级文件目录(即设置主目录[MFD])和用户文件目录(UED)。另外,为打开文件设置了运行文件目录(AFD)。

3、为了便于实现,对文件的读写作了简化,在执行读写命令时,只需改读写指针,并不进行实际的读写操作。

4、算法与框图: 

①因系统小,文件目录的检索使用了简单的线性搜索。

②文件保护简单使用了三位保护码:允许读写执行、对应位为 1,对应位为0,则表示不允许读写、执行。

③程序中使用的主要设计结构如下:

  主文件目录和用户文件目录( MFD、UFD)

  打开文件目录( AFD)(即运行文件目录)

文件系统算法的流程图如下:

三 . 实验题: 

1、增加 2~3个文件操作命令,并加以实现。(如移动读写指针,改变文件属性,更换文件名,改变文件保护级别)。

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include <conio.h>

#define MAXSIZE 100
#define ADDSIZE 50
#define PT elem+l-> length
#define N 4
typedef struct term{/*班级和学期的结构体*/
char class1[10];
char term1[10];
}term;

typedef struct student{/*学生成绩信息的结构体*/
term st;/*班级和学期结构体放于此结构体中*/
char num[10];
char name[12];
float course[4];
float total;
float average;
int bit;
}lnode,*stu;

typedef struct{
lnode *elem;/*指向上个结构体的指针*/
int size;/*最大能放lnode结构体成员的个数*/
int length;/*当前长度*/
}sqack,*sq;
sqack *l;


void init(void)/*动态分配存储空间*/
{
l-> elem=(stu)malloc(MAXSIZE*sizeof(lnode));
l-> length =0;
l-> size=MAXSIZE;
}


void input(void)/*输入学生的信息*/
{
lnode *newbase,*p;
char cla[10],ter[10],ch;
int n,i;

if(l-> length> =l-> size){
newbase=(stu)realloc(l-> elem,(l-> size +ADDSIZE)*sizeof(lnode));/*追加存储空间*/
l-> elem =newbase;
l-> size +=ADDSIZE;
}

p=l-> elem;
do
{
printf( "输入班级和学期(学期用这种格式,如20##年上学期 20## 1,20##年下学期 20## 2;先输入班级,回车后再输入学期)\n ");
gets(cla);
gets(ter);
printf( "要输入多少个名单? ");
scanf( "%d ",&n);
printf( "输入学生的成绩\n学号\t姓名\t科目1\t科目2\t科目3\t科目4\n ");

for(i=0;i <n;i++)
{
scanf( "%s%s%d%d%d%d ",p-> num ,p-> name,p-> course[0],p-> course[1],p-> course[2],p-> course[3]);
strcpy(p-> st.class1,cla);
strcpy(p-> st.term1,ter);
++l-> length ;
}
printf( "要继续吗?(y/n) ");
ch=getchar();}while(ch== 'Y '||ch== 'y ');
}

void change()/*修改学生的信息*/
{
lnode *p;
lnode e;
int flag=1,i;

char s1[10],num1[10];
printf( "输入学期和学号(输入学期以后按回车再输入学号):\n ");
gets(s1);
gets(num1);
p=l-> elem ;

while(p <=(l-> elem+l-> length ) && flag==1)/*查找要修改的学生的信息*/
{
if(strcmp(p-> num,num1)==0&&strcmp(p-> st.term1,s1)==0)
flag=0;/*找到了*/
p++;
}

p--;
if(flag==1) printf( "找不到此学号!\n ");

printf( "%s %s ",p-> num,p-> name);

for(i=0;i <N;i++)
printf( "%d ",p-> course[i]);

printf( "\n ");
printf( "输入修改信息\n ");

scanf( "%s%s%s%s ",e.st.class1,e.st.term1,&e.num,e.name);

for(i=0;i <N;i++)
scanf( "%d ",&e.course[i]);
*p=e;
}

void same(char *t1,char *t2,lnode *t,int *k) /*把学期和班级相同的学生信息放在结构体数组tt中*/
{
int i=0;
lnode *p,*q;
q=t;
p=l-> elem ;

while(p <=l-> elem+l-> length )
{
if(strcmp(p-> st.term1,t1)==0&&strcmp(p-> st.class1 ,t2)==0)
{
*q=*p;q++;
i++;
}
p++;
}
*k=i;
}

void sort(lnode *p,int *k)/*按学生成绩从高到低排序函数*/
{
int i;
lnode *q,temp;

for(q=p;q <p+ *k;q++)
{
q-> total =0;

for(i=0;i <N;i++)
q-> total =q-> total +q-> course [i];

q-> average =q-> total /N;
}

for(i=0;i <*k-1;i++)
for(q=p;q <p+*k-1-i;q++)

if(q-> total <(q+1)-> total)
{
temp=*q;*q=*(q+1);*(q+1)=temp;
}
}

void print(lnode *q,int *k)/*输出学生的成绩*/
{

lnode *p;
p=q;

for(p=q;p <q+*k;p++)
{
printf( "%s %s ",p-> num,p-> name);

for(int i=0;i <N;i++)
printf( "%d ",p-> course[i]);

printf( "%d %f ",p-> total,p-> average);
printf( "\n ");
}
}

void stat()/*统计学生的成绩*/
{
lnode tt[50];
char ter[10],clas[10];
int i,k;

printf( "请输入学期和班级(输入学期后按回车再输入班级):\n ");

for(i=0;ter[i]!= '\n ';i++)
ter[i]=getchar();
for(i=0;clas[i]!= '\n ';i++)
clas[i]=getchar();

same(ter,clas,tt,&k);/*把学期和班级相同的学生信息放在结构体数组tt中*/
sort(tt,&k);/*按学生成绩从高到低排序函数*/
print(tt,&k);/*输出学生的成绩*/
}

void search1()/*按学号查*/
{
lnode *p;
char ter1[10];
int i,flag=1;

p=l-> elem;
printf( "输入学号: ");
gets(ter1);

for(p=l-> elem;p <l-> PT;p++)
{
if(strcmp(p-> num,ter1)==0)
{
flag=0;
printf( "%s %s ",p-> st.term1,p-> st.class1);
printf( "%s %s ",p-> num,p-> name);

for(i=0;i <N;i++)
printf( "%d ",p-> course[i]);

printf( "%d %3.1f ",p-> total,p-> average);
printf( "\n ");
}
}

if(flag) printf( "没有找到! ");

}


void search2()/*按姓名查*/
{
lnode *p;
char ter1[10];
int i,flag=1;
p=l-> elem;

printf( "输入姓名: ");
gets(ter1);

for(p=l-> elem;p <l-> PT;p++)
{
if(strcmp(p-> name,ter1)==0)
{
flag=0;
printf( "%s %s ",p-> st.term1,p-> st.class1);
printf( "%s %s ",p-> num,p-> name);

for(i=0;i <N;i++)
printf( "%d ",p-> course[i]);

printf( "%d %f ",p-> total,p-> average);
printf( "\n ");
}
}

if(flag) printf( "没有找到! ") ;
}

void search()/*查找学生的成绩*/
{
char ch;
do
{
printf( "1 按学号查询\n2按姓名查询\n ");
ch=getchar();

switch(ch)
{
case '1 ':
search1();
break;
case '2 ':
search2();
break;

default:
printf( "错误!\n ");
}

printf( "要继续查找吗?(y/n) ");
ch=getchar();
} while(ch== 'y ' || ch== 'Y ');
}

void fail()/*查找不及格及学生名单*/
{
int i;
lnode *p;

for(p=l-> elem;p <l-> PT;p++)
{
for(i=0;i <N;i++)
if(p-> course[i] <60)
{
printf( "%s %s ",p-> st.class1,p-> st.term1);

for(i=0;i <N;i++)
printf( "%d ",p-> course[i]);

printf( "%d %f ",p-> total,p-> average);
printf( "\n ");}}
}


void output()/*按班级输出学生的成绩单*/
{
lnode tt[50];
int k;
char clas[10],ter1[10];

printf( "输入要查询的班级和学期(输入班级后按回车输入学期):\n ");
gets(clas);
gets(ter1);
same(ter1,clas,tt,&k);/*把学期和班级相同的学生信息放在结构体数组tt中*/
print(tt,&k);/*输出学生的成绩*/
}


int main()
{
char ch;
do
{
printf( "请选择:\n ");
printf( "1 对学生成绩的录入\n2 对学生成绩的修改\n3 统计学生成绩\n4 查询学生成绩\n5查找不及格科目及学生名单\n6 按班级输出学生成绩单\n ");
ch=getchar();

switch(ch)
{
case '1 ': input();break;
case '2 ':change();break;
case '3 ':stat();break;
case '4 ':search();break;
case '5 ':fail();break;
case '6 ':output();break;
default:printf( "错误!\n ");
}

printf( "要继续吗?(y/n) ");
ch=getchar();
}while(ch== 'y '||ch== 'Y ');

return 0;
getch();
}

2、编一个通过屏幕选择命令的文件管理系统,每屏要为用户提供足够的选择信息,不需要打入冗长的命令。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//主文件结构体
struct MasterFile{
char username[20]; //用户名
char password[20]; //用户名密码
char flag; //标志
struct MasterFile *next;
};
//用户文件结构体
struct UserFile{
int fnum; //文件编号
char fname[20]; //文件名
int flength; //文件长度
char flag; //标志
char fpw[20]; //文件保护码
struct UserFile *link;
};
//全局变量
int shoudsave; //存储标记
int usingnum; //当前用户标记
struct MasterFile MFD[20]; //主目录
struct UserFile UFD[20][20]; //用户目录


//寻找主目录空闲区
struct MasterFile*MoveMFDToLast()
{
for(int i=0;i<20;i++){
if(MFD[i].flag==0)
usingnum=i;
return &MFD[i];
}
return NULL;
}

//查找用户
struct MasterFile*SearchMFD(char str[]){
for(int i=0;i<20;i++){
if(strcmp(str,MFD[i].username)==0){
usingnum=i;
return &MFD[i];
}
}
return NULL;
}
//寻找用户目录空闲区
struct UserFile *MoveUFDToLast(){
for(int i=0;i<20;i++){
if(UFD[usingnum][i].flag==0)
return &UFD[usingnum][i];
}
return NULL;
}
//查找用户文件
struct UserFile *SearchUFD(int num){
for(int i=0;i<20;i++){
if(UFD[usingnum][i].fnum==num)
return &UFD[usingnum][i];
}
return NULL;
}

//删除用户文件目录
void LeftMoveUFD(int num){
for(int i=0;i<20;i++){
if(UFD[usingnum][i].fnum==num){
for(int j=i;j<19;j++){
UFD[usingnum][i].flag=UFD[usingnum][i+1].flag;
UFD[usingnum][i].flength=UFD[usingnum][i+1].flength;
strcpy(UFD[usingnum][i].fname,UFD[usingnum][i+1].fname);
UFD[usingnum][i].fnum=UFD[usingnum][i+1].fnum;
strcpy(UFD[usingnum][i].fpw,UFD[usingnum][i+1].fpw);
UFD[usingnum][i].link=UFD[usingnum][i+1].link;
}
}
}
}

//用户登陆
void Login(){
char flag1,flag2,flag3;
char str1[20],str2[20],str3[20],str4[20];
struct MasterFile *p;
printf("你是已有用户吗(y/n)?");
scanf("%s",&flag1);
if(flag1=='n'){ //新用户登录
printf("请创建新的用户:(y/n)");
scanf("%s",&flag2);
if(flag2=='n'){
printf("你已退出了系统!\n");
exit(1);
}else{
printf("请输入你的用户名:");
scanf("%s",&str1);
printf("请输入口令:");
scanf("%s",&str2);
p=MoveMFDToLast();
strcpy(p->username,str1);
strcpy(p->password,str2);
p->flag=1;
printf("%d",MFD[usingnum].flag);
p->next=NULL;
shoudsave=1; //存储标记
}
}else{ //旧用户登录
while(1){
printf("请输入你的用户名:"); //输入用户名
scanf("%s",&str3);
p=SearchMFD(str3);
if(p==NULL){
printf("对不起,你输入的用户名不存在!\n");
printf("继续(y)还是放弃(n)?");
scanf("%s",&flag3);
if(flag3=='y') continue;
else{
printf("你已退出了系统!\n");
exit(1);
}
}else{
while(1){
printf("请输入口令:"); //输入口令
scanf("%s",&str4);
if(strcmp(str4,p->password)!=0){
printf("对不起,你输入的口令不正确,请重新输入.\n");
continue;
}else break;
}
}break;
}
}
}

//菜单
void menu(){
printf("\n********************************************************************************");
printf("\t1列文件目录\t\t\t\t\t2创建文件\n");
printf("\t3删除文件\t\t\t\t\t4读文件\n");
printf("\t5写文件\t\t\t\t\t\t0退出系统\n");
printf("********************************************************************************\n");
}

//列文件目录
void Dir(){
if(MFD[usingnum].next==0)
printf("目前你不存在任何文件!\n");
else{
for(int i=0;i<20;i++){
if(UFD[usingnum][i].flag==1)
printf("文件编号\t%d\t文件名\t%s\t文件长度\t%d\t保护码\t%s\n",UFD[usingnum][i].fnum,UFD[usingnum][i].fname,UFD[usingnum][i].flength,UFD[usingnum][i].fpw);
}
}
}

//创建文件
void Create(){
FILE *fp;
int num;
struct UserFile *f;
char str1[20],str2[20];
printf("请输入你要创建的文件名:"); //输入文件信息
scanf("%s",&str1);
printf("请输入文件编号:");
scanf("%d",&num);
printf("请输入文件保护码:");
scanf("%s",&str2);
fp=fopen(str1,"w"); //创建文件
f=MoveUFDToLast(); //寻找用户目录空闲区
if(&UFD[usingnum][0]==f) //连接主目录
MFD[usingnum].next=(struct MasterFile*)f;
f->link=(struct UserFile*)fp; //设置用户目录
MFD[usingnum].next=(struct MasterFile*)&UFD[usingnum][0];
strcpy(f->fname,str1);
strcpy(f->fpw,str2);
f->fnum=num;
f->flength=0;
f->flag=1;
fclose(fp);
shoudsave=1; //设置存储标记
printf("文件已创建!\n");
}

//删除文件
void Delete(){
struct UserFile *f;
int num;
printf("请输入你要删除的文件编号:");
scanf("%d",&num);
f=SearchUFD(num); //查找用户文件
if(f==NULL) {
printf("你要删除的文件不存在!\n");
}else{
LeftMoveUFD(num); //删除用户文件目录
printf("文件已删除!\n");
}
shoudsave=1; //设置存储标记
}
//读文件
void Read(){
char ch;
struct UserFile *f;
FILE *fp;
int num;
printf("请输入你要读的文件的编号:");
scanf("%d",&num);
f=SearchUFD(num); //查找文件
if(f==NULL){
printf("你输入的文件不存在!\n");
}else{
if((fp=fopen(f->fname,"r"))==NULL){ //打开指定文件
printf("不能打开该文件!\n");
exit(0);
}
}
ch=fgetc(fp); //输出文件内容
while(ch!=EOF){
putchar(ch);
ch=fgetc(fp);
}
printf("\n");
fclose(fp); //关闭文件
printf("文件已读完毕!\n");
}
//写文件
void Write(){
char ch;
struct UserFile *f;
FILE *fp;
int num;
printf("请输入你要写的文件的编号:");
scanf("%d",&num);
f=SearchUFD(num); //查找文件
if(f==NULL){
printf("你输入的文件不存在!\n");
}else{
if((fp=fopen(f->fname,"wr"))==NULL){ //打开指定文件
printf("不能打开该文件!\n");
exit(0);
}
}
printf("请按字符输入内容(以'#'表示结束符)"); //写入文件
scanf("%s",&ch);
while(ch!='#'){
fwrite(&ch,1,1,fp);
scanf("%s",&ch);
}
fclose(fp); //关闭文件
shoudsave=1; //设置存储标记
printf("文件写入完毕!\n");
}
//保存
void Save(){
FILE *fpm,*fpu;
int flag=1,count=0;
fpm=fopen("F:\\MasterFile.txt","wb"); //打开主文件
if(fpm==NULL){
printf("\n提示:重新打开主文件信息文件时发生错误!\n");
exit(1);
}
for(int i=0;i<20;i++)
fwrite(&MFD[i],sizeof(struct MasterFile),1,fpm); //保存主文件目录信息
fclose(fpm);
printf("主文件目录信息保存完毕!\n");
fpu=fopen("F:\\UserFile.txt","wb"); //打开用户文件
if(fpu==NULL){
printf("\n提示:重新打开用户目录信息文件时发生错误!\n");
exit(1);
}
for(int j=0;j<20;j++) //保存用户文件目录信息
fwrite(&UFD[j],sizeof(struct UserFile),20,fpu);
fclose(fpu);
printf("用户文件目录信息保存完毕!\n");
}


//主函数
void main(){
FILE *fpm,*fpu; //文件指针
int sel;
char ch;
char jian;
printf("\t\t\t\t文件管理系统\n\t\t\t\t\n");
fpm=fopen("D:\\MasterFile.txt","rb"); //打开主文件目录信息文件
if(fpm==NULL) {
printf("\n提示:主文件目录信息文件还不存在,是否创建?(y/n)\n");
scanf("%s",&jian);
if(jian=='y'||jian=='Y')
fpm=fopen("D:\\MasterFile.txt","wb"); //创建主文件目录的文件
else exit(0);
}
fpu=fopen("D:\\UserFile.txt","rb"); //打开用户文件目录信息文件
if(fpu==NULL){
printf("\n提示:用户文件目录信息文件还不存在,是否创建?(y/n)\n");
scanf("%s",&jian);
if(jian=='y'||jian=='Y')
fpu=fopen("D:\\UserFile.txt","wb"); //创建用户文件目录的文件
else exit(0);
}
printf("文件正在打开,请稍等...");

for(int i=0;i<20;i++) //读取主文件目录信息
fread(&MFD[i],sizeof(struct MasterFile),1,fpm); //将文件的内容放入接点中
fclose(fpm); // 关闭文件
while(!feof(fpu)){ //读取用户目录文件信息
for(int i=0;i<20;i++){
if(fread(&UFD[i][0],sizeof(struct UserFile),20,fpu)) //将文件的内容放入接点中
MFD[i].next=(struct MasterFile*)&UFD[i][0];
}
}
fclose(fpu); //关闭文件
printf("\n文件已导入完毕!\n");
Login(); //用户登录

while(1) { //菜单操作
menu();
printf("请你选择操作:");
scanf("%d",&sel);
if(sel==0){ //保存文件信息
if(shoudsave==1){
getchar();
printf("\n资料已经改动,是否将改动保存到文件中(y/n)?\n");
scanf("%c",&ch);
if(ch=='y'||ch=='Y')
Save();
}
printf("\n你已经退出系统,再见!\n");
break;
}
switch(sel){
case 1:Dir();
break; //列文件目录
case 2:Create();
break; //创建文件
case 3:Delete();
break; //删除文件
case 4:Read();
break; //读文件
case 5:Write();
break; //写文件
default: printf("你输的选项有误,请重新输入!\n");
break;
}
}
}

3、设计一个树型目录结构的文件系统,其根目录为 root,各分支可以是目录,也可以是文件,最后的叶子都是文件。

#include <stdio.h>

#include <iostream.h>

#include <string.h>

#include <ctype.h>

#include <malloc.h>

#define FILENAME_LEN 21

#define INPUT_LEN 81

#define COMMAND_LEN 11

//结点结构

struct FileNode

{

 char filename[FILENAME_LEN];//文件名/目录名

 int isdir;//目录文件识别标志

 int i_nlink;//文件的链接数

 int adr;//文件的地址

 struct FileNode *parent, *child;//指向父亲的指针和指向左孩子的指针

 struct FileNode *sibling_prev, *sibling_next;//指向前一个兄弟的指针和指向

//后一个兄弟的指针.

};

void Init();//初始化文件树

int ParseCommand();//接受输入的命令并把其分解成操作名和路径文件名

void ExecuteCommand();//执行命令

int cdComd();//处理cd命令

int editComd();//处理edit命令创建文件

int delComd();//处理del命令删除文件

int rdComd();//处理rd命令/删除目录

int dirComd();//处理dir命令

int mdComd();//处理md命令创建目录

int FindPath(char *ph);//寻找参数ph所指向的路径

//从参数Para2中找到要建立或删除的文件、目录名,并把指针指向其父亲结点

int FindFilename(char Para2[]);

struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink);//创建结点

int GetInput(char* buffer,unsigned int buffer_len);//获取输入

int CheckCommand();//命令检查

int GetDir(int begin,char* path,char* curDir);//获取路径

void Trim(char* str);

struct FileNode * cp, *tp, *root,*upper;

char path[INPUT_LEN-COMMAND_LEN];//记录当前走过的路径

char curpath[INPUT_LEN-COMMAND_LEN],Para1[COMMAND_LEN],

     Para2[INPUT_LEN-COMMAND_LEN],tmppath[INPUT_LEN-COMMAND_LEN];

char filename[FILENAME_LEN],dirname[FILENAME_LEN],tmp;

int i,j;

//主函数

int main()

{

 printf("<<<*****************09208041 杜耀军 树型目录结构的文件系统*****************>>>\n");

 Init();//初始化文件树

 while(1)

 {

  if(ParseCommand())//分解命令

   ExecuteCommand();//执行命令

 }

}

//执行命令子函数

void ExecuteCommand()

{

 int sign;

    //根据参数Para1调用相应的功能处理模块

 if(strcmp(Para1,"cd")==0)

  sign=cdComd();            //cd命令

 else if(strcmp(Para1,"edit")==0)

  sign=editComd();         //edit命令

 else if(strcmp(Para1,"del")==0)

  sign=delComd();          //del命令

 else if(strcmp(Para1,"dir")==0)

  sign=dirComd();          //dir命令

 else if(strcmp(Para1,"md")==0)

  sign=mdComd();         //md命令

 else if(strcmp(Para1,"rd")==0)

  sign=rdComd();           //rd命令

 else if(strcmp(Para1,"exit")==0)

  exit(0);                         //exit命令

 else

  printf("命令错误,请重试\n");  //命令输入不正确,报错

}

//创建结点

struct FileNode* CreateFileNode(char filename[],int isdir,int i_nlink)

{

 //申请结点空间

    struct FileNode* node=(struct FileNode*)malloc(sizeof(struct FileNode));

 //相应内容赋初值

    strcpy(node->filename,filename);

 node->isdir=isdir;

 node->i_nlink=i_nlink;

 node->parent=NULL;

 node->child=NULL;

 node->sibling_prev=NULL;

 node->sibling_next=NULL;

    return node;

}

//初始化文件树

void Init()

{

 struct FileNode *binNode,*usrNode,

   *unixNode,*etcNode,*libNode,*userNode,

   *binNode2,*liuNode,*sunNode,*ftiNode;

 strcpy(path,"/"); //根目录写入当前路径

    //创建文件树的结点

 binNode=CreateFileNode("bin",1,0);

 usrNode=CreateFileNode("usr",1,0);

 unixNode=CreateFileNode("unix",0,0);

 etcNode=CreateFileNode("etc",1,0);

 libNode=CreateFileNode("lib",1,0);

 userNode=CreateFileNode("user",1,0);

 binNode2=CreateFileNode("bin",1,0);

 liuNode=CreateFileNode("liu",1,0);

 sunNode=CreateFileNode("sun",1,0);

 ftiNode=CreateFileNode("fti",1,0);

 cp=tp=root=CreateFileNode("/",1,0);

            //结点相应内容赋值

 root->parent=NULL;

 root->child=binNode;

 root->sibling_prev=root->sibling_next=NULL;

 binNode->parent=root;

 binNode->child=NULL;

 binNode->sibling_prev=NULL;

 binNode->sibling_next=usrNode;

 usrNode->parent=NULL;

 usrNode->child=libNode;

 usrNode->sibling_prev=binNode;

 usrNode->sibling_next=unixNode;

 unixNode->parent=NULL;

 unixNode->child=NULL;

 unixNode->sibling_prev=usrNode;

 unixNode->sibling_next=etcNode;

 etcNode->parent=NULL;

 etcNode->child=NULL;

 etcNode->sibling_prev=unixNode;

 etcNode->sibling_next=NULL;

 libNode->parent=usrNode;

 libNode->child=liuNode;

 libNode->sibling_prev=NULL;

 libNode->sibling_next=userNode;

 userNode->parent=NULL;

 userNode->child=NULL;

 userNode->sibling_prev=libNode;

 userNode->sibling_next=binNode2;

 binNode2->parent=NULL;

 binNode2->child=NULL;

 binNode2->sibling_prev=userNode;

 binNode2->sibling_next=NULL;

 liuNode->parent=libNode;

 liuNode->child=NULL;

 liuNode->sibling_prev=NULL;

 liuNode->sibling_next=sunNode;

 sunNode->parent=NULL;

 sunNode->child=NULL;

 sunNode->sibling_prev=liuNode;

 sunNode->sibling_next=ftiNode;

 ftiNode->parent=NULL;

 ftiNode->child=NULL;

 ftiNode->sibling_prev=sunNode;

 ftiNode->sibling_next=NULL;

}

//获取文件或目录名,并把指针指向其父亲结点

int FindFilename(char Para2[])

{

 i=strlen(Para2)-1;

 j=0;

 while(Para2[i]!='/'&& i>=0)

 {

  filename[j]=Para2[i];

  i--; j++;

 }

 filename[j]='\0';//获得逆序的文件或目录名,存入filename中

 if(i<0) Para2[i+1]='\0';

 else Para2[i]='\0';

 j--;

            //filename逆转,获得正确的文件或目录名

 for(i=0;i<strlen(filename)/2;i++,j--)

 {

  tmp=filename[i];

  filename[i]=filename[j];

  filename[j]=tmp;

 }

 //查找路径

 if(strlen(Para2)>0)

 {

  int sign=FindPath(Para2);

  if(sign==0) return 0;

 }

 return 1;

}

//缓冲区安全输入子函数

//如果输入超过buffer_len,则截取前buffer_len-1长度的输入,

//buffer_len处字符用'/0'代替

int GetInput(char* buffer,unsigned int buffer_len)

{

 int count=0;

 while(count<buffer_len)

 {

  if((buffer[count]=getchar())==10)

  {

   buffer[count]='\0';

   return count;

  }

  count++;

 }

 while(getchar()!=10);

 buffer[buffer_len-1]='\0';

 return -1;

}

//分解命令子函数

int ParseCommand()

{

 char Inputs[INPUT_LEN];

 int i=0,j=0,k=0,ch;

 printf("%s>",path);

            //获取输入

 if(GetInput(Inputs,INPUT_LEN)==-1)

 {

  printf("输入行太长。\n");

  return 0;

 }

 Para1[0]=Para2[0]='\0';

  

 //获取参数Para1,即操作名

while(Inputs[i]!=' '&&Inputs[i]!='\0' && i<COMMAND_LEN-1)

 {  

  Para1[i]=Inputs[i];

  i++;

 }//while

 Para1[i]='\0';

 //输入命令太长

 if(i==(COMMAND_LEN-1))return 1;

 //获取参数2,即路径文件名

if(Inputs[i]!='\0')

 {   

  while(Inputs[i]==' ' && i<INPUT_LEN-1) i++;

  j=0;

  while(Inputs[i]!='\0'  && i<INPUT_LEN-1)

  { 

   Para2[j]=Inputs[i];

   i++; j++;

  }

  Para2[j]='\0';

 }

 Trim(Para1);

 Trim(Para2);

 //将操作名全部转换成小写字母

 for(k=0;k<strlen(Para1);k++)

 {

  ch=tolower((int)Para1[k]);

  Para1[k]=ch;

 }

 return 1;

}

//cd功能处理子函数

int cdComd()

{

 if(!CheckCommand())//命令检查

  return 0;

  

 if(strcmp(Para2,"..")==0)

 {          //对cd ..命令的处理

  int i;

  while(cp->sibling_prev)

   cp=cp->sibling_prev;//找到这一层最左边的结点

  if(cp->parent)

  {

   cp=cp->parent;//找到父亲结点

  }

  else

  {

      return 0;

  }

  //对当前路径进行相应处理

i=strlen(path);

  while(path[i]!='/'&& i>0) i--;

 

  if(i!=0)

   path[i]='\0';

  else

   path[i+1]='\0';

 }

 else

 {

  FindPath(Para2);//查找路径

 }

 return 1;

}

//命令格式处理子函数

void Trim(char* str)

{

 int begin,end;

 char* tmp;

 begin=0;

 end=strlen(str);

 //找到字符串第一个非空格的位置

 while(str[begin]==' ' && str[begin]!='\0')begin++;

 //去除字符串尾部空格

 while(str[--end]==' ');

 str[end+1]='\0';

 //除去空格

 if(begin<end)

 {

  tmp=(char*)malloc((sizeof(char))*(end-begin+2));

  strcpy(tmp,&str[begin]);

  strcpy(str,tmp);

  free(tmp);

 }

}

//获取当前目录名子函数

int GetDir(int begin,char* path,char* curDir)

{

 int i=0;

 int len=strlen(path);

 while(!((path[begin]=='\\' )|| (path[begin]=='/'))&&begin<len)

 {

  curDir[i++]=path[begin++];

 }

 curDir[i]='\0';

 Trim(curDir);

 return begin+1;

}

//查找路径子函数

int FindPath(char *ph)

{

 struct FileNode *tp,*temp;

 char oldpath[INPUT_LEN-COMMAND_LEN];

 int i=0;

 int sign=1;

 if(strcmp(ph,"/")==0)

 {          //ph是根目录

  cp=root;

  strcpy(path,"/");

  return 1;

 }

 temp=cp;

 strcpy(oldpath,path);//保存原路径和指针

 if(ph[0]=='/')

 {          //指针指向根目录的左孩子

  cp=root->child;

  i++;//滤过'/'

  strcpy(path,"/");

 }

 else

 {

  if(cp!=NULL && cp!=root )

   strcat(path,"/");

  if(cp && cp->child)

  {

   if(cp->isdir)

    cp=cp->child; //指针指向当前目录的左孩子

   else

   {

    printf("路径错误!\n");

    return 0;

   }

  }

 }

 while(i<=strlen(ph)&& cp)//继续查找指定路径,如遇到文件则报错

 {

  int j=0;

  if(ph[i]=='/'&& cp->child)

  {

   i++;//略过 '/'

   if(cp->isdir)

    cp=cp->child;//继续查找下级目录

   else

   {

    printf("路径错误!\n");

    return 0;

   }

   strcat(path,"/");

  }

 

  //curpath 记录当前要找的路径名

  while(ph[i]!='/'&& i<=strlen(ph))

  {

   curpath[j]=ph[i];

   i++;  j++;

  }

 

  curpath[j]='\0';

  while((strcmp(cp->filename,curpath)!=0 || (cp->isdir!=1))&& cp->sibling_next!=NULL)

  {

   cp=cp->sibling_next;

  }

  if(strcmp(cp->filename,curpath)==0 )

  {

   if(cp->isdir==0)

   {

    strcpy(path,oldpath);

    cp=temp;

    printf("是文件不是目录.\n");

    return 0;

   }

   strcat(path,cp->filename);

  }

  if(strcmp(cp->filename,curpath)!=0 || cp==NULL)

  {

   strcpy(path,oldpath);

   cp=temp;

   printf("输入路径错误\n");

   return 0;

  }

 }

 return 1;

}

//创建文件子函数

int editComd()

{

 char tmp;

 struct FileNode * temp=CreateFileNode("",0,0);

 int sign;

 struct FileNode *tp;

 //路径不能为空

if(strlen(Para2)==0)

 {

  printf("\n命令格式有错误.\n");

  return 0;

 }

 //长度检查

if(strlen(Para2)>50)

 {

  printf("\n文件名过长\n");

  return 0;

 }

            //格式检查

 if (!(isalpha(Para2[0])||Para2[0]=='_'||Para2[0]=='\0'||Para2[0]=='/'))

 {

  printf("文件名格式有错!\n");/* 文件首字母可以为'字母'或'数字'或'_'或'/'或'回车'*/

  return 0;

 }

            //获取文件名

 sign=FindFilename(Para2);

 if(sign==0)

  return 0;

           

 if(cp->isdir!=1)//如当前指针指向的是文件,则报错

 {

  printf("you cannot edit a file in under a file!\n");

  return 0;

 }

      //创建文件结点,并插入到指定目录下

 tp=CreateFileNode("",1,0);

 strcpy(tp->filename,filename);

 tp->isdir=0;

 tp->i_nlink=0;

 if(cp->child==NULL)

 { tp->parent=cp;

  tp->child=NULL;

  cp->child=tp;

     tp->sibling_prev=NULL;

     tp->sibling_next=NULL;

 }

 else

 { temp=cp;

    //用temp找到新结点插入处

  temp=temp->child;

  while(temp->sibling_next )//find the last sibing node

  {

   temp=temp->sibling_next;

   if(strcmp(temp->filename,filename)==0&&temp->isdir==0)

   {

    printf("此文件名已存在\n");//重名报错

    return 0;

   }

  }//找到了最后一个结点

 

  temp->sibling_next=tp;

  tp->parent=NULL;

  tp->child=NULL;

             tp->sibling_prev=temp;

             tp->sibling_next=NULL;

 

 }

 return 1;

}

//创建目录子函数

int mdComd()

{

 char tmp;

 int sign;

 struct FileNode * temp, *tp;

 temp=CreateFileNode("",1,0);

 //参数不能为空

if(strlen(Para2)==0)

 {

  printf("\n命令格式有错误.\n");

  return 0;

 }

 //长度检查

if(strlen(Para2)>50)

 {

  printf("\n目录名过长\n");

  return 0;

 }

            //格式检查

 if (!(isalpha(Para2[0])||Para2[0]=='_'||Para2[0]=='\0'||Para2[0]=='/'))

    {

  printf("目录名格式有错!\n");/* 目录首字母可以为'字母'或'数字'或'_'或'/'或'回车'*/

  return 0;

    }

            //获取目录名

 sign=FindFilename(Para2);

 if(sign==0) return 0;

 //若当前指针指向的是文件,则报错

if(cp->isdir!=1)

 {

  printf("you cannot make a directory in under a file!\n");

  return 0;

 }

 //创建目录结点,并插入到指定目录下

tp=CreateFileNode(filename,1,0);

 if(cp->child==NULL)

 { tp->parent=cp;

  tp->child=NULL;

  cp->child=tp;

     tp->sibling_prev=NULL;

     tp->sibling_next=NULL;

 }

 else

 { temp=cp;

    //用temp找到新结点插入处

  temp=temp->child;

  while(temp->sibling_next )//find the last sibing node

  {

   temp=temp->sibling_next;

   if(strcmp(temp->filename,filename)==0&&temp->isdir==1)

   {

    printf("此文件名已存在\n");//重名报错

    return 0;

   }

  }//找到了最后一个结点

 

  temp->sibling_next=tp;

  tp->parent=NULL;

  tp->child=NULL;

             tp->sibling_prev=temp;

             tp->sibling_next=NULL;

 

 }

 return 1;

}

//删除文件子函数

int delComd()

{

 char tmp;

 int sign;

 struct FileNode *temp;

 //参数不能为空

if(strlen(Para2)==0)

 {

  printf("\n命令格式有错误.\n");

  return 0;

 }

            //获取文件名

 sign=FindFilename(Para2);

 if(sign==0) return 0;

    

 //用temp指向要删除的结点

if(cp->child)

 {

  temp=cp->child;

  while(temp->sibling_next && (strcmp(temp->filename,filename)!=0 || temp->isdir!=0))

   temp=temp->sibling_next;

  if(strcmp(temp->filename,filename)!=0)

  {

   printf("ERROR!该命令只能删除文件,不可删除目录!\n");

   return 0;

  }

 }

 else

 {

   printf("不存在该文件!\n");

   return 0;

 }

            //要删除的不能是目录

 if(temp->isdir!=0)

 {

  printf("ERROR!该命令只能删除文件,不可删除目录!\n");

  return 0;

 }

            //如仍有用户使用该文件,则不能删除

   if(temp->i_nlink!=0)

 {

  printf("还有用户共享了该文件,不能删除!\n");

  return 0;

 }

            //删除工作

    if(temp->parent==NULL)//不是第一个孩子

 {

  temp->sibling_prev->sibling_next=temp->sibling_next;

     if(temp->sibling_next)//处理是最后一个兄弟的情况

   temp->sibling_next->sibling_prev=temp->sibling_prev;

     temp->sibling_prev=temp->sibling_next=NULL;

 }//if

 else//第一个孩子

 {

  if(temp->sibling_next)//处理是最后一个兄弟的情况

   temp->sibling_next->parent=temp->parent;

  temp->parent->child= temp->sibling_next;

 }//else

 free(temp);

 return 1;

}

//命令检查子函数

int CheckCommand()

{

 if(strlen(Para2)==0)

 {

  printf("命令语法不正确。\n");

  return 0;

 }

 return 1;

}

//删除目录子函数

int rdComd()

{

 char tmp;

 struct FileNode *temp;

 char cmd[2];

 //命令检查

if(!CheckCommand())

  return 0;

            //获取目录名

 if(!FindFilename(Para2))

  return 0;

    

 //用temp指向要删除的结点

if(cp->child)

 {

  temp=cp->child;

  while(temp->sibling_next && (strcmp(temp->filename,filename)!=0|| temp->isdir!=1))

   temp=temp->sibling_next;

  if(strcmp(temp->filename,filename)!=0)

  {

   printf("不存在该目录!\n");

   return 0;

  }

 }

 else

 {

   printf("不存在该目录!\n");

   return 0;

 }

 //要删除的不能是文件

if(temp->isdir!=1)

 {

  printf("ERROR!该命令只能删除目录,不可删除文件!\n");

  return 0;

 }

            //若要删除的目录不为空,则提示用户是否删除

 if(temp->child)

 {

  printf("\n该目录不为空,您确定要删除吗? Y/N \n");

  GetInput(cmd,2);

  if(strcmp(cmd,"n")==0||strcmp(cmd,"N")==0)

   return 0;

 }

            //删除工作

if(temp->parent==NULL)//不是第一个孩子

 {

  temp->sibling_prev->sibling_next=temp->sibling_next;

     if(temp->sibling_next)//处理是最后一个兄弟的情况

   temp->sibling_next->sibling_prev=temp->sibling_prev;

     temp->sibling_prev=temp->sibling_next=NULL;

    

  

 }//if

 else//第一个孩子

 {

  if(temp->sibling_next)//处理是最后一个兄弟的情况

   temp->sibling_next->parent=temp->parent;

  temp->parent->child= temp->sibling_next;

 }//else

 free(temp);

 return 1;

}

//显示目录子函数

int dirComd()

{

 if(strlen(Para2)>0)

 {

  int sign=FindPath(Para2);//查找路径

  if(sign==0)

  {

   return 0;

  }

  else

  {

   printf("\n%s>", path);

  }

 }

 if(cp!=root)

  printf("   <DIR>             %s\n","..");

 if(cp->child==NULL)

 {

  return 0;//指定目录为空

 }

 tp=cp;

            //指定目录不为空,显示其所有子目录及文件名

 tp=tp->child;

 while(tp)

 {

  if(tp->isdir)

   printf("   <DIR>             %s\n",tp->filename);

  else

   printf("   <FILE>            %s\n",tp->filename);

  tp=tp->sibling_next;

 }

}

相关推荐