📄 os.cpp
字号:
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
#include<iostream.h>
#include<windows.h>
#include "define.h"
/***************************************************************************************************************
创建文件系统
****************************************************************************************************************/
void create_file_system()
{
fp=fopen(file_system_name,"wb+"); //以读写方式打开,如果存在,则覆盖原来信息,
if(fp==NULL) //否则创建该文件
{
cout<<"Create file system error!\n"<<endl;
exit(1);
}
//申请空间
int total=sizeof(int)*(DIR_NUM+FILE_NUM+BLOCK_NUM+3)+sizeof(struct dir_node)*DIR_NUM+sizeof(struct file_node)*FILE_NUM+BLOCK_SIZE*BLOCK_NUM;
for(long len=0;len<total;len++)
fputc(0,fp);
fseek(fp,0,SEEK_SET); //写超级块信息
used_dir=1;
fwrite(&used_dir,sizeof(int),1,fp);
used_file=0;
used_block=0;
fwrite(&used_file,sizeof(int),2,fp);
dir_flag[0]=1;
fwrite(&dir_flag[0],sizeof(int),1,fp); //标志对应目录节点、文件节点的使用情况
fwrite(&dir_flag[1],sizeof(int),DIR_NUM+FILE_NUM+BLOCK_NUM-1,fp);
strcpy(dir[0].dir_name,"A:"); //写根目录信息
dir[0].dir_count=0;
dir[0].file_count=0;
dir[0].parent=-1;
GetLocalTime(&dir[0].ctime); //获得当前时间
fwrite(&dir[0],sizeof(struct dir_node),1,fp);
for(int i=0;i<DIR_NUM;i++) //将所有标记清零
{
al_dir[i]=0;
al_dflag[i]=0;
dir[i].dir_count=0;
dir[i].file_count=0;
}
for(i=0;i<FILE_NUM;i++)
{
al_file[i]=0;
al_fflag[i]=0;
open_files[i]=0;
}
for(i=0;i<BLOCK_NUM;i++)
al_bflag[i]=0;
for(i=0;i<BUF_NUM;i++)
buffer[i].flag=0;
fflush(fp);
fclose(fp);
}
/***************************************************************************************************************
搜索目录或文件,成功则返回该文件或目录的索引失败则返回-1,
type用来区分要搜索的是文件还是目录0表示目录,1表示文件,
index用来指定找到的文件或目录在父目录下的位置
****************************************************************************************************************/
int search(int parent,char *name,int type,int &index)
{
struct dir_node *p=&dir[parent];
int i,temp;
if(type==0) //表示目录
for(i=0;i<p->dir_count;i++)
{
temp=p->child_dir[i];
if(strcmp(name,dir[temp].dir_name)==0)// 字符串相等时
{
index=i;
return temp;
}
}
else
for(i=0;i<p->file_count;i++)//表示找文件
{
temp=p->child_file[i];
if(strcmp(name,file[temp].file_name)==0)
{
index=i;
return temp;
}
}
return -1;
}
/***************************************************************************************************************
根据输入的字符串,获得父目录及真正的文件或目录名,引用参数p用来指定目录或文件名的起始位置
****************************************************************************************************************/
int get_parent(char *name,int &p)
{
char buf[32],*path,*s;
int pos,start=0,index;
path=new char[128];
strcpy(path,name);
s=strrchr(path,'/'); //如果没有指定路径,则将当前目录指定为父目录
if(s==NULL)
return curr;
pos=(int)(s-path);
p=pos+1;
if(p==(int)strlen(path))
return -1;
path[p]='\0';
s=strchr(path,'/');
pos=(int)(s-path);
if(strncmp(path,"A:",pos)!=0) //前面没有跟根目录名,则从当前目录往下搜索
start=curr;
else
path+=3;
while(start!=-1 && (int)strlen(path)>0) //进行搜索,知道路径名结束或出现不匹配
{
s=strchr(path,'/');
pos=(int)(s-path);
strncpy(buf,path,pos);
buf[pos]='\0';
start=search(start,buf,0,index);
path+=pos+1;
}
return start;
}
/***************************************************************************************************************
为文件申请磁盘块,一次调用申请一块,成功则返回磁盘块索引,失败返回-1
****************************************************************************************************************/
int get_block(int pos)
{
for(int i=0;i<BLOCK_NUM;i++)
if(block_flag[i]==0)
{ //修改磁盘块使用情况及文件的控制信息
block_flag[i]=1;
al_bflag[i]++; //目录节点占用标志
used_block++; //已用的磁盘块数
int top=file[pos].block_count;
file[pos].block[top]=i;
file[pos].block_count++;
return i;
}
return -1;
}
/***************************************************************************************************************
释放文件占用的磁盘块,用于删除文件时用
****************************************************************************************************************/
void return_block(int pos)
{
for(int i=0;i<file[pos].block_count;i++)
{
int temp=file[pos].block[i];
block_flag[temp]=0;
al_bflag[temp]++;
}
used_block-=file[pos].block_count;
}
int get_dir(int parent,char *dir_name) //创建目录节点,成功则返回目录的索引,失败则返回-1
{
int index;
if(search(parent,dir_name,0,index)!=-1) //搜索在父目录下是否有同名目录,有则创建失败
{
cout<<"Directory name repeated!"<<endl;
return -1;
}
for(int i=1;i<DIR_NUM;i++) //搜索空闲的目录节点
if(dir_flag[i]==0)
{ //登记并给目录节点初始化
dir_flag[i]=1;
al_dflag[i]++;
al_dir[i]++;
used_dir++;
strcpy(dir[i].dir_name,dir_name);
dir[i].dir_count=0;
dir[i].file_count=0;
dir[i].parent=parent;
GetLocalTime(&dir[i].ctime); //获得当前时间
return i;
}
return -1;
}
/***************************************************************************************************************
创建文件节点,成功则返回文件的索引号,失败返回-1
****************************************************************************************************************/
int get_file(int parent,char *file_name)
{
int index;
if(search(parent,file_name,1,index)!=-1) //搜索在父目录下是否有同名文件存在,有则创建失败
{
cout<<"File name repeated!"<<endl;
return -1;
}
for(int i=0;i<FILE_NUM;i++) //搜索空闲的文件节点
if(file_flag[i]==0)
{
strcpy(file[i].file_name,file_name);
file[i].block_count=0;
if(get_block(i)==-1) //给新创建的文件申请磁盘块,如果失败,创建文件
{ //将失败
cout<<"Disk volumn error!"<<endl;
return -1;
}
file_flag[i]=1;
al_fflag[i]++; //登记并给文件节点初始化
al_file[i]++;
used_file++;
file[i].file_length=0;
file[i].parent=parent;
GetLocalTime(&file[i].ctime); //获得当前时间
return i;
}
return -1;
}
/***************************************************************************************************************
给文件申请缓冲区,打开文件时调用,失败时返回-1
****************************************************************************************************************/
int get_buffer(int pos)
{
for(int i=0;i<BUF_NUM;i++)
if(buffer[i].flag==0) //buffer[] 缓冲区数组
{
buffer[i].flag=1; //修改使用标志并初始化
buffer[i].file_id=pos;
buffer[i].length=0;
buffer[i].offset=0;
return i;
}
return -1;
}
/***************************************************************************************************************
得到被打开文件的缓冲区索引号,失败则返回-1
****************************************************************************************************************/
int get_buffer_id(int pos)
{
for(int i=0;i<BUF_NUM;i++)
if(buffer[i].flag==1 && buffer[i].file_id==pos)
return i;
return -1;
}
/***************************************************************************************************************
在指定的目录下创建文件,如果创建成功则返回文件的索引号,否则返回-1
如果父目录已满,则创建失败
****************************************************************************************************************/
int create_file(int parent,char *file_name)
{
if(dir[parent].file_count==16)
{
cout<<"Parent directory is full!"<<endl;
return -1;
}
int pos=get_file(parent,file_name); //开始创建文件
if(pos==-1)
{
cout<<"Create file error!"<<endl;
return -1;
}
struct dir_node *p=&dir[parent]; //修改父目录的控制信息
int top=p->file_count;
p->child_file[top]=pos;
p->file_count++;
al_dir[parent]++;
return pos;
}
/***************************************************************************************************************
在指定的目录下创建目录,如果成功则返回目录的索引号,否则返回-1
如果父目录已满,则创建失败
****************************************************************************************************************/
int create_dir(int parent,char *dir_name)
{
if(dir[parent].dir_count==8)
{
cout<<"Parent directory is full!"<<endl;
return -1;
}
int pos=get_dir(parent,dir_name); //开始创建目录
if(pos==-1)
{
cout<<"Create directory error!"<<endl;
return -1;
}
struct dir_node *p=&dir[parent]; //修改父目录的控制信息
int top=p->dir_count;
p->child_dir[top]=pos;
p->dir_count++;
al_dir[parent]++;
return pos;
}
/***************************************************************************************************************
创建目录的主调函数,它的参数只有用户输入
如果创建成功,则返回目录的索引号,否则返回-1
****************************************************************************************************************/
int md(char *name)
{
int parent,p=0;
parent=get_parent(name,p);
if(parent==-1) //父目录找不到,输入有误,创建失败
{
cout<<"Path name error!"<<endl;
return -1;
}
return create_dir(parent,name+p); //开始创建目录
}
/***************************************************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -