📄 fdtana.c
字号:
/*************************************************************************/
/*************************************************************************/
#include <stdio.h>
#include <bios.h> /*TC下运行需要(biosdisk())*/
/*宏定义*/
#define CATTOTAL 16*16 /*总的文件目录项*/
#define CATLEN 32 /*文件目录项的长度*/
#define MAXSIZE 512*16 /*数组的最大容量*/
#define HEAD 255 /*每个柱面磁头数*/
#define SECTOR 63 /*每个磁头扇区数*/
#define SECBYTE 512 /*每个扇区字节数*/
#define SECTOTAL 16 /*要读的扇区数*/
/*结构体类型申明*/
typedef struct CHSVal /*存放扇区地址*/
{
int cyl;
int head;
int sec;
}CHS;
typedef struct createtime /*记录时间*/
{
short int sec;
short int min;
short int hour;
}TIME;
typedef struct createdate /*记录日期*/
{
short int day;
short int mon;
short int year;
}DATE;
typedef struct diskinfo /*记录磁盘的基本属性*/
{
int isActive; /*判断是否是活动驱动器*/
int fileSysType; /*记录驱动器的文件系统类型*/
int byteVals[10]; /*记录驱动器的大小以及起始和终止的扇区地址*/
long isNext; /*判断是否是最后一个分区*/
}DINFO;
typedef struct FDTInfo /*记录FDT信息*/
{
short int fName[8]; /*存放文件名*/
short int extName[3]; /*存放扩展名*/
short int createTime[2];
short int createDate[2];
short int startAdd[2]; /*起始簇地址*/
long fSize[4];
short int fProperty;
long isEOF; /*用来判断FDT是否结束*/
}FDT;
typedef struct retArr /*存放一个数组,处理1个字节*/
{
int arr[8];
}ARR;
typedef struct DVArr /*存放一个数组,处理两个字节*/
{
int arr[16];
}DARR;
/*函数申明*/
void ReadSec(char name[],int cyl,int head,int len); /*读取扇区地址*/
int RetByteLow(int byteVal); /*返回一个字节的底4位*/
int RetByteHigh(int byteVal); /*返回一个字节的高四位*/
long DataConversion(int arr[],int len,int r); /*将数组代表的数字转换成十进制(长度为len的Arr是r进制)*/
long StartAdd(FDT fdtInfo); /*计算文件的起始地址*/
void PrintProperty(int fProperty); /*显示文件属性*/
int IsFolder(int fProperty); /*判断FDT代表是否是文件夹*/
FDT RetCatalog(int catalog,FILE*fp); /*从文件目录表返回长度为32个字节的文件目录项*/
TIME RetCraeteTime(FDT fdtInfo); /*返回文件或文件夹创建或更新的时间*/
DATE RetCreateDate(FDT fdtInfo); /*返回文件或文件夹创建和更新的日期*/
void AnalyzeFDT(FILE*fp); /*分析文件目录项*/
void DisSecInfo(FILE*fp,int byte); /*显示扇区数据信息*/
void PrintLongName(); /*显示长文件名*/
void CombLongName(FILE*fp); /*把占多个目录项的长文件名合起来,显示出长文件名全名*/
CHS RetCHS(int byteVal1,int byteVal2,int byteVal3); /*返回起始终止扇区物理地址*/
DINFO RetDiskData(FILE *fp); /*返回驱动器基本信息*/
void DisDiskInfo(DINFO diskInfo); /*显示分析的驱动器基本信息*/
long RetFDTLBA(FILE *fp); /*计算FDT的逻辑首地址*/
CHS LBAToCHS(long LBA); /*逻辑地址专为CHS地址*/
void SaveSecData(); /*读取扇区信息保存*/
/*主函数*/
void main()
{
FILE *fpmbr,*fpdbr,*fpfdt;
char ch;
DINFO diskInfo;
fpmbr=fopen("MBRInfo.TXT","wb+"); /*MBR信息*/
fpdbr=fopen("DBRInfo.TXT","wb+"); /*DBR信息*/
fpfdt=fopen("FDTInfo.TXT","wb+"); /*FDT信息*/
SaveSecData(fpmbr,fpdbr,fpfdt);
/*以上注释行是动态获取C盘扇区信息的代码,在tc下替换下三行即可动态分析本机C盘信息*/
diskInfo=RetDiskData(fpmbr); /*读取扇区基本信息*/
while(1)
{
system("cls"); /*清屏函数*/
/*菜单显示*/
printf("\n\nA.Display the sector values of MBR(CHS=0,0,1)\n");
printf("B.Display the sector values of DBR(CHS=0,1,1)\n");
printf("C.Display the sector values of FDT\n");
printf("D.Display the basic information of driver C\n");
printf("E.Display the root directory information of driver C\n");
printf("F.Display the long name \n");
printf("Q.Exit the program!\n");
printf("-----------------------------------------------------------------------------------------\n");
printf("Please choose one option:");
scanf("%c",&ch);
if (ch=='a'||ch=='A') /*显示主引导记录所在扇区信息*/
DisSecInfo(fpmbr,SECBYTE);
else if(ch=='B'||ch=='b') /*显示BPB所在扇区数据*/
DisSecInfo(fpdbr,SECBYTE);
else if(ch=='C'||ch=='c') /*显示FDT扇区数据*/
DisSecInfo(fpfdt,SECBYTE*SECTOTAL);
else if (ch=='D'||ch=='d') /*显示C盘的基本属性*/
DisDiskInfo(diskInfo);
else if(ch=='E'||ch=='e') /*显示C盘根目录各文件(夹)属性*/
AnalyzeFDT(fpfdt);
else if(ch=='F'||ch=='f') /*显示长文件名*/
CombLongName(fpfdt);
else if (ch=='Q'||ch=='q') /*退出程序*/
{
fclose(fpmbr);
fclose(fpdbr);
fclose(fpfdt);
exit(0);
}
else if(ch==0x0a||ch==0x0d) /*回车或换行不处理*/
;
else /*输入其他字符提示出错*/
{
printf("Input Error. Please input again!");
getch();
}
}
}
/*返回一个字节的底4位*/
int RetByteLow(int byteVal)
{
return (byteVal&0x0f); /*位与运算(对应的两位中有一个为0则结果为0)*/
}
/*返回一个字节的高四位*/
int RetByteHigh(int byteVal)
{
return ((byteVal>>4)&0x0f);
}
/*将数组代表的数字转换成十进制(长度为len的Arr是r进制)*/
long DataConversion(int arr[],int len,int r)
{
int i=0,j=0;
long expt=0; /*记录权位大小*/
long retVal=0; /*返回十进制值*/
for (i=0;i<len;i++)
{
expt=arr[i];
for (j=len-1;j>i;j--) /*计算权位*/
expt=expt*r;
retVal=retVal+expt;
}
return retVal;
}
/*转换成二进制*/
ARR ValToBin(int value,int len)
{
ARR arrBin; /*记录二进制位*/
int i=0,val=value;
for (i=0;i<len;i++) /*除2取余*/
{
arrBin.arr[i]=val%2;
val=val/2;
}
return arrBin;
}
/*显示文件属性*/
void PrintProperty(int fProperty)
{
ARR arrBin;
arrBin=ValToBin(fProperty,8); /*把表示文件属性字节数值转为二进制,每一位都代表一个属性*/
if(arrBin.arr[5]) /*第6位为1表示归档文件*/
printf("A,");
if(arrBin.arr[4])
printf("sub,");
if(arrBin.arr[3])
printf("V,");
if(arrBin.arr[2])
printf("S,");
if(arrBin.arr[1])
printf("H,");
if(arrBin.arr[0])
printf("R,");
printf("\n");
}
/*判断FDT代表是否是文件夹*/
int IsFolder(int fProperty)
{
ARR arrBin=ValToBin(fProperty,8); /*把表示文件属性字节数值转为二进制*/
return arrBin.arr[4]; /*第5位(arr[4])如果是1表示是文件夹*/
}
/*计算文件的起始地址簇号*/
long StartAdd(FDT fdtInfo)
{
int sizeVal[4]={0}; /*扇区信息用两个字节表示文件起始*/
int i=0,j=0;
long stAdd=0;
for (i=0,j=3;i<2;i++)
{
sizeVal[j]=RetByteLow(fdtInfo.startAdd[i]);
sizeVal[j-1]=RetByteHigh(fdtInfo.startAdd[i]);
j=j-2;
}
stAdd=DataConversion(sizeVal,4,16); /*数组表示的数字转换为十进制*/
return stAdd;
}
/*把两个字节的数据转换成二进制,计算日期和时间*/
DARR BytesToBin(int byteVal[])
{
int i=0,val=byteVal[1];
DARR dbyte; /*记录返回的16位二进制*/
for (i=7;i>=0;i--) /*switch to bin*/
{
dbyte.arr[i]=val%2;
val=val/2;
}
val=byteVal[0];
for (i=15;i>=8;i--) /*switch to bin*/
{
dbyte.arr[i]=val%2;
val=val/2;
}
return dbyte;
}
/*返回文件或文件夹创建或更新的时间*/
TIME RetCraeteTime(FDT fdtInfo)
{
int hour[5],min[6],sec[5];
int i=0,j=0;
int timeArr[2]={0};
TIME cTime;
DARR dByte;
for(i=0;i<2;i++)
timeArr[i]=fdtInfo.createTime[i]; /*必须把表示文件更新时间的两个字节存放在临时变量里*/
dByte=BytesToBin(timeArr); /*参数如果直接传fdtInfo.createTime会发生错误*/
for (i=0;i<5;i++) /*小时占5位*/
{
hour[i]=dByte.arr[i];
cTime.hour=(short)DataConversion(hour,5,2);
}
for (i=5,j=0;i<11;i++,j++) /*分钟占6位*/
{
min[j]=dByte.arr[i];
cTime.min=(short)DataConversion(min,6,2);
}
for (i=11,j=0;i<16;i++,j++) /*秒占5位,以2为增量的二进制*/
{
sec[j]=dByte.arr[i];
cTime.sec=(short)DataConversion(sec,5,2)*2;
}
return cTime;
}
/*返回文件或文件夹创建和更新的日期*/
DATE RetCreateDate(FDT fdtInfo)
{
int year[7],mon[4],day[5];
int i=0,j=0;
int dateArr[2];
DATE cData;
DARR dByte;
for(i=0;i<2;i++)
dateArr[i]=fdtInfo.createDate[i]; /*必须把表示文件更新时间的两个字节存放在临时变量里*/
dByte=BytesToBin(dateArr); /*参数如果直接传fdtInfo.createDate会发生错误*/
for (i=0;i<7;i++) /*年占7位,(7位转十进制+1980即为年份)*/
{
year[i]=dByte.arr[i];
cData.year=(short)DataConversion(year,7,2);
}
for (i=7,j=0;i<11;i++,j++) /*月份占7位*/
{
mon[j]=dByte.arr[i];
cData.mon=(short)DataConversion(mon,4,2);
}
for (i=11,j=0;i<16;i++,j++) /*具体哪天占5位*/
{
day[j]=dByte.arr[i];
cData.day=(short)DataConversion(day,5,2);
}
return cData;
}
/*从文件目录表返回长度为32个字节的文件目录项*/
FDT RetCatalog(int catalog,FILE*fp)
{
int i=0,j=0,count=0;
int cat[CATTOTAL][CATLEN]; /*总共的文件目录项*/
FDT fdtInfo; /*记录文件目录项各字节代表的内容*/
for (i=0;i<CATTOTAL;i++)
for (j=0;j<CATLEN;j++) /*一个文件目录项占32B*/
cat[i][j]=fgetc(fp);
fdtInfo.isEOF=0;
for (j=0,count=0;j<CATLEN;j++,count++) /*搜索一个文件目录项*/
{
if (j<=7)
fdtInfo.fName[count]=cat[catalog][j]; /*前7字节是文件名*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -