Starting in 1996, Alexa Internet has been donating their crawl data to the Internet Archive. Flowing in every day, these data are added to the Wayback Machine after an embargo period.
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.
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:
If the first byte is equal to 0x00, this entry is available and no entry beyond this one has been used.
If the first byte is equal to 0xE5, this entry has been erased and is available for use.
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:
typedefstruct 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:
0x01(0000 0001) - Read Only
0x10(0000 0002) - Hidden File
0x04(0000 0100) - System File
0x08(0000 1000) - Volume label
0x10(0001 0000) - Directory
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.
Bits 0 - 4: Day of month, range 1-31
Bits 5 - 8: Month of year, range 1-12
Bits 9 - 15: Count of years, range 0 - 127
Time format: This is also 16-bit and its granularity is 2 seconds.
Bits 0 - 4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds)
Bits 5 - 10: Minutes, rane 0-59
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)
typedefstruct 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 failureif (!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 ModeNULL, // Security Descriptor
OPEN_EXISTING, // How to create
0, // File attributesNULL); // Handle to templateif(hFloppy != NULL)
{
dwFilePointer = SetFilePointer(hFloppy,
(512 * 19), NULL, FILE_BEGIN);
// Test for failureif (dwFilePointer != INVALID_SET_FILE_POINTER)
{
int iSector = 19;
BOOL bNoEntry = FALSE;
// Iterate through root directory sectorsdo
{
if (!ReadFile(hFloppy, byteRoot, 512,
&dwBytesRead, NULL))
{
printf("Error in Reading Root Entry.\n");
}
else
{
BYTE *pByteRoot = byteRoot;
// Iterate through 32 byte entriesfor(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// statusif(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.
About the Author
Small-Talk and Small-Programming working together.
My Blog
Add www.codeguru.com to your favorites Add www.codeguru.com to your browser search box IE 7 | Firefox 2.0 | Firefox 1.5.xReceive news via our XML/RSS feed
RATE THIS ARTICLE:
Excellent Very Good Average Below Average Poor
(You must be signed in to rank an article. Not a member? Click here to register)
Latest Comments:
No Comments Posted.
Add a Comment:
Title:
Comment:
Pre-Formatted:
Check this if you want the text to display with the formatting as typed (good for source code)
(You must be signed in to comment on an article. Not a member? Click here to register)