• C

Reading FAT table

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;
};
rnstAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

grg99Commented:
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.

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
rnstAuthor Commented:
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 ;)
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.