FAT Root Directory Structure on Floppy Disk and File Information

Introduction

In my previous article, "Extract Floppy Disk Geometry from the Boot Sector," you learned about floppy disk geometry formatted in a Windows environment for FAT. In this article, you will look at the FAT root directory entry on a floppy disk. So far, you know that a floppy disk formatted in a Windows environment has a total of 2880 sectors. Out of this, the 0th sector (the first 512 bytes) is reserved as the boot sector. The next 18 sectors are reserved for FATs.

Immediately after these FAT sectors, the root directory sectors start. In a FAT file sytem, root directories comprise 14 sectors. Today's discussion will be on this area.

You know that the maximum directory entry allowed under the root directory for the FAT file system on a 3.5" floppy disk is 224. The size for root directory entries is (14 * 512) bytes, which is equivalent to 7168 bytes. Divide 7168 bytes with the max root entries for the FAT; you will get each entry size for the root directory, which is 32 bytes. Each 32 bytes holds information about a file or directory.

I would like to advise you to go through the FAT 32-byte directory structure as mentioned by Microsoft in http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx.

Structure for FAT 32-Byte Directory Entry

Byte Range Description
0 - 10 Short name (8+3) for file/folder
11 File attribute (Read only, directory, System file, and so on)
12 Reserved
13 Millisecond time for file creation
14 - 15 File creation time
16 - 17 File creation date
18 - 19 File access date
20 - 21 High 16-bit cluster number
22 - 23 File modification time
24 - 25 File modification date
26 - 27 16-bit cluster number
28 - 31 File size in bytes

Notes on the first byte of the FAT directory entry:

  1. If the first byte is equal to 0x00, this entry is available and no entry beyond this one has been used.
  2. If the first byte is equal to 0xE5, this entry has been erased and is available for use.
  3. If the first byte is equal to 0x05, the actual filename character for this byte is 0xE5.

C++ Data Structure for 32-Byte Root Directory Entry

I have created one structure, as shown below, to hold the root directory entry:

typedef struct root_Entries
{
   BYTE short_FileName[11];
   BYTE fileAttributes;
   BYTE reserved;
   BYTE createTime_ms;
   WORD createTime;
   WORD createDate;
   WORD accessedDate;
   WORD clusterNumber_High;
   WORD modifiedTime;
   WORD modifiedDate;
   WORD firstClusterAddress_FAT12;
   DWORD sizeofFile;
} root;

Notes on the file attribute byte of the FAT directory entry:

  1. 0x01(0000 0001) - Read Only
  2. 0x10(0000 0002) - Hidden File
  3. 0x04(0000 0100) - System File
  4. 0x08(0000 1000) - Volume label
  5. 0x10(0001 0000) - Directory
  6. 0x20(0010 0000) - Archive

Notes on the Date/Time format of the FAT directory entry:

Date Format: The date field is 16-bit. This is relative to 01/01/1980.

  1. Bits 0 - 4: Day of month, range 1-31
  2. Bits 5 - 8: Month of year, range 1-12
  3. Bits 9 - 15: Count of years, range 0 - 127

Time format: This is also 16-bit and its granularity is 2 seconds.

  1. Bits 0 - 4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds)
  2. Bits 5 - 10: Minutes, rane 0-59
  3. Bits 11 - 15: Hours, range 0-23

Reading file information from a 32-byte root directory

The following code snippet will give the basic operation to read file information stored directly under the drive's root ('A:\'). For the simplicity of the program, I have formatted the floppy under the Windows environment for FAT and a short-named file (file name with an 8+3 format) copied into it. Then, I tried the following code snippet and got file information.

#define INVALID_SET_FILE_POINTER ((DWORD)-1)

typedef struct root_Entries
{
   BYTE short_FileName[11];
   BYTE fileAttributes;
   BYTE reserved;
   BYTE createTime_ms;
   WORD createTime;
   WORD createDate;
   WORD accessedDate;
   WORD clusterNumber_High;
   WORD modifiedTime;
   WORD modifiedDate;
   WORD firstClusterAddress_FAT12;
   DWORD sizeofFile;
} root;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
   int nRetCode = 0;

   // initialize MFC and print and error on failure
   if (!AfxWinInit(::GetModuleHandle(NULL), NULL,
       ::GetCommandLine(), 0))
   {
      // TODO: change error code to suit your needs
      cerr << _T("Fatal Error: MFC initialization failed") << endl;
      nRetCode = 1;
   }
   else
   {
      DWORD dwFilePointer;
      DWORD dwBytesRead;
      root stRoot;
      BYTE byteRoot[512];
      memset(&byteRoot, 0, 512);

      HANDLE hFloppy = NULL;
      hFloppy = CreateFile("\\\\.\\A:",    // Floppy drive to open
         GENERIC_READ,                     // Access mode
         FILE_SHARE_READ,                  // Share Mode
         NULL,                             // Security Descriptor
         OPEN_EXISTING,                    // How to create
         0,                                // File attributes
         NULL);                            // Handle to template
      if(hFloppy != NULL)
      {
         dwFilePointer = SetFilePointer(hFloppy,
            (512 * 19), NULL, FILE_BEGIN);
         // Test for failure
         if (dwFilePointer != INVALID_SET_FILE_POINTER)
         {
            int iSector = 19;
            BOOL bNoEntry = FALSE;
            // Iterate through root directory sectors
            do
            {
               if (!ReadFile(hFloppy, byteRoot, 512,
                   &dwBytesRead, NULL))
               {
                  printf("Error in Reading Root Entry.\n");
               }
               else
               {
                  BYTE *pByteRoot = byteRoot;
                  // Iterate through 32 byte entries
                  for(int i = 0; i < (512/32); i++)
                  {
                     memcpy(&stRoot, pByteRoot, 32);

                      // No entry beyond this used.
                     if(stRoot.short_FileName[0] == 0x00)
                     {
                        // Stop iteration
                        bNoEntry = TRUE;
                        break;
                     }
                     else
                     {
                        // This if loops checks for file deletion
                        // status
                        if(stRoot.short_FileName[0] == 0xE5)
                        {
                           printf("First character of file after
                                   deletion :0x%x\n",
                              stRoot.short_FileName[0]);
                           printf("File status: Deleted.\n");
                        }

                        printf("File Name            : %s\n",
                                                     : stRoot.short_
                                                     : FileName);
                        if(stRoot.fileAttributes & 0x01)
                        printf("File Attribute       : Read Only File\n");
                        if(stRoot.fileAttributes & 0x02)
                           printf("File Attribute    : Hidden File\n");
                        if(stRoot.fileAttributes & 0x04)
                           printf("File Attribute    : System File\n");
                        if(stRoot.fileAttributes & 0x08)
                           printf("File Attribute    : Volume Label\n");
                        if(stRoot.fileAttributes & 0x0f)
                           printf("File Attribute    : Long File Name\n");
                        if(stRoot.fileAttributes & 0x10)
                           printf("File Attribute    : Directory\n");
                        if(stRoot.fileAttributes & 0x20)
                           printf("File Attribute    : Archive\n");

                        WORD nYear = (stRoot.createDate >> 9);
                        WORD nMonth = (stRoot.createDate << 7);
                        nMonth = nMonth >> 12;
                        WORD nDay = (stRoot.createDate << 11);
                        nDay = nDay >> 11;

                        printf("Create Date    : %d/%d/%d\n", nDay,
                                               : nMonth, (nYear+1980));

                        nYear  = (stRoot.modifiedDate >> 9);
                        nMonth = (stRoot.modifiedDate << 7);
                        nMonth = nMonth >> 12;
                        nDay   = (stRoot.modifiedDate << 11);
                        nDay   = nDay >> 11;

                        printf("Modification Date    : %d/%d/%d\n",
                                                     : nDay, nMonth,
                                                     : (nYear+1980));

                        nYear  = (stRoot.accessedDate >> 9);
                        nMonth = (stRoot.accessedDate << 7);
                        nMonth = nMonth >> 12;
                        nDay   = (stRoot.accessedDate << 11);
                        nDay   = nDay >> 11;

                        printf("Accessed Date        : %d/%d/%d\n",
                                                     : nDay, nMonth,
                                                     : (nYear+1980));

                        printf("Start Cluster Address: %d\n",
                               stRoot.firstClusterAddress_FAT12);
                        printf("File Size            : %d bytes\n",
                                                     : stRoot.
                                                     :sizeofFile);
                        pByteRoot += 32;
                     }    // End of else
                  }

                  if(bNoEntry)
                  break;
                  else
                  {
                     iSector += 1;
                  }
               }
            } while(iSector <= 33);
         }

         CloseHandle(hFloppy);
      }
   }

   return nRetCode;
}

Once you run the program above, it will give following output:

You can cross check this information with file properties from Windows Explorer. The result must be the same.

FAT Root Directory Structure on Floppy Disk and File Information

Deletion of File and 32-byte root directory entry:

I have deleted this file from the floppy using Windows Explorer. Then, I executed my program and got interesting information. Please follow the picture below:

[File_Details_Delete.JPG]

It is clear that, after deleting the file from Windows Explorer, all information is intact except that the first byte of the file name has been replaced with 0xE5. It marks that the entry has been erased and it can be reused for other files. But, until and unless it is being used for other files, the deleted file can be recovered.



About the Author

Mufti Mohammed

Small-Talk and Small-Programming working together. My Blog

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Wednesday, September 24, 2014 8:00 AM - 9:00 AM PDT According to a recent Forrester Research report, many companies are choosing low-code platforms over traditional programming platforms, due to the speed with which low-code apps can be assembled and tested. With customer-facing applications on the rise, traditional programming platforms simply can't keep up with the "short schedules and rapid change cycles" required to develop these applications. Check out this upcoming webinar and join Clay Richardson from …

  • Java developers know that testing code changes can be a huge pain, and waiting for an application to redeploy after a code fix can take an eternity. Wouldn't it be great if you could see your code changes immediately, fine-tune, debug, explore and deploy code without waiting for ages? In this white paper, find out how that's possible with a Java plugin that drastically changes the way you develop, test and run Java applications. Discover the advantages of this plugin, and the changes you can expect to see …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds