关于分析FAT12/16/32文件系统的实验(2)

来源:互联网 发布:暴风影音mac 加载字幕 编辑:程序博客网 时间:2024/05/17 02:50

 

这节将会让我看到期待已经的效果,即读取根目录下的目录和文件,在fat16文件系统下,根目录是一个特殊的扇区,但是fat32则是普通的数据簇的第一个扇区,这是他们的区别之一。

由于我对FAT32文件系统详细说明的白皮书领悟的尚不是太深,对于长文件名的读取,还有没完全领会,所以程序能够解析短文件名目录和文件,而且对部分区域还是有些影响。

因此下面这个程序是不完整,不严谨的程序,大家拿来仅供对白皮书的学习,因为下面的算法是没有在白皮书中提及的。

如何从得到的一个启动目录扇区的号这一个数得到CHS这三个参数呢??其实这个问题我也被难住了许久,下面就是他们的计算的方法:

   FirstRootDirSecNum=bpb.BPB_RsvdSecCnt + (bpb.BPB_NumFATs * bpb.BPB_FATSz16);
   AbsSecNum=FirstRootDirSecNum+bpb.BPB_HiddSec;
   sec=AbsSecNum % bpb.BPB_SecPerTrk + 1;
   header=(AbsSecNum / bpb.BPB_SecPerTrk) % bpb.BPB_NumHeads;
   cyl=(AbsSecNum / bpb.BPB_SecPerTrk) / bpb.BPB_NumHeads;

当取得这个扇区的内容后,我们便利用

/***** FAT Directory Structure ******/
struct FAT_RootDIR
{
UINT8 DIR_Name[11];
UINT8 DIR_Attr;
UINT8 DIR_NTRes;
UINT8 DIR_CrtTimeTeenth;
UINT16 DIR_CrtTime;
UINT16 DIR_CrtDate;
UINT16 DIR_LastAccDate;
UINT16 DIR_FstClusHI;
UINT16 DIR_WrtTime;
UINT16 DIR_WrtDate;
UINT16 DIR_FstClusL0;
UINT32 DIR_FileSize;
};

这个32字节长数据结构来分析,并且该结构的 DIR_Name[0]是一个重要的判断标志。

最后强调,本程序不需要CCDOS支持,但是这是不严谨的版本,仅供探讨学习,后面会有更优化的版本。

 

/*
This programme will read the Directory of the Root
        Writen by Lunzi QingFeng Studio 2008/01/07
        E-mail:Dragon123321@hotmail.com QQ:123685049
*/

#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <mem.h>

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long

struct BPB_FAT16
{
        UINT8 BS_drvNum;
        UINT8 BS_Reserved1;
        UINT8 BS_BootSig;
        UINT16 BS_VolID[2];
UINT8 BS_VolLab[11];
UINT8 BS_FileSysType[8];
};

struct BPB_FAT32
{
        UINT32 BPB_FATSz32;
        UINT16 BPB_ExtFlags;
        UINT16 BPB_FSVer;
        UINT32 BPB_RootClus;
        UINT16 BPB_FSInfo;
        UINT16 BPB_BkBootSec;
        UINT8 BPB_Reserved[12];
        UINT8 BS_DrvNum;
        UINT8 BS_Reserved1;
        UINT8 BS_BootSig;
        UINT16 BS_VolID[2];
UINT8 BS_FilSysType[19];
};

struct BPB_Info
{
UINT8 BS_jmpBoot[3];
UINT8 BS_OEMName[8];
        UINT16 BPB_BytsPerSec;
        UINT8 BPB_SecPerClus;
        UINT16 BPB_RsvdSecCnt;
        UINT8 BPB_NumFATs;
        UINT16 BPB_RootEntCnt;
        UINT16 BPB_TotSec16;
        UINT8 BPB_Media;
        UINT16 BPB_FATSz16;
        UINT16 BPB_SecPerTrk;
        UINT16 BPB_NumHeads;
        UINT32 BPB_HiddSec;
        UINT32 BPB_TotSec32;
union BPB_FATs
        {
   struct BPB_FAT16 FAT16;
   struct BPB_FAT32 FAT32;
} BPB_FAT;
};

/***** FAT Directory Structure ******/
struct FAT_RootDIR
{
UINT8 DIR_Name[11];
UINT8 DIR_Attr;
UINT8 DIR_NTRes;
UINT8 DIR_CrtTimeTeenth;
UINT16 DIR_CrtTime;
UINT16 DIR_CrtDate;
UINT16 DIR_LastAccDate;
UINT16 DIR_FstClusHI;
UINT16 DIR_WrtTime;
UINT16 DIR_WrtDate;
UINT16 DIR_FstClusL0;
UINT32 DIR_FileSize;
};


void readSector(int cyl,int header,int sec,UINT8 buff[]);
void showSector(UINT8 buff[]);
int writeToFile(UINT8 buff[]);

void readSector(int cyl,int header,int sec,UINT8 buff[])
{
union REGS inr,outr;

        inr.h.ah=0x02;           /*NO 2. fuction*/
        inr.h.al=0x01;           /*the number of sectors wanted read*/
        inr.x.bx=buff;           /*save back buffer address ES:BX */
        inr.h.ch=cyl;            /*Num of cylder*/
inr.h.cl=sec;            /*Num of sector*/
inr.h.dh=header;         /*Num of header*/
        inr.h.dl=0x80;           /*Num of destnition disk*/
int86(0x13,&inr,&outr);
}

void showSector(UINT8 buff[])
{
        int i;

for(i=0;i<512;i++){
                if(i%24==0){
    printf("/n");
    printf("%4x : ",i);
   }

                printf("%2x ",buff[i]);
}
}


int writeToFile(UINT8 buff[])
{
        FILE *fp;
        int i;

if((fp=fopen("C://MyPro//DiskSec.bin","wab"))==NULL)
        {
   printf("Error:Could not create or open the log file ./n");
                fclose(fp);
                return(0);
        }

for(i=0;i<512;i++){
                fputc(buff[i],fp);
}

        fclose(fp);
        return(1);

}

/*************Main FUNCTION*************/
int main(int argc,char *argv[])
{
        UINT8 ASector[512];
int cyl,sec,header;
int key_Input;
        /*DBR*/
struct BPB_Info bpb;
char * ptr;
int c;
/*FAT*/
        UINT16 RootDirSectors;
        UINT16 FirstDataSector;
        UINT16 FirstSectorofCluster;
UINT16 FATSz;
/*FAT ROOT DIR*/
        UINT16 FirstRootDirSecNum;
struct FAT_RootDIR frd;
UINT32 AbsSecNum;
        UINT8 DirFlag=0xFF;
int t=0;
/*
if(argc <= 3 ){
   printf("This Programme need three parameters:Cylder Header Sector /n");
   exit(1);
}

cyl=atoi(argv[1]);
header=atoi(argv[2]);
sec=atoi(argv[3]);

        readSector(cyl,header,sec,ASector);

        showSector(ASector);

printf("/nWrite the content to a log file press Y others for exit !/n");
key_Input=getch();
if(key_Input=='y' || key_Input=='Y')
{
                if(writeToFile(ASector)==1) printf("Successfully write into the log file !");
    else printf("Failed write into the log file!");
}

size=62
printf("%d ",sizeof(bpb));
*/
readSector(0,1,1,ASector);

        ptr=memcpy(&bpb,&ASector[0],sizeof(bpb));
if(ptr)
{
   RootDirSectors=((bpb.BPB_RootEntCnt*32)+(bpb.BPB_BytsPerSec))/bpb.BPB_BytsPerSec;

   if(bpb.BPB_FATSz16!=0)
    FATSz=bpb.BPB_FATSz16;
   else
   {
                        /*FATSz=bpb.BPB_FATSz32;*/
    printf("ERROR:Your FS isn't FAT16,Please change this programme./n");
    exit(0);
   }
   FirstDataSector=bpb.BPB_RsvdSecCnt+(bpb.BPB_NumFATs * FATSz) + RootDirSectors;

   FirstRootDirSecNum=bpb.BPB_RsvdSecCnt + (bpb.BPB_NumFATs * bpb.BPB_FATSz16);
   AbsSecNum=FirstRootDirSecNum+bpb.BPB_HiddSec;
   sec=AbsSecNum % bpb.BPB_SecPerTrk + 1;
   header=(AbsSecNum / bpb.BPB_SecPerTrk) % bpb.BPB_NumHeads;
   cyl=(AbsSecNum / bpb.BPB_SecPerTrk) / bpb.BPB_NumHeads;

   readSector(cyl,header,sec,ASector);

                /*Show volume label*/
   printf("/n Volume Label is : ");
   for(c=0;c<11;c++) printf("%c",bpb.BPB_FAT.FAT16.BS_VolLab[c]);
   printf("/n Volume Serial Number is : %4x-%4x",bpb.BPB_FAT.FAT16.BS_VolID[1],bpb.BPB_FAT.FAT16.BS_VolID[0]);
   printf("/n Directory Of The Root :");
   printf("/n/n");

                while(DirFlag!=0)
   {
    ptr=memcpy(&frd,&ASector[t],sizeof(frd));
    t=t+32;
    if(ptr)
    {
     DirFlag=frd.DIR_Name[0];

                                if(DirFlag==0xE5)
     {
      printf("This root directory is empty. /n");
      break;
     }

     if((DirFlag!='A')&&(DirFlag!=0xE5)&&(DirFlag!=0))
                                {
                                        if(DirFlag==0X05) printf("%c",0xE5);
                                                else printf("%c",DirFlag);

                                        for(c=1;c<8;c++)
      {
            if(frd.DIR_Name[c]!=0x20) printf("%c",frd.DIR_Name[c]);
      }
                                        printf(".");
      for(c=8;c<11;c++) printf("%c",frd.DIR_Name[c]);

      /*File attributions is follow:*/
      printf("/t/t%u",frd.DIR_FileSize);
                                }

     if(DirFlag=='A')
                                {
      memcpy(&frd,&ASector[t],sizeof(frd));
      t=t+32;
      for(c=0;c<11;c++)       printf("%c",frd.DIR_Name[c]);
      printf("/t<DIR>");
                                        /*Directory attributions is follow:*/
                                }
    }
    else
    {
     printf("Can't copy the DBR to the memory!/n");
    }
    printf("/n");
   }

}
else
{
   printf("Can't copy the DBR to the memory!/n");
}


return (0);
}

大家看windows.0 486C.0 这两个目录以上读取是正确的,但是下面的就有些现实不正常。我也正在学习改正。。如果有前辈希望能指出其中的纰漏,在此先行谢过。。。

 

 

这是稍微正式版的读取第一个磁盘分区的根目录的程序代码,已经隐藏了卷标文件,并且能够显示 所有文件/目录名.

另外,SUPER486对U盘的读操作已经取得突破性进展...继续努力ing ...

/*
This programme will read the Directory of the Root
Writen by Lunzi QingFeng Studio 2008/03/03
        E-mail:Dragon123321@hotmail.com QQ:123685049
*/

#include <stdio.h>
#include <string.h>
#include <dos.h>
#include <mem.h>

#define UINT8 unsigned char
#define UINT16 unsigned short
#define UINT32 unsigned long

#define ATTR_READ_ONLY 0X01
#define ATTR_HIDDEN 0X02
#define ATTR_SYSTEM 0X04
#define ATTR_VOLUME_ID 0X08
#define ATTR_DIRECTORY 0X10
#define ATTR_ARCHIVE 0X20
#define ATTR_LONG_NAME ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID

typedef struct BPB_FAT16
{
        UINT8 BS_drvNum;
        UINT8 BS_Reserved1;
        UINT8 BS_BootSig;
        UINT16 BS_VolID[2];
UINT8 BS_VolLab[11];
UINT8 BS_FileSysType[8];
};

typedef struct BPB_FAT32
{
        UINT32 BPB_FATSz32;
        UINT16 BPB_ExtFlags;
        UINT16 BPB_FSVer;
        UINT32 BPB_RootClus;
        UINT16 BPB_FSInfo;
        UINT16 BPB_BkBootSec;
        UINT8 BPB_Reserved[12];
        UINT8 BS_DrvNum;
        UINT8 BS_Reserved1;
        UINT8 BS_BootSig;
        UINT16 BS_VolID[2];
UINT8 BS_FilSysType[19];
};

typedef struct BPB_Info
{
UINT8 BS_jmpBoot[3];
UINT8 BS_OEMName[8];
        UINT16 BPB_BytsPerSec;
        UINT8 BPB_SecPerClus;
        UINT16 BPB_RsvdSecCnt;
        UINT8 BPB_NumFATs;
        UINT16 BPB_RootEntCnt;
        UINT16 BPB_TotSec16;
        UINT8 BPB_Media;
        UINT16 BPB_FATSz16;
        UINT16 BPB_SecPerTrk;
        UINT16 BPB_NumHeads;
        UINT32 BPB_HiddSec;
        UINT32 BPB_TotSec32;
union BPB_FATs
        {
   struct BPB_FAT16 FAT16;
   struct BPB_FAT32 FAT32;
} BPB_FAT;
};

/***** FAT Directory Structure ******/
typedef struct FAT_RootDIR
{
UINT8 DIR_Name[11];
UINT8 DIR_Attr;
UINT8 DIR_NTRes;
UINT8 DIR_CrtTimeTeenth;
UINT16 DIR_CrtTime;
UINT16 DIR_CrtDate;
UINT16 DIR_LastAccDate;
UINT16 DIR_FstClusHI;
UINT16 DIR_WrtTime;
UINT16 DIR_WrtDate;
UINT16 DIR_FstClusL0;
UINT32 DIR_FileSize;
};


void readSector(int cyl,int header,int sec,UINT8 buff[]);
void showSector(UINT8 buff[]);
int writeToFile(UINT8 buff[]);

void readSector(int cyl,int header,int sec,UINT8 buff[])
{
union REGS inr,outr;

        inr.h.ah=0x02;           /*NO 2. fuction*/
        inr.h.al=0x01;           /*the number of sectors wanted read*/
        inr.x.bx=buff;           /*save back buffer address ES:BX */
        inr.h.ch=cyl;            /*Num of cylder*/
inr.h.cl=sec;            /*Num of sector*/
inr.h.dh=header;         /*Num of header*/
        inr.h.dl=0x80;           /*Num of destnition disk*/
int86(0x13,&inr,&outr);
}

void showSector(UINT8 buff[])
{
        int i;

for(i=0;i<512;i++){
                if(i%24==0){
    printf("/n");
    printf("%4x : ",i);
   }

                printf("%2x ",buff[i]);
}
}


int writeToFile(UINT8 buff[])
{
        FILE *fp;
        int i;

if((fp=fopen("C://MyPro//DiskSec.bin","wab"))==NULL)
        {
   printf("Error:Could not create or open the log file ./n");
                fclose(fp);
                return(0);
        }

for(i=0;i<512;i++){
                fputc(buff[i],fp);
}

        fclose(fp);
        return(1);

}

/*************Main FUNCTION*************/
int main(int argc,char *argv[])
{
        UINT8 ASector[512];
int cyl,sec,header;
int key_Input;
        /*DBR*/
struct BPB_Info bpb;
char * ptr;
int c;
/*FAT*/
        UINT16 RootDirSectors;
        UINT16 FirstDataSector;
        UINT16 FirstSectorofCluster;
UINT16 FATSz;
/*FAT ROOT DIR*/
        UINT16 FirstRootDirSecNum;
struct FAT_RootDIR frd;
UINT32 AbsSecNum;
        UINT8 DirFlag=0xFF;
int t=0;
/*
if(argc <= 3 ){
   printf("This Programme need three parameters:Cylder Header Sector /n");
   exit(1);
}

cyl=atoi(argv[1]);
header=atoi(argv[2]);
sec=atoi(argv[3]);

        readSector(cyl,header,sec,ASector);

        showSector(ASector);

printf("/nWrite the content to a log file press Y others for exit !/n");
key_Input=getch();
if(key_Input=='y' || key_Input=='Y')
{
                if(writeToFile(ASector)==1) printf("Successfully write into the log file !");
    else printf("Failed write into the log file!");
}

size=62
printf("%d ",sizeof(bpb));
*/
readSector(0,1,1,ASector);

        ptr=memcpy(&bpb,&ASector[0],sizeof(bpb));
if(ptr)
{
   RootDirSectors=((bpb.BPB_RootEntCnt*32)+(bpb.BPB_BytsPerSec))/bpb.BPB_BytsPerSec;

   if(bpb.BPB_FATSz16!=0)
    FATSz=bpb.BPB_FATSz16;
   else
   {
                        /*FATSz=bpb.BPB_FATSz32;*/
    printf("ERROR:Your FS isn't FAT16,Please change this programme./n");
    exit(0);
   }
   FirstDataSector=bpb.BPB_RsvdSecCnt+(bpb.BPB_NumFATs * FATSz) + RootDirSectors;

   FirstRootDirSecNum=bpb.BPB_RsvdSecCnt + (bpb.BPB_NumFATs * bpb.BPB_FATSz16);
   AbsSecNum=FirstRootDirSecNum+bpb.BPB_HiddSec;
   sec=AbsSecNum % bpb.BPB_SecPerTrk + 1;
   header=(AbsSecNum / bpb.BPB_SecPerTrk) % bpb.BPB_NumHeads;
   cyl=(AbsSecNum / bpb.BPB_SecPerTrk) / bpb.BPB_NumHeads;

   readSector(cyl,header,sec,ASector);

                /*Show volume label*/
   printf("/n Volume Label is : ");
   for(c=0;c<11;c++) printf("%c",bpb.BPB_FAT.FAT16.BS_VolLab[c]);
   printf("/n Volume Serial Number is : %4x-%4x",bpb.BPB_FAT.FAT16.BS_VolID[1],bpb.BPB_FAT.FAT16.BS_VolID[0]);
   printf("/n Directory Of The Root :");
   printf("/n/n");

   ptr=memcpy(&frd,&ASector[t],sizeof(frd));
   t=t+32;
   DirFlag=frd.DIR_Name[0];

   while(DirFlag!=0x0)
   {
    if(ptr)
    {
     if(DirFlag==0xE5)
     {
      /*printf("This is a empty directory and have no directory below. /n");*/
      break;
     }

                                /***** Judge the file is a directory or a file *****/

     if(((frd.DIR_Attr & ATTR_DIRECTORY)==ATTR_DIRECTORY)||(frd.DIR_Attr==0x0f))
                                {
      if(frd.DIR_Attr==0x0f)
      {
       memcpy(&frd,&ASector[t],sizeof(frd));
       t=t+32;
                                         }
      for(c=0;c<11;c++)       printf("%c",frd.DIR_Name[c]);
                                        printf("/t<DIR>");
      /*Directory attributions is follow:*/
      printf("/n");
                                }
     else if((frd.DIR_Attr & ATTR_VOLUME_ID)!=ATTR_VOLUME_ID)
                                {
                                        if(DirFlag==0X05) printf("%c",0xE5);
                                                else printf("%c",DirFlag);

      for(c=1;c<8;c++) printf("%c",frd.DIR_Name[c]);
      printf(" ");
      for(c=8;c<11;c++) printf("%c",frd.DIR_Name[c]);

      /*File attributions is follow:*/
      printf("/t/t%u",frd.DIR_FileSize);
      printf("/t%d-%d-%d",(((frd.DIR_WrtDate&0xff00)>>8)),((frd.DIR_WrtDate&0x00f0)>>4),(frd.DIR_WrtDate&0x000f));
      printf("/t%4x",frd.DIR_WrtDate);
      printf("/n");
                                }


     /***** FAT16<128k/FAT12<6K/FAT32 IS NOT FIXED LENGTH *****/

     if(t<512)
     {
      memcpy(&frd,&ASector[t],sizeof(frd));
      t=t+32;
                                        DirFlag=frd.DIR_Name[0];
                                 }
                                 else
                                 {
                                        sec++;
                                        readSector(cyl,header,sec,ASector);
      memcpy(&frd,&ASector[0],sizeof(frd));
      t=32;
      DirFlag=frd.DIR_Name[0];
                                 }

    }
    else
    {
     printf("Can't copy the DBR to the memory!/n");
     exit(0);
    }
   }

}
else
{
   printf("Can't copy the DBR to the memory!/n");
   exit(0);
}


return (0);
}