Solved

Reading FAT table

Posted on 2003-10-29
2
1,197 Views
Last Modified: 2012-06-27
Hi,
I'm doing a program which reads the FAT table of a partition and calculates
the amount of free space on that partition.
I read the FAT table of a 1,5Gb partition. The partition is 80% free but I get
with the program that the partition has 5% free space.
I don't know what's wrong interpretating the FAT.

The code is as follows:


/* This function reads the FAT table into memory */
int fatTableRead (Partition *p, FatTable* ft, FatSpecific* fs, int tableNum)
{
      if(ft->rawSize < fs->fatSectors*512)
            return 0;

      memset(ft->table,0,ft->rawSize);

      if(!readFromDisk(p->d,fs->fatOffset+tableNum*fs->fatSectors,
                        fs->fatSectors,(char *) ft->table))
            return 0;


        if ( *((unsigned char*) ft->table) != fs->bootSector.media)
      {
            WRITELOG3(flog,FAT_TABLE_ERRORMSG002,(int) tableNum + 1,
                  (int) *((unsigned char*) ft->table),(int) fs->bootSector.media);
                  return 0;
        }

      ft->clusterCount = fs->clusterCount;

      fatTableCountStats(ft);

      return 1;
}

/* This function counts the number of both free and bad clusters */
int fatTableCountStats(FatTable* ft)
{
      unsigned long i;

      if(ft->clusterCount + 2 > ft->size)
            return 0;

      ft->freeClusterCount = 0;
      ft->badClusterCount = 0;

      for (i=2; i < ft->clusterCount + 2; i++)
      {
            if (fatTableIsAvailable(ft,i))
                  ft->freeClusterCount++;
            else if (fatTableIsBad (ft,i))
                  ft->badClusterCount++;
      }
      return 1;
}

int fatTableIsAvailable(FatTable* ft, unsigned long cluster)
{
      return _testCodeAvailable(ft,fatTableGet(ft,cluster));
}

int fatTableIsBad(FatTable* ft, unsigned long cluster)
{
      return _testCodeBad(ft,fatTableGet(ft,cluster));
}

unsigned long fatTableGet(FatTable* ft, unsigned long cluster)
{
      if (cluster >= ft->clusterCount + 2)
            return 0;

      switch (ft->fatType)
      {
            case FAT_TYPE_FAT16:
                  return ((unsigned short *) ft->table) [cluster];

            case FAT_TYPE_FAT32:
                  return ((unsigned int *) ft->table) [cluster];
            default:
                  return 0;
      }
}

int _testCodeAvailable(FatTable* ft, unsigned long code)
{
      return code == 0;
}

int _testCodeBad(FatTable* ft, unsigned long code)
{
      switch (ft->fatType)
      {
            case FAT_TYPE_FAT12:
                  if(code==0x0FF7) return 1;
                  break;
                  
            case FAT_TYPE_FAT16:
                  if (code == 0xFFF7) return 1;
                  break;
                  
            case FAT_TYPE_FAT32:
                  if (code == 0x0FFFFFF7) return 1;
                  break;
      }
      return 0;
}



/* The structure of the FAT Boot Sector */
struct FatBootSectorStruct
{
      unsigned char      bootJump[3];      /* 00: Boot strap short or near jump */
      unsigned char      systemId[8];      /* 03: system name */
      unsigned short      sectorSize;      /* 0b: bytes per logical sector */
      unsigned char      clusterSize;      /* 0d: sectors/cluster */
      unsigned short      reservedSectors;      /* 0e: reserved sectors */
      unsigned char      numFats;            /* 10: number of FATs */
      unsigned short      dirEntries;      /* 11: number of root directory entries */
      unsigned short      sectors;      /* 13: if 0, total_sect supersedes */
      unsigned char      media;            /* 15: media code */
      unsigned short      fatLength;      /* 16: sectors/FAT for FAT12/16 */
      unsigned short      sectorsTrack;      /* 18: sectors per track */
      unsigned short      heads;            /* 1a: number of heads */
      unsigned long      hiddenSectors;            /* 1c: hidden sectors (partition start) */
      unsigned long      sectorCount;      /* 20: no. of sectors (if sectors == 0) */

      union
      {
            struct /* campos FAT16/12 */
            {
                  unsigned char      driveNum;
                  unsigned char      empty_1;      
                  unsigned char      extSignature;      /* 0x29 */
                  unsigned long      serialNumber;      
                  unsigned char      volumeName [11];      
                  unsigned char      fatName [8];      
                  unsigned char      bootCode[448];      
            } __attribute__ ((packed)) fat16;      
            struct /* campos FAT32 */
            {
                  unsigned long      fatLength;      /* tamaño FAT en sectores */
                  unsigned short      flags;            /* bit 8: fat mirroring, bits 3..0: fat activa */
                  unsigned short      version;        /* minor * 256 + major */
                  unsigned long      rootDirCluster;      
                  unsigned short      infoSector;    
                  unsigned short      backupSector;      
                  unsigned char      empty1 [12];      
                  unsigned short      driveNum;      
                  unsigned char      extSignature;      /* 0x29 */
                  unsigned long      serialNumber;      
                  unsigned char      volumeName [11];      
                  unsigned char      fatName [8];      
                  unsigned char            bootCode[420];      
            } __attribute ((packed)) fat32;
      } u;
      unsigned short      boot_sign;      /* 0xAA55 */
} __attribute__ ((packed));

struct FatTableStruct
{
      void*            table;
      unsigned long      size;
      int            rawSize;

      FatType            fatType;
      unsigned long      clusterCount;
      unsigned long      freeClusterCount;
      unsigned long      badClusterCount;

      unsigned long      lastAlloc;
};

struct _FatSpecific
{
      FatBootSector            bootSector;    /* structure of boot sector */
      FatInfoSector            infoSector;    /* fat32-only information sector */

      int                  logicalSectorSize;      /* illogical sector size  */
      unsigned long long      sectorCount;
      int                  clusterSize;
      unsigned long long      clusterSectors;
      unsigned long            clusterCount;
      int                  dirEntriesPerCluster;

      FatType                  fatType;
      int                  fatTableCount;
      unsigned long long      fatSectors;

      unsigned long            serialNumber;

      unsigned long long      infoSectorOffset;     /* FAT32 only */
      unsigned long long      fatOffset;
      unsigned long long      rootDirOffset;      /* non-FAT32 */
      unsigned long long      clusterOffset;
      unsigned long long      bootSectorBackupOffset;

      unsigned long            rootCluster;           /* FAT32 only */
      int                  rootDirEntryCount;   /* non-FAT32 */
      unsigned long long      rootDirSectorCount;  /* non-FAT32 */
      unsigned long            totalDirClusters;

      FatTable*            fat;
      FatClusterInfo*            clusterInfo;

      unsigned long long       bufferSectors;
      char*                  buffer;

      int                  fragSize;
      unsigned long long       fragSectors;
      int                  fragCount;
      int                  bufferFrags;
      int                  clusterFrags;
};
0
Comment
Question by:rnst
2 Comments
 
LVL 22

Accepted Solution

by:
grg99 earned 175 total points
ID: 9641460
It might help to do a little sanity checking.

First when you read the BPB, verify if the numbers make sense.  A little function called Ensure( int32 Val, int32 Lo, int32 Hi, char * Error )  is very handy for this.


Then when you read the FAT, scan it to make sure you've read the right blocks.  Check each entry to make sure it's in the right range for a cluster number or a free or bad cluster.

Also make sure your numbers are sign-extending properly from 16 to 32 bits.

And make sure yoou're using the rigth values for the free cluster indicators.  I think they're subtly different for 16 and 32 bit FATS.

Oh and it would help to check if that file system is something else, like NTFS.

0
 

Author Comment

by:rnst
ID: 9643850
I've checked all this things, all were correct. Today I've realiazed that I changed the function readFromDisk and it didn't work properly. Now it works fine and the program says the things ok.

Thank you ;)
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Suggested Solutions

An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
The goal of this video is to provide viewers with basic examples to understand how to use strings and some functions related to them in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use nested-loops in the C programming language.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now