Solved

Reading FAT table

Posted on 2003-10-29
2
1,211 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

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…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
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.

707 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