📄 文件系统实现.c
字号:
/*----------------------------------------写文件------------------------------------------------*/
int write(int fd, char *buf, int len)
{
char *first;
int item, i, j, k;
int ilen1, ilen2, modlen, temp;
/*----------用 $ 字符作为空格 # 字符作为换行符-----------------------*/
char Space = 32; /*SPACE的ASCII码值*/
char Endter= '\n';
for(i=0;i<len;i++)
{
if(buf[i] == '$') /*用 $ 字符作为空格*/
buf[i] = Space;
else if(buf[i] == '#')
buf[i] = Endter;
}
/*----------读取用户打开表对应表项第一个盘块号-----------------------*/
item = u_opentable.openitem[fd].firstdisk;
/*-------------找到当前目录所对应表项的序号-------------------------*/
for(i=2;i<MSD+2;i++)
{
if(cur_dir->directitem[i].firstdisk==item)
break;
}
temp = i; /*-存放当前目录项的下标-*/
/*------找到的item 是该文件的最后一块磁盘块-------------------*/
while(fat[item].item!=-1)
{
item =fat[item].item; /*-查找该文件的下一盘块--*/
}
/*-----计算除该文件的最末地址-------*/
first = fdisk+item*DISKSIZE+u_opentable.openitem[fd].size%DISKSIZE;
/*-----如果最后磁盘块剩余的大小大于要写入的文件的大小-------*/
if(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE>len)
{
strcpy(first,buf);
u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len;
cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len;
}
else
{
for(i=0;i<(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);i++)
{/*写一部分内容到最后一块磁盘块的剩余空间(字节)*/
first[i] = buf [i];
}
/*-----计算分配完最后一块磁盘的剩余空间(字节) 还剩下多少字节未存储-------*/
ilen1 = len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE);
ilen2 = ilen1/DISKSIZE;
modlen = ilen1%DISKSIZE;
if(modlen>0)
ilen2 = ilen2+1; /*--还需要多少块磁盘块-*/
/*调试时特别注意*/
for(j=0;j<ilen2;j++)
{
for(i=ROOT_DISK_NO+1;i<DISK_NUM;i++)/*寻找空闲磁盘块*/
{
if(fat[i].em_disk=='0')
break;
}
if(i>=DISK_NUM) /*--如果磁盘块已经分配完了-*/
return(-1);
first = fdisk+i*DISKSIZE; /*--找到的那块空闲磁盘块的起始地址-*/
if(j==ilen2-1) /*--如果是最后要分配的一块-*/
{
for(k=0;k<len-(DISKSIZE-u_opentable.openitem[fd].size%DISKSIZE)-j*DISKSIZE;k++)
first[k] = buf[k];
}
else/*-如果不是要最后分配的一块--*/
{
for(k=0;k<DISKSIZE;k++)
first[k] =buf[k];
}
fat[item].item = i; /*--找到一块后将它的序号存放在上一块的指针中-*/
fat[i].em_disk = '1'; /*--置找到的磁盘快的空闲标志位为已分配-*/
fat[i].item = -1; /*--它的指针为 -1 (即没有下一块)-*/
}
/*--修改文件打开表用户的长度-*/
u_opentable.openitem[fd].size = u_opentable.openitem[fd].size+len;
/*--修改目录项的文件长度-*/
cur_dir->directitem[temp].size = cur_dir->directitem[temp].size+len;
}
return 0;
}
/*----------------------------------------------------------------------------------------------*/
/*----------------------------------------读文件------------------------------------------------*/
int read(int fd, char *buf)
{
int len = u_opentable.openitem[fd].size;
char *first;
int i, j, item;
int ilen1, modlen;
item = u_opentable.openitem[fd].firstdisk;
if(len>u_opentable.openitem[fd].size) /*--欲读出的文件长度比实际文件长度长-*/
return(-1);
ilen1 = len/DISKSIZE;
modlen = len%DISKSIZE;
if(modlen!=0)
ilen1 = ilen1+1; /*--计算文件所占磁盘的块数-*/
first = fdisk+item*DISKSIZE; /*--计算文件的起始位置-*/
for(i=0;i<ilen1;i++)
{
if(i==ilen1-1) /*--如果在最后一个磁盘块-*/
{
for(j=0;j<len-i*DISKSIZE;j++)
buf[i*DISKSIZE+j] = first[j];
}
else /*--不在最后一块磁盘块-*/
{
for(j=0;j<len-i*DISKSIZE;j++)
buf[i*DISKSIZE+j] = first[j];
item = fat[item].item; /*-查找下一盘块-*/
first = fdisk+item*DISKSIZE;
}
}
return 0;
}
/*----------------------------------------------------------------------------------------------*/
/*----------------------------------------删除文件----------------------------------------------*/
int del(char *name)
{
int i,cur_item,item,temp;
for(i=2;i<MSD+2;i++) /*--查找要删除文件是否在当前目录中-*/
{
if(!strcmp(cur_dir->directitem[i].name,name))
break;
}
cur_item = i; /*--用来保存目录项的序号,供释放目录中-*/
if(i>=MSD+2) /*--如果不在当前目录中-*/
return(-1);
if(cur_dir->directitem[cur_item].property!='0') /*--如果删除的(不)是目录-*/
return(-3);
for(i=0;i<MOFN;i++) /*--如果文件打开,则不能删除,退出-*/
{
if(!strcmp(u_opentable.openitem[i].name,name))
return(-2);
}
item = cur_dir->directitem[cur_item].firstdisk;/*--该文件的起始盘块号-*/
while(item!=-1) /*--释放空间,将FAT表对应项进行修改-*/
{
temp = fat[item].item;
fat[item].item = -1;
fat[item].em_disk = '0';
item = temp;
}
/*-----------------释放目录项-----------------------*/
cur_dir->directitem[cur_item].sign = 0;
cur_dir->directitem[cur_item].firstdisk = -1;
strcpy(u_opentable.openitem[cur_item].name,"");
cur_dir->directitem[cur_item].next = -1;
cur_dir->directitem[cur_item].property = '0';
cur_dir->directitem[cur_item].size = 0;
return 0;
}
/*----------------------------------------------------------------------------------------------*/
/*---------------------------------------创建子目录---------------------------------------------*/
int mkdir(char *name)
{
int i,j;
struct direct *cur_mkdir;
if(strchr(name,'\\'))/*如果目录名中有 '\'字符*/
return(-4);
if(!strcmp(name,"."))
return(-6);
if(!strcmp(name,".."))
return(-6);
if(strlen(name)>8) /*-如果目录名长度大于 8位-*/
return(-1);
for(i=2;i<MSD+2;i++) /*-如果有空闲目录项退出-*/
{
if(cur_dir->directitem[i].firstdisk==-1)
break;
}
if(i>=MSD+2) /*-目录/文件 已满-*/
return(-2);
for(j=2;j<MSD+2;j++) /*-判断是否有重名-*/
{
if(!strcmp(cur_dir->directitem[j].name,name))
break;
}
if(j<MSD+2) /*-如果有重名-*/
return(-3);
for(j=ROOT_DISK_NO+1;j<DISK_NUM;j++) /*-找到空闲磁盘块 j 后退出-*/
{
if(fat[j].em_disk=='0')
break;
}
if(j>=DISK_NUM)
return(-5);
fat[j].em_disk='1'; /*-将该空闲块设置为已分配-*/
/*-------------填写目录项----------*/
strcpy(cur_dir->directitem[i].name,name);
cur_dir->directitem[i].firstdisk=j;
cur_dir->directitem[i].size=ROOT_DISK_SIZE;
cur_dir->directitem[i].next=j; /*-指向子目录(其实就是其本身)的起始盘块号-*/
cur_dir->directitem[i].property='1';
/*-sign=1为根标志,这里可以省略-*/
/*-所创目录在虚拟磁盘上的地址(内存物理地址)-*/
cur_mkdir=(struct direct *)(fdisk+cur_dir->directitem[i].firstdisk*DISKSIZE);
/*-初始化目录-*/
/*-指向当前目录的目录项-*/
cur_mkdir->directitem[0].sign=0;
cur_mkdir->directitem[0].firstdisk=cur_dir->directitem[i].firstdisk;
strcpy(cur_mkdir->directitem[0].name,".");
cur_mkdir->directitem[0].next=cur_mkdir->directitem[0].firstdisk;
cur_mkdir->directitem[0].property='1';
cur_mkdir->directitem[0].size=ROOT_DISK_SIZE;
/*-指向上一级目录的目录项-*/
cur_mkdir->directitem[1].sign=cur_dir->directitem[0].sign;/*-指向上一级目录的目录项-*/
cur_mkdir->directitem[1].firstdisk=cur_dir->directitem[0].firstdisk;
strcpy(cur_mkdir->directitem[1].name,"..");
cur_mkdir->directitem[1].next=cur_mkdir->directitem[1].firstdisk;
cur_mkdir->directitem[1].property='1';
cur_mkdir->directitem[1].size=ROOT_DISK_SIZE;
for(i=2;i<MSD+2;i++) /*-子目录都初始化为空-*/
{
cur_mkdir->directitem[i].sign=0;
cur_mkdir->directitem[i].firstdisk=-1;
strcpy(cur_mkdir->directitem[i].name,"");
cur_mkdir->directitem[i].next=-1;
cur_mkdir->directitem[i].property='0';
cur_mkdir->directitem[i].size=0;
}
return 0;
}
/*----------------------------------------------------------------------------------------------*/
/*---------------------------------------删除子目录---------------------------------------------*/
int rmdir(char *name)
{
int i,j,item;
struct direct *temp_dir;
/*-检查当前目录项中有无该目录-*/
for(i=2;i<MSD+2;i++)
{
if(!strcmp(cur_dir->directitem[i].name,name))
break;
}
if(cur_dir->directitem[i].property!='1')/*-删除的不是目录-*/
return(-3);
if(i>=MSD+2) /*-没有这个文件或目录-*/
return(-1);
/*-判断要删除的目录有无子目录-*/
/*-要删除的目录起始地址-*/
temp_dir=(struct direct *)(fdisk+cur_dir->directitem[i].next*DISKSIZE);
for(j=2;j<MSD+2;j++)
{
if(temp_dir->directitem[j].next!=-1)
break;
}
if(j<MSD+2) /*-有子目录或文件-*/
return(-2); /*-有关联则报错,也可以采取级联删除,像Windows-*/
/*------------找到起始盘块号,并将其释放----------------*/
item=cur_dir->directitem[i].firstdisk;
fat[item].em_disk='0';
/*-修改目录项-*/
cur_dir->directitem[i].sign=0;
cur_dir->directitem[i].firstdisk=-1;
strcpy(cur_dir->directitem[i].name,"");
cur_dir->directitem[i].next=-1;
cur_dir->directitem[i].property='0';
cur_dir->directitem[i].size=0;
return 0;
}
/*----------------------------------------------------------------------------------------------*/
/*-------------------------------显示当前目录的子目录-------------------------------------------*/
void dir()
{
int i;
for(i=0;i<MSD+2;i++)
{
if(cur_dir->directitem[i].firstdisk!=-1) /*-如果存在子目录-*/
{ /*-其本身和父目录也算?-*/
printf("%s\t",cur_dir->directitem[i].name);
if(cur_dir->directitem[i].property=='0') /*-文件-*/
printf("%d\t\t\n",cur_dir->directitem[i].size);
else /*-目录-*/
printf("\t<DIR>\t\n");
}
}
}
/*----------------------------------------------------------------------------------------------*/
/*---------------------------------------更改当前目录-------------------------------------------*/
int cd(char *name)
{
int i,j,item;
char *str,*str1;
char *temp,*point,*point1;
struct direct *temp_dir;
temp_dir=cur_dir; /*-先用临时目录代替当前目录-*/
str=name; /*-str用来记录下次查找的起始地址-*/
if(!strcmp("\\",name)) /*如果输入"\" ,回根目录*/
{
cur_dir = root;
strcpy(bufferdir,"Root:");
return 0;
}
j=0;
for(i=0;i<(int)strlen(str);i++)/*查找有两个连续是"\",即"\\",退出 */
{
if(name[i]=='\\')
{
j++;
if(j>=2)
{
return -3;
}
}
else
j=0;
}
if(name[0]=='\\') /*如果最后一个是"\" ,去掉这个"\"*/
{
temp_dir = root;
strcpy(bufferdir,"Root:");
str++;
}
if(str[strlen(str)-1] == '\\')
{
str[strlen(str)-1] = '\0';
}
str1=strchr(str,'\\'); /*-找到'\'字符的位置-*/
temp = (char *)malloc(DIR_LENGTH*sizeof(char));/*-为子目录的名字分配空间-*/
while(str1!=NULL) /*-找到-*/
{
for(i=0;i<str1-str;i++)
{
temp[i]=str[i];
}
temp[i]='\0';
for(j=2;j<MSD+2;j++) /*-查找该子目录是否在当前目录中-*/
{
if(!strcmp(temp_dir->directitem[j].name,temp))
break;
}
if(j>=MSD+2) /*-不在当前目录-*/
return(-1);
item=temp_dir->directitem[j].firstdisk;
temp_dir=(struct direct *)(fdisk+item*DISKSIZE); /*-计算当前目录物理位置-*/
str=str1+1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -