2008. 10. 3. 17:36

[File System] FAT에 대한 예제코드

 3장 실습 소스 < FAT_exam1.c >

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

 

#define U8 unsigned char
#define S8 char
#define U16 unsigned short
#define U32 unsigned int
#define U64 unsigned __int64

 

#pragma pack(1)
typedef struct _FAT16_BPB_struct{
 U8  JmpBoot[3];
 U8  OEMName[8];
 U16  BytsPerSec;
 U8  SecPerClus;
 U16  RsvdSecCnt;
 U8  NumFATs;
 U16  RootEntCnt;
 U16  TotSec16;
 U8  Media;
 U16  FATs16;
 U16  SecPerTrk;
 U16  NumHeads;
 U32  HiddSec;
 U32  TotSec32;
 //-----공통영역------
 U8  DriveNumber;
 U8  Reserved1;
 U8  BootSignal;
 U32  VolumeID;
 U8  VolumeLabel[11];
 U8  FilSysType[8];
 //------FAT16영역

 U8  BootCodeArea[448];
 U16  Signature;
}FAT16_BPB;

 

#pragma pack()

 

typedef struct _VOL_struct{
 U32  Drive;
 U32  VolBeginSec;
 U32  FirstDataSec;
 U32  RootDirSec;
 U32  RootEntCnt; 
 U32  RootDirSecCnt;
 U32  FATSize;
 U32  FATStartSec;
 U32  TotalClusCnt;
 U32  TotalSec;
 U32  DataSecSize;
 U32  ClusterSize;
 U32  SecPerClus;
}VolStruct;


U32 HDD_read(U8 drv, U32 SecAddr, U32 blocks, U8* buf);
U32 get_BPB_info(FAT16_BPB* BPB, VolStruct* pVol);

VolStruct gVol;

 

int main(void)
{

 char buf[512];

 gVol.Drive = 0x4;
 gVol.VolBeginSec = 0x00;
// memset( buf, 0, 512 );

// HDD_write( gVol.Drive, gVol.VolBeginSec, 1, (unsigned char *)buf);

 

 if( HDD_read(gVol.Drive, gVol.VolBeginSec, 1 ,(unsigned char *)buf ) == 0 )
 {
  printf("Boot Sector Read Failed \n");
  return 1;
 }

 if( get_BPB_info((FAT16_BPB*)buf, &gVol) == 0 )
 {
  printf("It is not FAT16 file System \n");
  return 1;
 }

 

 printf("  ------------- volume infomation -------------- \n\n");

 printf("  Total Sector             = %d sectors \n", gVol.TotalSec);
 printf("  FAT size                 = %d sectors \n", gVol.FATSize);
 printf("  Root Dir Sector          = %d         \n", gVol.RootDirSec);
 printf("  Root Dor Sector Count    = %d         \n", gVol.RootDirSecCnt);
 printf("  First Data Sector        = %d         \n", gVol.FirstDataSec);
 printf("  Data Sector Count        = %d Sectors \n", gVol.DataSecSize);
 printf("  Total Cluster            = %d         \n", gVol.TotalClusCnt);
 printf("  Size of Cluster          = %d         \n", gVol.ClusterSize);
 system("pause");
 return 0;
}

 

U32 get_BPB_info(FAT16_BPB* BPB, VolStruct* pVol)
{
 if(BPB->RootEntCnt == 0 || BPB->Signature != 0xAA55)
 {
  return 0;
 }

 //Get Total Sector
 if( BPB->TotSec16 != 0 )
 {
  pVol->TotalSec = BPB->TotSec16;
 }
 else
 {
  pVol->TotalSec = BPB->TotSec32;
 }

 //Get FAT Size
 pVol->FATSize = BPB->FATs16;

 //Get FAT Start Sector
 pVol->FATStartSec = pVol->VolBeginSec + BPB->RsvdSecCnt;

 //Get Root Dir Entry Count
 pVol->RootEntCnt = BPB->RootEntCnt;

 //Get Root Dir Sector
 pVol->RootDirSec = pVol->VolBeginSec + BPB->RsvdSecCnt + (BPB->NumFATs * BPB->FATs16);

 //Get Root Dir Sector Count
 pVol->RootDirSecCnt = (( BPB->RootEntCnt * 32) + (BPB->BytsPerSec - 1)) / BPB->BytsPerSec;

 //Get Data Start Sector
 pVol->FirstDataSec = pVol->VolBeginSec + BPB->RsvdSecCnt +( BPB->NumFATs * pVol->FATSize ) + pVol->RootDirSecCnt;

 //Get Size of Data Area
 pVol->DataSecSize = pVol->TotalSec - ( BPB->RsvdSecCnt + ( BPB->NumFATs * pVol->FATSize ) + pVol->RootDirSecCnt );

 //Get Total Cluster Count
 pVol->TotalClusCnt = pVol->DataSecSize / BPB->SecPerClus;

 //Get Size of Cluster
 pVol->ClusterSize = BPB->SecPerClus * BPB->BytsPerSec;

 //Get Sector Per Cluster
 pVol->SecPerClus = BPB->SecPerClus;

 return 1;
}

 

U32 HDD_read(U8 drv, U32 SecAddr, U32 blocks, U8* buf)
{
 U32 ret = 0;
 U32 ldistanceLow, ldistanceHigh, dwpointer, bytestoread, numread;

 char cur_drv[100];
 HANDLE g_hDevice;

 sprintf(cur_drv, "\\\\.\\PhysicalDrive%d",(U32)drv);
 g_hDevice = CreateFile(cur_drv, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

 if(g_hDevice == INVALID_HANDLE_VALUE) return 0;

 ldistanceLow = SecAddr << 9;
 ldistanceHigh = SecAddr >> (32 - 9);
 dwpointer = SetFilePointer(g_hDevice, ldistanceLow, (long *)&ldistanceHigh, FILE_BEGIN);

 if(dwpointer != 0xFFFFFFFF)
 {
  bytestoread = blocks * 512;
  ret = ReadFile(g_hDevice, buf, bytestoread, (unsigned long*)&numread, NULL);
  if(ret) ret = 1;
  else ret = 0;
 }

 CloseHandle(g_hDevice);
 return ret;
}

 

 < FAT_exam2.c >

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

#define U8 unsigned char
#define S8 char
#define U16 unsigned short
#define U32 unsigned int
#define U64 unsigned __int64
 
 #pragma pack(1)
typedef struct _FAT16_BPB_struct{
 U8  JmpBoot[3];
 U8  OEMName[8];
 U16  BytsPerSec;
 U8  SecPerClus;
 U16  RsvdSecCnt;
 U8  NumFATs;
 U16  RootEntCnt;
 U16  TotSec16;
 U8  Media;
 U16  FATs16;
 U16  SecPerTrk;
 U16  NumHeads;
 U32  HiddSec;
 U32  TotSec32;
 //-----공통영역------
 U8  DriveNumber;
 U8  Reserved1;
 U8  BootSignal;
 U32  VolumeID;
 U8  VolumeLabel[11];
 U8  FilSysType[8];
 //------FAT16영역

 U8  BootCodeArea[448];
 
 U16  Signature;
}FAT16_BPB;

typedef struct _VOL_struct{
 U32  Drive;
 U32  VolBeginSec;
 U32  FirstDataSec;
 U32  RootDirSec;
 U32  RootEntCnt; 
 U32  RootDirSecCnt;
 U32  FATSize;
 U32  FATStartSec;
 U32  TotalClusCnt;
 U32  TotalSec;
 U32  DataSecSize;
 U32  ClusterSize;
 U32  SecPerClus;
}VolStruct;

 typedef struct _DIR_struct{
  U8  Name[11];
  U8  Attr;
  U8  NTRes;
  U8  CrtTimeTenth;
  U16  CrtTime;
  U16  CrtDate;
  U16  LstAccDate;
  U16  FstClusHi;
  U16  WriteTime;
  U16  WriteDate;
  U16  FstClusLow;
  U32  FileSize;
 }DirEntry;
 #pragma pack()
 
 #pragma pack(1)
 typedef struct _LONG_DIR_struct{
  U8  Order;
  U8  Name1[10];
  U8  Attr;
  U8  Type;
  U8  chksum;
  U8  Name2[12];
  U16  FstClusLo;
  U8  Name3[4]; 
 }LongDirEntry;
 #pragma pack()
 
 void print_longName(LongDirEntry* pLongDir, U32 EntryNum);
 U32  show_dir (DirEntry* pDir);
 U32  get_BPB_info(FAT16_BPB* BPB, VolStruct* pVol);
 U32  HDD_read (U8 drv, U32 SecAddr, U32 blocks, U8* buf);
 
 VolStruct gVol;
 
 int main(void) {
  U8      buf[512];
  U8*      pRootBuf;
 
  gVol.Drive  = 0x4;
  gVol.VolBeginSec = 0x0; 
 
  if( HDD_read(gVol.Drive, gVol.VolBeginSec, 1, buf) == 0 ){
   printf("Boot Sector Read Failed \n");
   return 1;
  }
 
  if (get_BPB_info((FAT16_BPB*)buf, &gVol) == 0){
   printf("It is not FAT16 File System \n");
   return 1;
  } 
   
  pRootBuf = (U8*)malloc( gVol.RootDirSecCnt * 512);
  
  if( HDD_read(gVol.Drive, gVol.RootDirSec, gVol.RootDirSecCnt, pRootBuf) == 0 ){
   printf("Root Dir Read Failed \n");
   return 1;
  }
 
  show_dir((DirEntry*)pRootBuf); 
 system("pause");
  return 0;
 }
 
 U32 show_dir(DirEntry* pDir) { 
  U32 i, y, LongEntryEn=0;  
  
  for(i=0; i<=gVol.RootEntCnt; i++)
  { 
   switch( (U8) pDir[i].Name[0]){
    case 0x00: return 1; // End of Entry
    case 0xE5: continue;
   }
   
   if(pDir[i].Attr == 0x0F){
    LongEntryEn = 1;       //Long File Name Entry
    continue;
   }
   
   printf("---------Entry Number %d ------------ \n", i);
 
    if(pDir[i].Attr == 0x10) printf("Directory Name: ");
    else                       printf("File Name: ");
 
   if(LongEntryEn == 1){   // print long file name
    print_longName((LongDirEntry*)pDir, i-1);
    LongEntryEn = 0;
   }else{                     //printf short file name
    for(y=0; y < 11; y++)
     printf("%c",pDir[i].Name[y]);
   }
   printf("\n");
   printf("File Size     : %d \n",pDir[i].FileSize);
   printf("Start Cluster : %d \n",(pDir[i].FstClusLow | pDir[i].FstClusHi << 16) );
  }  
  return 1;
 }
 
 void print_longName(LongDirEntry* pLongDir, U32 EntryNum)
 {
  wchar_t  filename[512];
  char  final[512];
  U32  nameOffset = 0;
  
  do{
   memcpy(&filename[nameOffset],pLongDir[EntryNum].Name1, 10); nameOffset += 5;
   memcpy(&filename[nameOffset],pLongDir[EntryNum].Name2, 12); nameOffset += 6;
   memcpy(&filename[nameOffset],pLongDir[EntryNum].Name3, 4 ); nameOffset += 2;
  }while( (pLongDir[EntryNum--].Order & 0x40) == 0 );
  
  filename[nameOffset] = 0x0000;
 
  wcstombs( final, filename, 512 );    
     printf( "%s", final ); 
 }

 

 U32 HDD_read(U8 drv, U32 SecAddr, U32 blocks, U8* buf)
{
 U32 ret = 0;
 U32 ldistanceLow, ldistanceHigh, dwpointer, bytestoread, numread;

 char cur_drv[100];
 HANDLE g_hDevice;

 sprintf(cur_drv, "\\\\.\\PhysicalDrive%d",(U32)drv);
 g_hDevice = CreateFile(cur_drv, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
         OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

 if(g_hDevice == INVALID_HANDLE_VALUE) return 0;

 ldistanceLow = SecAddr << 9;
 ldistanceHigh = SecAddr >> (32 - 9);
 dwpointer = SetFilePointer(g_hDevice, ldistanceLow, (long *)&ldistanceHigh, FILE_BEGIN);

 if(dwpointer != 0xFFFFFFFF)
 {
  bytestoread = blocks * 512;
  ret = ReadFile(g_hDevice, buf, bytestoread, (unsigned long*)&numread, NULL);
  if(ret) ret = 1;
  else ret = 0;
 }

 CloseHandle(g_hDevice);
 return ret;
}


 U32 get_BPB_info(FAT16_BPB* BPB, VolStruct* pVol)
{
 if(BPB->RootEntCnt == 0 || BPB->Signature != 0xAA55)
 {
  return 0;
 }

 //Get Total Sector
 if( BPB->TotSec16 != 0 )
 {
  pVol->TotalSec = BPB->TotSec16;
 }
 else
 {
  pVol->TotalSec = BPB->TotSec32;
 }

 //Get FAT Size
 pVol->FATSize = BPB->FATs16;

 //Get FAT Start Sector
 pVol->FATStartSec = pVol->VolBeginSec + BPB->RsvdSecCnt;

 //Get Root Dir Entry Count
 pVol->RootEntCnt = BPB->RootEntCnt;

 //Get Root Dir Sector
 pVol->RootDirSec = pVol->VolBeginSec + BPB->RsvdSecCnt + (BPB->NumFATs * BPB->FATs16);

 //Get Root Dir Sector Count
 pVol->RootDirSecCnt = (( BPB->RootEntCnt * 32) + (BPB->BytsPerSec - 1)) / BPB->BytsPerSec;

 //Get Data Start Sector
 pVol->FirstDataSec = pVol->VolBeginSec + BPB->RsvdSecCnt +( BPB->NumFATs * pVol->FATSize ) + pVol->RootDirSecCnt;

 //Get Size of Data Area
 pVol->DataSecSize = pVol->TotalSec - ( BPB->RsvdSecCnt + ( BPB->NumFATs * pVol->FATSize ) + pVol->RootDirSecCnt );

 //Get Total Cluster Count
 pVol->TotalClusCnt = pVol->DataSecSize / BPB->SecPerClus;

 //Get Size of Cluster
 pVol->ClusterSize = BPB->SecPerClus * BPB->BytsPerSec;

 //Get Sector Per Cluster
 pVol->SecPerClus = BPB->SecPerClus;

 return 1;
}