How to set up smartphones and PCs. Informational portal
  • home
  • Windows phone
  • FAT file system architecture. Features of FAT32, NTFS and exFAT file systems

FAT file system architecture. Features of FAT32, NTFS and exFAT file systems

There are many ways to store information and programs on a hard drive. A very well-known system that saves various information in the form of files, grouping them into folders with a unique assignment. However, few people thought about how the physical storage of information on the media actually takes place.

In order for information to be stored on a physical medium, it must be prepared for use in a computer operating system. The operating system allocates free disk space to save information. To do this, you need to divide the disk into small containers - sectors. Formatting a disk at a low level allocates a certain size for each sector. The operating system groups these sectors into clusters. Top-level formatting sets all clusters to the same size, typically between 2 and 16 sectors. In the future, one or more clusters are allocated for each file. The cluster size depends on the operating system, disk capacity, and the required speed.

In addition to the area for storing files on the disk, there are areas necessary for the operation of the operating system. These areas are designed to store boot information and information to map file addresses to physical locations on the disk. The boot area is used to start the operating system. After the BIOS is loaded, the boot area of ​​the disk is read and executed to start the operating system.

FAT file system

The FAT file system appeared with the Microsoft DOS operating system, after which it was improved several times. It has FAT12, FAT16 and FAT32 versions. The name FAT itself comes from the file system's use of a kind of database in the form of a "file allocation table" (File Allocation Table), which contains an entry for each cluster on the disk. The version numbers refer to the number of bits used in the item numbers in the table. Therefore, the file system has a limit on the supported disk size. In 1987, it did not support disks larger than 32 MB. With the advent of Windows 95, a new version of the FAT32 file system was released with theoretical support for drives up to 2 TB. Persistent problems with supporting large disks appear due to the fixed number of elements, limited by the number of bits used in determining the position of the cluster. For example, the FAT16 version does not support more than 2 16 or 65536 clusters. The number of sectors in a cluster is also limited.

Another problem with large disks was the inability to use the huge space allocated for small files. Due to the fact that the number of clusters is limited, their size was increased in order to cover the entire capacity of the disk. This leads to inefficient use of space when storing most files that are not a multiple of the cluster size. For example, FAT32 allocates 16 KB clusters for disk partitions ranging from 16 GB to 32 GB. To store a 20 KB file, you will need two 16 KB clusters, which will occupy 32 KB on disk. 1 KB files take up 16 KB of disk space. Thus, on average, 30-40% of the disk capacity is wasted for storing small files. Partitioning a disk into small partitions allows you to reduce the size of the cluster, but it is not used in practice for disks with a capacity of more than 200 GB.

File fragmentation is also not a small problem of the file system. Since a file may require several clusters to locate, which may not be physically consecutive, the time it takes to read slows down programs. Therefore, there is a constant need for.

NTFS file system

In the early 1990s, Microsoft began developing completely new software designed for environments with more resource consumption than typical home users. For the needs of business and industry, the resources provided by DOS-based Windows operating systems have become insufficient. Microsoft Corporation worked with IBM on the OS / 2 operating system with the HPFS (High Performance File System) file system. Corporate development did not bring success and soon each company again went its own way. Microsoft developed various versions of the Windows NT operating system that Windows 2000 and Windows XP are based on. Each of them uses its own version of the NTFS file system, which continues to evolve.

NTFS (New Technology File System) is the standard file system for Windows NT-based operating systems. It was designed to replace FAT. NTFS is more flexible than FAT. Its system areas store mostly files rather than fixed structures like FAT, allowing them to be modified, expanded, or moved during use. A simple example is the Master File Table (MFT). MFT is a kind of database with various information about files on a disk. Small files (1 KB or less) can be stored directly in the MFT. For large files, NTFS allocates clusters, but unlike FAT, the cluster size usually does not exceed 4 KB, and the built-in compression method eliminates problems with unused space allocated for files. And in NTFS you can use .

The NTFS file system is designed for a multi-user environment and has built-in security and access control mechanisms. For example, operating systems Windows 2000 and Windows XP (except "Home Edition") allow you to set access permissions for individual files and encrypt them. However, a high level of security complicates the work of ordinary users with a computer. You must be extremely careful when setting passwords and file permissions so as not to lose important data.

Greetings!

Whatever the storage medium is - be it a hard drive, an SSD drive or a flash drive (MicroSD, microSDXC, USB-Flash Drive, etc.), they all need a file system so that they can write and read data from them.

There are a number of file systems, but in this article we will consider the most popular and, accordingly, used ones.

The presented information is very useful in situations where you need to format a hard disk (SSD drive) or one of its partitions, a flash drive, etc.

FAT16, FAT32 file system - history and features

Let's start with the file system FAT16(also called simply FAT) - it was created primarily for the MS DOS operating system, and its support was available in Windows 95 and Windows 98. The limit on the maximum size of a single file was 2 Gigabytes. Exactly the same could be the maximum partition size.

The dominance of FAT16 did not last long, it was soon replaced by the FAT32 file system - it was standard for Windows 95 and Windows 98, although for compatibility purposes, as mentioned above, these operating systems also supported FAT16.

In FAT32, the maximum file size was already 4 GB. Those. the number of files can be any, but the size of any of them cannot exceed 4 gigabytes. And the maximum partition size could be theoretically 8 Terabytes, but in Windows it was artificially limited. For example, in Windows 98, the size of a partition could not exceed 137 GB.

You may have a natural question why, after so many years, flash drives and small hard drives can be formatted into this file system. The answer to this question is below.

  • Compatibility: FAT32 is still universally supported by major operating systems: Windows, MacOS, Linux, various standalone devices (set-top boxes, MP3 players, phones, smartphones, etc.) and embedded systems.
  • Restrictions: If you try to write a file that is larger than 4 gigabytes, you will not be able to do this and an error will pop up. There are solutions to this problem.

    There are also partition size limits - although FAT32 theoretically supports storage media up to 8 Terabytes, in Windows XP (and later) you will not be able to format a disk or partition larger than 32 GB to FAT32. This limitation was introduced by Microsoft in order to maintain optimal performance when working with this file system.

  • Today, this file system is successfully used on flash drives and drives in order to ensure maximum compatibility with the widest class of devices.

    Another advantage is the absence of redundant writing / reading of "technical data" in the process of interacting with this file system. For Flash disks, which have a limited resource for reading / writing memory cells, this is undoubtedly a blessing.

NTFS file system - description, application and key properties

File system NTFS today is relevant and ubiquitous. First debuting in Windows XP, it continues to be used in all modern versions of Microsoft's operating system, including the latest Windows 10.

Its developers did their best, endowing this file system with many features that were dictated by modern realities. For example, due to the recording of technical information of all ongoing file operations, it was significantly possible to increase the reliability of data safety in the event of a sharp blackout of the media.

Also in NTFS was added the ability to set the rights to files and folders, which significantly raises the overall security when working in Windows. Do not forget about the possibility of creating shadow copies of files and data during the operation of a system that actively uses the Windows OS in order to ensure high performance when backing up data, encrypting and simply operating the operating system normally.

Naturally, this is not a complete list of what the modern NTFS file system offers.

As mentioned above, this file system is standard for Windows XP and subsequent released operating systems from Microsoft. During the installation of the operating system, you will not even be able to select a file system - the hard drive or SSD will be formatted strictly in NTFS.

Due to the significant complication of the principles of the NTFS file system and some licensing issues, it has very limited support from other operating systems and devices.

For example, the MacOS operating system can only read data from media that uses NTFS, but it can no longer write data to media with this file system.

In Linux the situation is better. Although Linux can only read data from NTFS media by default, some final Linux distributions also add support for writing to NTFS drives.

As for standalone devices, game consoles (Sony PlayStation, Xbox 360), etc., in most cases NTFS is not supported by them.

  • Compatibility: Fully supported in all modern OS versions from Microsoft. Macintosh (MacOS) only supports reading, while Linux supports reading and, in some final distributions, also writing. As for other devices, in most cases it is not supported at all.
  • Restrictions: There are no restrictions on the number and size of files and folders.
  • Optimal scope: The file system was created with an eye to use for hard drives (and later SSDs), mainly in the Windows environment.

ExFat file system - what it is, what it was created for

ExFat(also called FAT64) is a file system that debuted in 2006, designed for flash drives. During its development, all the best from FAT32 was taken and its inherent limitations were eliminated. ExFat has no limits on the maximum file size that can be written to media with a given file system.

Also, the situation with the elimination of an excessive number of technical read / write operations has been further improved in order to ensure the maximum speed of basic file operations with a minimum impact on memory cells in order to prevent and delay their wear as much as possible.

If we talk about compatibility, then the situation with it is much better when compared with the same NTFS. MacOS has full support for read/write operations, and support from Linux is available, provided that you install several packages from the repository.

As for external devices, the situation with ExFat support is improving, but it is definitely impossible to guarantee support on all devices.

  • Compatibility: It has full support on Windows starting with Windows XP, on MacOS and Linux OS (you may need to install a support package from the repository).

    Old standalone devices (MP3 players, cameras, etc.) may not be supported.

  • Restrictions: This file system does not have any restrictions on both the maximum file size and their number.
  • Optimal scope: Any flash drives and drives (MicroSD, microSDXC, USB Flash drive, etc.) larger than 4 GB. A flash drive with this file system will show high speed performance and last longer than if it uses NTFS.

Summary

To summarize the above, it turns out that the NTFS file system should be used for hard (HDD) and SSD drives that are installed inside the computer, and ExFat for external flash drives.
And FAT32 is best used for flash drives of small size (up to 4 gigabytes), as well as flash drives that are used in older devices and do not understand ExFat.

That's all! See you in new content! In order not to miss them - it is worth subscribing!

Let's analyze the types of file system for a flash drive, which one is still better. One user sent me a photo with the error "The file is too large for the target file system" and decided to write an article in which cases to use FAT32, NTFS and exFAT systems. He moved a file larger than 4 GB to an 8 GB flash drive. The fact is that the FAT32 system cannot process information over 4 GB, if your flash drive has a capacity of 32 GB and its file system is FAT32, then you will not be able to write a file over 4 GB to it. Consider all three file systems in windows, analyze their pros and cons.

FAT32

The old file system mode, which is usually used when buying a flash drive from the store and the reason for this is compatibility. Compatibility lies in the fact that FAT32 can be used on any computer running MAC, Windows, Linux, old PCs. The biggest limitation is that it has a 4 GB file size limit, which today has problems with formats such as 4k video, Blu-ray. In a word, if you are going to work with files that are less than 4 GB in size and the flash drive is used on different computers, with different operating systems, then the FAT32 file system is very suitable.

exFAT

An updated file system created by Microsoft to replace FAT32. Started in Windows Vista SP1 and has a maximum file size of 16 exabytes (EB), which is 1 EB = 10 18 bytes. Compatible with Mac OS and Windows, it is a very good system for sharing large files.

Minuses:

  • It does not have any logging functionality in which all changes to files on disk are logged before they are actually executed.
  • Not supported by Time Machine on Apple. In a word, you will not be able to backup from Apple using Time Machine software.
  • A very complex structure that requires more computing power.

Pros:

  • Rewrites the same sector fewer times, which is important for flash drives, extending the life of memory cells. As you know, flash drives have N-number of overwrites, then they fail.
  • Large file size limit of 16 exabytes.
  • The cluster size is 32 megabytes.
  • Improved free space distribution, which reduces disk defragmentation.

NTFS

The latest file system created by microsoft is the modern structure of today for almost any modern internal hard drive, flash drive or ssd drive. NTFS is a new file system technology. The windows system can only be installed on NTFS. It is the default for operating system discs due to its versatility. It has all microsoft technologies: logging, no file size limit, support for file compression, long filenames, file access control for server admins and more. At home, this is the best option for using this system on disks and flash drives. There is one catch, when you insert a USB flash drive into Mac OS, you can copy information from a USB flash drive, but you cannot change it.

Output:

For USB sticks you should use exFAT if you are constantly in the Mac OS, Windows environment, moving the flash drive from one operating system to another. If you're only using windows, then NTSF is a great solution.

VLADIMIR MESHKOV

FAT file system architecture

General characteristics of the FAT file system. Partition structure with FAT file system

The FAT (File Allocation Table) file system was developed by Bill Gates and Mark McDonald in 1977 and was originally used in the 86-DOS operating system. In order to achieve portability of programs from the CP/M operating system to 86-DOS, it retained the earlier restrictions on filenames. 86-DOS was later acquired by Microsoft and became the basis for MS-DOS 1.0, released in August 1981. FAT was designed to work with floppy disks smaller than 1 MB and did not initially support hard disks.

The structure of the FAT partition is shown in the figure.

In the FAT file system, the disk space of a logical partition is divided into two areas - the system area and the data area (see Figure 1). The system area is created and initialized when formatting, and subsequently updated when manipulating the file structure. The system area of ​​FAT file systems consists of the following components:

  • boot record (boot record, BR);
  • reserve area;
  • file allocation tables;
  • root directory area (does not exist in FAT32).

The data area of ​​a logical disk contains files and directories subordinate to the root, and is divided into sections of the same size - clusters. A cluster may consist of one or more consecutive sectors on a disk. The number of sectors in a cluster must be a multiple of 2N and can take values ​​from 1 to 64. The cluster size depends on the type of file system used and the size of the logical disk.

Purpose, structure and types of the file allocation table

FAT got its name from the file allocation table of the same name - File Allocation Table, FAT. The file allocation table stores information about logical disk clusters. Each cluster corresponds to an entry in the FAT table containing information about whether the cluster is free or occupied by file data. If the cluster is occupied by a file, then the address of the cluster containing the next part of the file is indicated in the corresponding element of the file allocation table. The number of the initial cluster occupied by the file is stored in the directory entry containing the file entry. The last element of the list of clusters contains the sign of the end of the file (EOF - End Of File). The first two elements of the FAT are reserved.

The FAT file system always fills free disk space sequentially from beginning to end. When creating a new file or expanding an existing one, it looks for the very first free cluster in the file allocation table. If in the course of work some files were deleted, while others changed in size, then the resulting empty clusters will be scattered across the disk. If the clusters containing the file's data are not in a row, then the file is fragmented.

There are the following types of FAT - FAT12, FAT16, FAT32. FAT type names are derived from the element size: FAT12 element has a size of 12 bits (1.5 bytes), FAT16 - 16 bits (2 bytes), FAT32 - 32 bits (4 bytes). In FAT32, the four most significant bits are reserved and are ignored during the operation of the operating system.

Root directory

The file allocation tables are followed by the root directory. Each file and subdirectory in the root directory has a 32-byte directory entry containing the file name, its attributes (archived, hidden, system, and read-only), and the date and time it was created (or last modified) , as well as other information. For FAT12 and FAT16 file systems, the position of the root directory on the partition and its size are fixed. In FAT32, the root directory can be located anywhere in the partition's data area and have an arbitrary size.

File name formats

One of the characteristics of early versions of FAT (FAT12 and FAT16) is the use of short filenames. The short name consists of two fields - an 8-byte field containing the file name itself, and a 3-byte field containing the extension (format "8.3"). If the file name entered by the user is shorter than 8 characters, then it is padded with spaces (code 0x20); if the entered extension is shorter than three bytes, then it is also padded with spaces.

The directory entry structure for a short file name is shown in Table 1.

The first byte of the short name performs the functions of a directory occupancy indicator:

  • if the first byte is 0xE5, then the directory entry is free and can be used when creating a new file;
  • if the first byte is 0x00, then the directory entry is free and is the start of a clean directory area (there is no active entry after it).

Table 1. Directory entry structure for a short file name

Bias

Size (byte) Content
0x00 11 Short file name
0x0B 1 File Attributes
0x0C 1 Reserved for Windows NT.
0x0D 1 A field specifying the time the file was created (contains tens of milliseconds). The field is processed only in FAT32
0x0E 1 File creation time. The field is processed only in FAT32
0x10 2 The date the file was created. The field is processed only in FAT32
0x12 2 The date the file was last accessed to write or read data. The field is processed only in FAT32
0x14 2 High word of the file's first cluster number. The field is processed only in FAT32
0x16 2 The time of the last write operation to the file
0x18 2 The date on which the file was last written to
0x1A 2 Low word of the first cluster number of the file
0x1C 4 File size in bytes

There are a number of restrictions on the use of ASCII characters in a short name:

  • you cannot use characters with codes less than 0x20 (except for the code 0x05 in the first byte of the short name);
  • characters with codes 0x22, 0x2A, 0x2B, 0x2C, 0x2E, 0x2F, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, 0x5B, 0x5C, 0x5D, 0x7C cannot be used;
  • you cannot use a space character (0x20) in the first byte of a name.

The FAT32 and VFAT (virtual FAT, FAT16 extension) file systems support long file names (LFN). The long name is stored in the directory entries adjacent to the main entry. The file name is written not in ASCII characters, but in Unicode. Up to 13 Unicode characters can be stored in one directory entry. The unused section of the last fragment is filled with codes 0xFFFF. The directory entry structure for a long filename is shown in Table 2.

Table 2. Directory entry structure for a long filename

Bias Size (byte) Content
0x00 1 Fragment number
0x01 10 Characters 1-5 of file name in Unicode
0x0B 1 File Attributes
0x0C 1 Flags Byte
0x0D 1 Short name checksum
0x0E 12 Characters 6-11 of the filename in Unicode
0x1A 2 Number of the first cluster (filled with zeros)
0x1C 4 Characters 12-13 of the filename in Unicode

boot sector

The first sector of a FAT logical disk contains the boot sector and the BIOS parameter block. The initial section of this block is identical for all FAT types (Table 3). Differences in the structure of boot sectors for different FAT types start at offset 0x24. For FAT12 and FAT16, the structure is shown in Table 4, for FAT32 - in Table 5.

Table 3. Initial section of the boot sector

Bias Size, bytes Description
0x00 3 Unconditional jump (jmp) to boot code
0x03 8 Manufacturer ID
0x0B 2 Bytes per sector (512)
0x0D 1 Number of sectors in a cluster
0x0E 2 The number of spare sectors in the partition's spare area, starting from the first sector of the partition
0x10 1 Number of FAT tables (copies)
0x11 2 For FAT12/FAT16 - number of 32-byte file descriptors in the root directory; for FAT32 this field has a value of 0
0x13 2 The total number of sectors in the section; if this field contains 0, then the number of sectors is set by the field at offset 0x20
0x15 1 Media type. For a hard drive, this is 0xF8; for a floppy disk (2 sides, 18 sectors per track) - 0xF0
0x16 2 For FAT12/FAT16, this field contains the number of sectors occupied by one copy of FAT; for FAT32 this field has a value of 0
0x18 2 Number of sectors per track (for interrupt 0x13)
0x1A 2 Number of working surfaces (for interrupt 0x13)
0x1C 4 Number of hidden sectors before partition
0x20 4 The total number of sectors in the partition. The field is used if the section more than 65535 sectors, otherwise the field contains 0.

Table 4. Structure of the FAT12/FAT16 boot sector

Bias Size, bytes Description 0x24 1 Interrupt drive number 0x13 0x25 1 0x26 1 Enhanced boot record flag (0x29) 0x27 4 Logical drive number 0x2B 11 Disc label 0x36 8 Text string with file system type abbreviation

Table 5. FAT32 boot sector structure

Size, bytes Description 4 Number of sectors occupied by one copy of FAT 2 Active FAT number 2 FAT32 version number: high byte - version number,minor - revision number. The current value is 0:0 4 Cluster number for the first root directory cluster 2 Sector number of the FSINFO structure in the spare area of ​​the logical disk 2 Sector number (in the spare area of ​​the logical drive) usedto store a backup copy of the boot sector 12 Reserved (contains 0)

Bias
0x24
0x28
0x2A
0x2C
0x30
0x32
0x34

In addition to the 2nd and 3rd fields listed in the tables, the zero sector of the logical disk must contain the code 0x55 in the byte with offset 0x1FE, and the code 0xAA in the next byte (offset 0x1FF). The specified two bytes are a sign of a boot disk.

Thus, the boot sector performs two important functions: it describes the data structure on the disk, and it also allows you to boot the operating system.

On a FAT32 logical disk, there is an additional FSInfo structure located in the first sector of the spare area. This structure contains information about the number of free clusters on the disk and the number of the first free cluster in the FAT table. The structure format is described in Table 6.

Table 6. Structure of the FSInfo sector and FAT32 backup boot sector

Size, bytes Description 4 The value 0x41615252 is a signature that indicates that this sector contains the FSInfo structure 480 Reserved (contains 0) 4 Value 0x61417272 (signature) 4 Contains the current number of free clusters on disk. If the field contains the value 0xFFFFFFFF, then the number of free clusters is unknown and must be calculated 4 Contains the cluster number from which the disk driver should start searching for free clusters. If the field contains the value 0xFFFFFFFF, then the search for free clusters should start from cluster number 2 12 Reserved (contains 0) 4 Signature 0xAA550000 - sign of the end of the FSInfo structure

Bias
0x000
0x004
0x1E4
0x1E8
0x1EC
0x1F0
0x1FC

To access the contents of a file located on a partition with the FAT file system, you need to get the number of the first cluster of the file. This number, as we have already established, is part of the directory entry containing the file entry. The number of the first cluster corresponds to the FAT table entry, which stores the address of the cluster containing the next part of the file. The FAT entry corresponding to the last cluster in the chain contains the end-of-file signature. For FAT12 this value is 0xFFF, for FAT16 it is 0xFFFF, for FAT32 it is 0xFFFFFFFF.

Let's look at the software implementation of the reading algorithm for each FAT type, and start with FAT16.

All source texts considered in the article are available on the journal's website.

Software implementation of the algorithm for reading a file from a logical partition with the FAT16 file system

Let's develop a module that reads the first N clusters of a file created on a partition with the FAT16 file system. The parameter N (number of clusters to read) is a variable and is set by the user. The file name follows the format "8.3", i.e. is short. The module operates under Linux OS.

Define the necessary header files:

#include

#include

#include

#include

#include

#include "split.h"

The header file split.h has the following contents:

#include

#define SHORT_NAME 13 // maximum length of a short filename

struct split_name(

U8name; // File name

U8 ext; // file extension

Int name_len, // filename length

ext_len; // file extension length

The split_name structure is designed to store the components of a short file name (name and extension) and their lengths.

The header file defines structural types that describe the main components of the FAT file system - boot sector, FSInfo sector, directory entry structures for short and long file names.

Let's briefly consider the fields that are included in each of these structures.

    1. Boot sector structure struct fat_boot_sector:
      • __s8 system_id– system identifier;
      • __u8 sector_size - sector size in bytes;
      • __u8 cluster_size– cluster size in sectors;
      • __u16 reserved– number of spare sectors in the spare area of ​​the partition;
      • __u8 fats– number of FAT copies;
      • __u8 dir_entries– number of 32-byte file descriptors in the root directory;
      • __u8 sectors– number of sectors per partition; if this field is 0, the total_sect field is used;
      • __u8 media– type of media on which the file system was created;
      • __u16 fat_length– FAT size in sectors;
      • __u32 total_sect– FAT partition size in sectors (if sectors == 0).
      • __u32 fat32_length– FAT32 size in sectors;
      • __u32 root_cluster– number of the first cluster of the root directory;
      • __u16 info_sector– number of the sector containing the FSInfo structure.

The following fields of this structure are only used by FAT32:

  1. FSInfo sector structure struct fat_boot_fsinfo:
    • __u32 signature1– signature 0x41615252;
    • __u32 signature2– signature 0x61417272;
    • __u32 free_clusters is the number of free clusters. If the field contains -1, the search for free clusters should start from cluster number 2.
  2. Short name directory entry structure struct msdos_dir_entry:
    • __s8 name,ext– file name and extension;
    • __u8 attr– file attributes;
    • __u8 ctime_ms– this field specifies the file creation time up to ms (only FAT32 is used);
    • __u16 ctime– file creation time (only FAT32 is used);
    • __u16 cdate– file creation date (only FAT32 is used);
    • __u16 date– date of the last access to the file (only FAT32 is used);
    • __u16 starthi– upper 16 bits of the number of the first cluster of the file (only FAT32 is used);
    • __u16time,date,start– time and date of file creation, number of the first file cluster;
    • __u32 size– file size (in bytes).
  3. Long name directory entry structure:
    • __u8 id– element number;
    • __u8 name0_4- characters 1 - 5 of the name;
    • __u8 attr– file attributes;
    • __u8 alias_checksum– checksum of the short name;
    • __u8 name5_10- characters 6 - 11 of the name;
    • __u8 name11_12- characters 12 - 13 of the name.

Let's continue the consideration of the software implementation of the algorithm and determine the name of the partition on which the FAT16 file system was created:

#ifndef FAT16_PART_NAME

#define FAT16_PART_NAME "/dev/hda1"

#endif

Global Structures:

struct fat_boot_sector fbs; // boot sector structure

struct msdos_dir_entry dentry; // directory element structure

Global variables:

U16 *fat16; // copy FAT16 table here

U16 sector_size; // sector size (from FAT16)

U16 dir_entries; // number of 32-byte descriptors

// in the root directory (0 for FAT32)

U16 sectors; // total number of sectors in the partition

U32 fat16_size; // FAT16 size

U32 root_size; // size of the root directory

U16 byte_per_cluster; // cluster size in bytes

U16 next_cluster; // next cluster in the chain

int fat;

Let's start with the main function:

int main()

int num;

We set the full name of the file whose contents we want to read. Let me remind you that we work only with short file names. The procedure for working with long names is not covered in this article.

U8 *full_path = "/Folder1/Folder2/text.txt";

Open the device file:

Hard = open(FAT16_PART_NAME, O_RDONLY);

If(hard< 0) {

error(FAT16_PART_NAME);

Exit(-1);

We read the first 10 clusters of the file. The reading is performed by the fat16_read_file() function. The function parameters are the full file name and the number of clusters to read. The function returns the number of clusters read or -1 if an error occurred while reading:

Num = fat16_read_file(full_path, 10);

If(num< 0) perror("fat16_read_file");

Else printf("Read %d clusters ", num);

Close the device file and exit:

close(hard);

return 0;

The function for reading file clusters is as follows:

int fat16_read_file(__u8 *full_path, int num)

Struct split_name sn; // structure for storing the component parts of the file

U8 tmp_name_buff; // buffer for temporary storage of composite elements of the full path of the file

Static int i = 1;

int n;

U8 *tmp_buff;

U16 start_cluster, next_cluster;

We listed the function parameters when considering the main function.

Preparatory operations - reset the tmp_name_buff buffer and the struct split_name sn structure:

The first character in an absolute pathname of a file must be a forward slash (/). Let's check it out:

Read the boot sector from the partition:

If(read_fbs()< 0) return -1;

The read boot sector is now in the global structure struct fat_boot_sector fbs. Copy from this structure the sector size, the number of entries in the root directory and the total number of sectors on the partition:

Determine the size of the cluster in bytes:

Byte_per_cluster = fbs.cluster_size * 512

Let's display the information in the boot sector:

Printf("System id - %s ", fbs.system_id);

Printf("Sector size - %d ", sector_size);

Printf("Cluster size - %d ", fbs.cluster_size);

Printf("Reserved - %d ", fbs.reserved);

Printf("FATs number - %d ",fbs.fats);

Printf("Dir entries - %d ", dir_entries);

Printf("Sectors - %d ", sectors);

Printf("Media - 0x%X ", fbs.media);

Printf("FAT16 length - %u ", fbs.fat_length);

Printf("Total sect - %u ", fbs.total_sect);

Printf("Byte per cluster - %d ", byte_per_cluster);

We calculate the size of FAT16 in bytes and read it:

fat16_size = fbs.fat_length * 512;

If(read_fat16()< 0) return -1;

Reading the root directory:

If(read_root_dentry()< 0) return -1;

The dir_entry pointer is now positioned to the memory area containing the root directory entries. The size of this memory area is equal to the size of the root directory (root_size).

Save (for control) the contents of the root directory in a separate file:

#ifdef DEBUG

close(fat);

#endif

Calculate the beginning of the data area:

data_start = 512 * fbs.reserved + fat16_size * fbs.fats + root_size;

With all the entries in the root directory, we can get to the contents of the test.txt file. To this end, we organize a cycle. In the body of the cycle, we will parse the full name of the file, highlighting its elements - subdirectories (we have two of them, Folder1 and Folder2) and the name of the desired file (test.txt).

While(1) (

Memset(tmp_name_buff, 0, SHORT_NAME);

Memset((void *)&sn, 0, sizeof(struct split_name));

For(n = 0 ; n< SHORT_NAME; n++, i++) {

If((tmp_name_buff[n] == "/") || (tmp_name_buff[n] == "?")) (

I++;

break;

tmp_name_buff[n] = "?";

We fill the structure struct split_name sn with the appropriate information. Filling is performed by the split_name function, and the file name is checked for compliance with the "8.3" format:

< 0) {

printf("not valid name");

return -1;

For each element of the full file name, we determine the initial cluster. To do this, we search in the directory elements (starting from the root) for an entry corresponding to the full name element, and read this entry. The search procedure is performed by the get_dentry() function:

If(get_dentry(&sn)< 0) {

Printf("No such file!");

return -1;

Checking file attributes. If it's a directory, read its contents and continue the loop:

If(dentry.attr & 0x10) (

If(read_directory(dentry.start)< 0) return -1;

continue;

If this is a file, we read the first num clusters. For control, the read information will be saved in a separate file:

If(dentry.attr & 0x20) (

Start_cluster = dentry.start;

tmp_buff = (__u8 *)malloc(byte_per_cluster); // the contents of the cluster will be read here

N = open("clust", O_CREAT|O_RDWR, 0600); // save the read information in this file

If(n< 0) {

error("open");

return -1;

To read the clusters of the file, we organize a loop:

For(i = 0; i< num; i++) {

We read the contents of the cluster into the tmp_buff buffer and save it in a separate file:

< 0) return -1;

< 0) {

error("write");

close(n);

return -1;

We read from FAT16 the number of the next cluster occupied by this file. If this is the last cluster, we break the loop and return to the main function:

#ifdef DEBUG

Printf("OK. Read");

Printf("file`s next cluster - 0x%X .. ", next_cluster);

#endif

If(next_cluster == EOF_FAT16) (

#ifdef DEBUG

Printf("last cluster. ");

#endif

Free(tmp_buff);

close(n);

Return ++i;

#ifdef DEBUG

printf("stop reading");

#endif

Return i;

The FAT16 boot sector is read by the read_fbs() function. The result is placed in the global fbs structure:

int read_fbs()

If(read(hard,(__u8 *)&fbs, sizeof(fbs))< 0) return -1;

return 0;

Reading the file allocation table of the FAT16 file system is performed by the read_fat16() function:

int read_fat16()

U64 seek = (__u64)(fbs.reserved) * 512; // offset to FAT16 from the beginning of the partition

Fat16 = (void *)malloc(fat16_size);

If(pred64(hard, (__u8 *)fat16, fat16_size, seek)< 0) return -1;

return 0;

The root directory is read by the read_root_dentry() function:

int read_root_dentry()

U64 seek = (__u64)fbs.reserved * 512 + fat16_size * fbs.fats; // offset to the root directory from the beginning of the section

Root_size = 32 * dir_entries; // calculate the size of the root directory

dir_entry = (__u8 *)malloc(root_size);

If(!dir_entry) return -1;

Memset(dir_entry, 0, root_size);

If(pred64(hard, dir_entry, root_size, seek)< 0) return -1;

return 0;

Reading a cluster belonging to a file is performed by the read_cluster() function. The input parameters of the function are the cluster number cluster_num and a pointer to the __u8 *tmp_buff buffer where the reading result should be placed. The offset to the cluster on the partition is calculated by the formula (see):

SEEK = DATA_START + (CLUSTER_NUM - 2) * BYTE_PER_CLUSTER,

  • SEEK– offset to a cluster on a partition
  • DATA_START– start of data area
  • CLUSTER_NUM– sequence number of the cluster
  • BYTE_PER_CLUSTER– cluster size in bytes

int read_cluster(__u16 cluster_num, __u8 *tmp_buff)

U64 seek = (__u64)(byte_per_cluster) * (cluster_num - 2) + data_start; // calculate the offset to the cluster

< 0) return -1;

return 0;

The read_directory function reads the entries of a directory (not the root) and places the result in the memory area pointed to by the dir_entry pointer:

int read_directory(__u16 start_cluster)

Int i = 1;

U16 next_cluster;

For(; ;i++) (

We allocate memory to store the contents of the directory, read the contents of the starting cluster and get the value of the next cluster from the FAT16 table:

If(!dir_entry) return -1;

< 0) return -1;

Next_cluster = fat16;

Let's save the contents of the directory in a separate file (for control):

#ifdef DEBUG

Printf("Next cluster - 0x%X ", next_cluster);

Fat = open("dir16", O_CREAT|O_WRONLY, 0600);

Write(fat, dir_entry, root_size);

close(fat);

#endif

If the last cluster is reached, exit the loop, otherwise continue reading the directory by increasing the size of the dir_entry buffer by one more cluster:

If(next_cluster & EOF_FAT16) break;

start_cluster = next_cluster;

return 0;

The get_dentry() function performs a search in the contents of the directory for an element corresponding to the searched file. The input parameters of this function are a pointer to a struct split_name *sn structure containing the elements of the short file name:

Int i = 0;

The dir_entry global buffer contains an array of directory entries in which we are going to look for a file (or directory) entry. For search we organize a cycle. In the body of the loop, we copy the catalog elements into the global dentry structure and compare the value of the name and ext fields of this structure with the corresponding fields of the struct split_name *sn structure. The coincidence of these fields means that we have found an entry of the desired file in the array of directory elements:

for(; ; i++) (

If(!(memcmp(dentry.name, sn->name, sn->name_len)) &&

!(memcmp(dentry.ext, sn->ext, sn->ext_len)))

break;

If(!dentry.name) return -1;

#ifdef DEBUG

Printf("name - %s ", dentry.name);

Printf("start cluster - 0x%X ", dentry.start);

Printf("file size - %u ", dentry.size);

Printf("file attrib - 0x%X ", dentry.attr);

#endif

return 0;

All of the above code is located in the FAT16 directory, file fat16.c. To get the executable module, let's create a Makefile with the following content:

INCDIR = /usr/src/linux/include

PHONY=clean

Fat16: fat16.o split.o

Gcc -I$(INCDIR) $^ -g -o [email protected]

%.o: %.c

Gcc -I$(INCDIR) -DDEBUG -c $^

clean:

Rm -f *.o

Rm -f ./fat16

Software implementation of the algorithm for reading a file from a logical partition with the FAT12 file system

In general, the algorithm for reading a file from a FAT12 partition is identical to the algorithm for reading a file from a FAT16 partition. The difference lies in the procedure for reading elements from the FAT12 table. The FAT16 table was considered by us as a simple array of 16-bit elements. To read the elements of the FAT12 table, the following algorithm is proposed:

  • multiply the element number by 1.5;
  • extract a 16-bit word from FAT using the result of the previous operation as an offset;
  • if the element number is even, perform an AND operation on the read word and mask 0x0FFF. If the number is odd, shift the word read from the table by 4 bits towards the least significant bits.

Based on this algorithm, we implement the function of reading elements from the FAT12 table:

int get_cluster(__u16 cluster_num)

U16 seek;

U16 cluster;

We calculate the offset in the FAT12 table and read a 16-bit word from the table:

Seek = (cluster_num * 3) / 2;

Memcpy((__u8 *)&clust, (__u8 *)(fat12 + seek), 2);

If the starting cluster number is an even number, we shift the value read from the table by 4 bits towards the lower bits, if it is odd, we add it with 0x0FFF:

If(cluster_num % 2) cluster >>= 4;

Else clust &= 0x0FFF;

This snippet can also be implemented in assembler:

" xorw %%ax, %%ax "

" btw $0, %%cx "

"jnc 1f"

" shrw $4, %%dx "

"jmp2f"

"1: andw $0x0FFF, %%dx "

"2: movw %%dx, %%ax "

:"=a" (next)

:"d" (clust), "c" (cluster_num));

We return the result:

return cluster;

Let's take a closer look at the algorithm itself. Assume that a file has been created on a FAT12 partition that occupies the 9th and 10th clusters. Each FAT12 element is 12 bits. Because we read 16-bit elements from the table, then the offset to the 9th element will be equal to 13 bytes (9 * 1.5 = 13, discard the remainder), while the lower 4 bits will belong to the 8th FAT element. They must be discarded, and for this it is enough to shift the read element by 4 bits towards the lower bits, which is provided by the algorithm. The offset to the 10th element will be 15 bytes, and the high 4 bits will belong to the 11th element of the FAT. To discard them, it is necessary to perform an AND operation on the 10th element and the mask 0x0FFF, which also corresponds to the above algorithm.

The source texts of the module for reading a file from a FAT12 partition are located in the FAT12 directory, file fat12.c.

Software implementation of the algorithm for reading a file from a logical partition with the FAT32 file system

The algorithm for reading a file from a partition with the FAT32 file system is practically the same as for FAT16, except that in FAT32 the root directory can be located anywhere on the partition and have an arbitrary size. Therefore, to make it more interesting, let's complicate the task - suppose that we only know the number of the partition with the FAT32 file system. To read information from this partition, you must first determine its coordinates - the offset to the partition from the beginning of the disk. And for this you need to have an idea about the logical structure of the hard drive.

The logical structure of the hard drive

Let's consider the logical structure of a hard drive that corresponds to the Microsoft standard - "main partition - extended partition - non-DOS partitions".

Hard disk space can be organized into one or more partitions, and partitions can contain one or more logical drives.

On the hard disk at the physical address 0-0-1 is the master boot record (Master Boot Record, MBR). The MBR structure contains the following elements:

  • non-system bootloader (non-system bootstrap - NSB);
  • disk partition description table (partition table, partition table, PT). It is located in the MBR at offset 0x1BE and occupies 64 bytes;
  • MBR signature. The last two bytes of the MBR must contain the number 0xAA55.

The partition table describes the location and characteristics of the partitions on the hard drive. Disk partitions can be of two types - primary (primary, main) and extended (extended). The maximum number of primary partitions is four. The presence of at least one primary partition on the disk is mandatory. An extended partition can be divided into a large number of subsections - logical drives. A simplified structure of the MBR is presented in Table 7. The partition table is located at the end of the MBR, 16 bytes are allocated to describe the partition in the table.

Table 7. MBR Structure

Bias Size, bytes 0 446 0x1BE 16 0x1CE 16 0x1DE 16 0x1EE 16 0x1FE 2

The partition table entry structure is shown in Table 8.

Table 8. Structure of the partition table entry entry

Bias Size, bytes Content
0x00 1 Activity flag (0 - section is inactive, 0x80 - section is active)
0x01 1 Disk head number at which the partition starts
0x02 2 Cylinder number and sector number from which the section begins
0x04 1 System ID partition type code
0x05 1 Disk head number where the partition ends
0x06 2 Cylinder number and sector number that ends the section
0x08 4 Absolute (logical) number of the initial sector of the partition
0x0C 4 Partition size (number of sectors)

The first byte in the section element is the section activity flag (0 - inactive, 0x80 - active). It serves to determine whether the partition is a system boot partition and whether it is necessary to boot the operating system from it when the computer starts. Only one section can be active. The partition activity flag is followed by the coordinates of the beginning of the partition - three bytes, indicating the head number, sector number and cylinder number. Cylinder and sector numbers are given in the interrupt format Int 0x13, i.e. bits 0-5 contain the sector number, bits 6-7 are the most significant two bits of the 10-bit cylinder number, bits 8-15 are the least significant eight bits of the cylinder number. Then follows the code identifier System ID, indicating that this partition belongs to one or another operating system. The identifier occupies one byte. Behind the system identifier are the coordinates of the end of the section - three bytes containing the numbers of the head, sector and cylinder, respectively. The next four bytes are the number of sectors before the partition, and the last four bytes are the size of the partition in sectors.

Thus, a partition table element can be described using the following structure:

struct pt_struct(

U8 bootable; // section activity flag

U8 start_part; // coordinates of the beginning of the section

U8 type_part; // system identifier

U8 end_part; // coordinates of the end of the section

U32 sect_before; // number of sectors before partition

U32 sect_total; // partition size in sectors (number of sectors in the partition)

The element of the primary partition immediately points to the boot sector of the logical disk (there is always only one logical disk in the primary partition), and the element of the extended partition points to the list of logical disks made up of structures called secondary MBR (Secondary MBR, SMBR).

Each disk in an extended partition has its own SMBR block. SMBR has a structure similar to MBR, but it does not have a boot record (filled with zeros), and only two of the four partition descriptor fields are used. The first element of the partition points to the logical drive, the second element points to the next SMBR structure in the list. The last SMBR in the list contains the section code zero in the second element.

Let's return to the consideration of the module for reading a file from a FAT32 partition.

Header files:

#include

#include

#include

#include

#include

MBR Signature:

#define SIGNATURE 0xAA55

Device file from which partition information will be read:

#define DEVICE "/dev/hda"

Partition table entry size (16 bytes):

#define PT_SIZE 0x10

The following array of structures maps a section's type code to its character mapping:

struct systypes (

U8 part_type;

U8 *part_name;

struct systypes i386_sys_types = (

(0x00, "Empty"),

(0x01, "FAT12"),

(0x04, "FAT16<32M"},

(0x05, "Extended"),

(0x06, "FAT16"),

(0x0b, "Win95 FAT32"),

(0x0c, "Win95 FAT32 (LBA)"),

(0x0e, "Win95 FAT16 (LBA)"),

(0x0f, "Win95 Ext"d (LBA)"),

(0x82, "Linux swap"),

(0x83, Linux)

(0x85, "Linux extended"),

(0x07, HPFS/NTFS)

Let's determine the number of elements in the i386_sys_types array using the PART_NUM macro:

#define PART_NUM (sizeof(i386_sys_types) / sizeof(i386_sys_types))

Set a limit on the number of logical drives:

#define MAX_PART 20

The following structure array will contain information about the logical drives on the device (hard drive):

struct pt_struct(

U8 bootable;

U8 start_part;

U8 type_part;

U8 end_part;

U32 sect_before;

U32 sect_total;

)pt_t;

inthard; // device file descriptor

U8mbr; // count MBR here

The number of the partition on which the FAT32 file system was created:

#define FAT32_PART_NUM 5

Boot sector, FSInfo sector and directory entry structures (defined in file ):

struct fat_boot_sector fbs;

struct fat_boot_fsinfo fsinfo;

struct msdos_dir_entry dentry;

U32 *fat32 = NULL; // copy FAT32 table here

U16 sector_size; // sector size (from FAT32)

U16 dir_entries; // 0 for FAT32

U16 sectors; // number of sectors per partition

U32 fat32_size; // FAT32 size

U32 data_start; // start of data area

U16 byte_per_cluster; // how many bytes are in the cluster (cluster size in bytes)

U32 next_cluster; // next cluster in the chain

U32 root_cluster; // ROOT cluster - initial cluster of the root directory

U8 *dir_entry = NULL; // pointer to directory entries

U64 start_seek = 0; // start offset to section (in bytes)

Main function:

int main()

int num = 0;

int cluster_num = 5; // how many clusters to read from file

U8 *full_path = "/Folder1/Folder2/readme"; // file to read

We open the device, get information about the partition table on the device and display information about the partitions:

Hard = open(DEV_NAME, O_RDONLY);

If(hard< 0) {

error(DEV_NAME);

Exit(-1);

If(get_pt_info(hard)< 0) {

error("get_pt_info");

Exit(-1);

Show_pt_info();

Calculate the starting offset to the partition:

Start_seek = (__u64)(pt_t.sect_before) * 512;

Read the clusters belonging to the file:

Num = fat32_read_file(full_path, cluster_num);

If(num< 0) perror("fat32_read_file");

Else printf("Read %d clusters\n", num);

close(hard);

return 0;

Information about the partition table is read by the get_pt_info() function:

int get_pt_info(int hard)

Int i = 0;

U64 seek;

We read the partition table from the MBR and check the signature:

Read_main_ptable(hard);

If(check_sign()< 0) {

Printf("Not valid signature!\n");

return -1;

We are looking for the identifier of the extended section. If there is one, we calculate the offset to the extended partition and read information about the logical drives:

for(;i< 4; i++) {

If((pt_t[i].type_part == 0xF) || \

(pt_t[i].type_part == 0x5) || \

(pt_t[i].type_part == 0x0C)) (

Seek = (__u64)pt_t[i].sect_before * 512;

Read_ext_ptable(hard, seek);

break;

return 0;

Partition table reading function read_main_ptable():

void read_main_ptable(int hard)

If(read(hard, mbr, 512)< 0) {

error("read");

close(hard);

Exit(-1);

Memset((void *)pt_t, 0, (PT_SIZE * 4));

Memcpy((void *)pt_t, mbr + 0x1BE, (PT_SIZE * 4));

return;

Signature check function check_sign():

int check_sign()

U16 sign = 0;

Memcpy((void *)&sign, (void *)(mbr + 0x1FE), 2);

#ifdef DEBUG

Printf("Signature - 0x%X\n", sign);

#endif

If(sign != SIGNATURE) return -1;

return 0;

Extended Partition Table Read Function:

void read_ext_ptable(int hard, __u64 seek)

int num = 4; // starting from this position, the array of pt_t structures will be filled with information about logical drives

U8 smbr;

Input data:

  • hard– device file descriptor;
  • seek– offset to the extended partition from the beginning of the disk (in bytes).

To obtain information about logical disks, we organize a loop:

For(;;num++) (

We read the SMBR located at the seek offset from the beginning of the disk:

memset((void *)smbr, 0, 512);

pred64(hard, smbr, 512, seek);

We fill in two elements of the pt_t table, starting from position num. The first element will point to the logical drive, and the second element will point to the following SMBR structure:

Memset((void *)&pt_t, 0, PT_SIZE * 2);

Memcpy((void *)&pt_t, smbr + 0x1BE, PT_SIZE * 2);

We make an amendment in the field "Number of the initial sector" - the countdown is from the beginning of the disk:

Pt_t.sect_before += (seek / 512);

If the partition type code is zero, then there are no more logical disks:

If(!(pt_t.type_part)) break;

Calculate the offset to the next SMBR:

Seek = ((__u64)(pt_t.sect_before + pt_t.sect_total)) * 512;

return;

The show_pt_info() function displays information about found logical drives on the device:

void show_pt_info()

Int i = 0, n;

#ifdef DEBUG

Printf("Number of partitions on disk - %d\n", PART_NUM);

#endif

For(; i< MAX_PART; i++) {

If(!pt_t[i].type_part) break;

Printf("\nPartition type %d - ", i);

For(n = 0; n< PART_NUM; n++) {

If(pt_t[i].type_part == i386_sys_types[n].part_type) (

Printf("%s\n", i386_sys_types[n].part_name);

break;

If(n == PART_NUM) printf("unknown type\n");

Printf("Boot flag - 0x%X\n", pt_t[i].bootable);

Printf("Sectors in section %d - %d\n", i, pt_t[i].sect_total);

Printf("Sectors before section %d - %d\n\n", i, pt_t[i].sect_before);

return;

Reading file clusters from a FAT32 partition is done by the fat32_read_file() function. This function has a lot in common with the fat16_read_file() function, so see point 6 for detailed comments:

int fat32_read_file(__u8 *full_path, int num)

Struct split_name sn;

U8 tmp_name_buff;

Int i = 1, n;

U32 start_cluster, next_cluster;

U8 *tmp_buff;

Preparatory operations - clear the buffer, structure and check the first slash:

Memset(tmp_name_buff, 0, SHORT_NAME);

Memset((void *)&sn, 0, sizeof(struct split_name));

If(full_path != "/") return -1;

Reading the boot sector:

If(read_fbs()< 0) return -1;

Memcpy((void *)§or_size, (void *)fbs.sector_size, 2);

Memcpy((void *)&dir_entries, (void *)fbs.dir_entries, 2);

Memcpy((void *)§ors, (void *)fbs.sectors, 2);

We read the FSInfo structure and display the signature in it:

If(read_fs_info()< 0) return -1;

Printf("Signature1 - 0x%X\n", fsinfo.signature1);

Printf("Signature2 - 0x%X\n", fsinfo.signature2);

Fat32_size = fbs.fat32_length * 512; // FAT32 size in bytes

data_start = 512 * fbs.reserved + fat32_size * 2; // start of data field

Byte_per_cluster = fbs.cluster_size * 512; // cluster size in bytes

root_cluster = fbs.root_cluster; // cluster number of the root directory

Read FAT32:

If(read_fat32()< 0) return -1;

Allocate memory for directory entries:

Dir_entry = (__u8 *)malloc(byte_per_cluster);

If(!dir_entry) return -1;

Reading the root directory:

If(read_directory(root_cluster)< 0) return -1;

We parse the full path of the file and separate each element into components:

While(1) (

Memset(tmp_name_buff, 0, SHORT_NAME);

Memset((void *)&sn, 0, sizeof(struct split_name));

For(n = 0 ; n< SHORT_NAME; n++, i++) {

tmp_name_buff[n] = full_path[i];

If((tmp_name_buff[n] == "/") || (tmp_name_buff[n] == "\0")) (

I++;

break;

tmp_name_buff[n] = "\0";

If(split_name(tmp_name_buff, &sn)< 0) {

Printf("not valid name\n");

return -1;

If(get_dentry(&sn)< 0) {

Printf("No such file!\n");

return -1;

To get the cluster start number in the FAT32 file system, you need to use the high word of the first cluster number of the file - the starthi field of the dentry structure:

Start_cluster = (((__u32)dentry.starthi<< 16) | dentry.start);

Checking the attribute byte:

If(dentry.attr & 0x10) ( // this is a directory

If(read_directory(start_cluster)< 0) return -1;

continue;

If(dentry.attr & 0x20) ( // and this is a file

tmp_buff = (__u8 *)malloc(byte_per_cluster);

N = open("clust", O_CREAT|O_RDWR, 0600);

If(n< 0) {

error("open");

return -1;

Printf("file`s first cluster - 0x%X .. ", start_cluster);

For(i = 0; i< num; i++) {

Memset(tmp_buff, 0, byte_per_cluster);

If(read_cluster(start_cluster, tmp_buff)< 0) return -1;

If(write(n, tmp_buff, byte_per_cluster)< 0) {

error("write");

return -1;

If(next_cluster == EOF_FAT32) (

Free(tmp_buff);

close(n);

Return ++i;

start_cluster = next_cluster;

Return i;

The purpose of the following three functions is to get the contents of the system area, i.e. boot sector, FSInfo structure and FAT32 table:

1) the read_fbs() function reads the boot sector:

int read_fbs()

If(pred64(hard, (__u8 *)&fbs, sizeof(fbs), start_seek)< 0) return -1;

return 0;

2) the read_fs_info() function reads the FSInfo structure:

int read_fs_info()

U64 seek = (__u64)fbs.info_sector * 512 + start_seek;

If(pred64(hard, (__u8 *)&fsinfo, sizeof(fsinfo), seek)< 0) return -1;

return 0;

3) the read_fat32() function reads the FAT32 table:

int read_fat32()

U64 seek = (__u64)fbs.reserved * 512 + start_seek;

Fat32 = (void *)malloc(fat32_size);

If(!fat32) return -1;

If(pred64(hard, (__u8 *)fat32, fat32_size, seek)< 0) return -1;

return 0;

The read_cluster() function reads the cluster with the specified number:

int read_cluster(__u32 cluster_num, __u8 *tmp_buff)

U64 seek = (__u64)(byte_per_cluster) * (cluster_num - 2) + data_start + start_seek;

If(pred64(hard, tmp_buff, byte_per_cluster, seek)< 0) return -1;

return 0;

Reading directories (including the root one) is handled by the read_directory() function:

int read_directory(__u32 start_cluster)

Int i = 2;

U32 next_cluster;

The function parameters are the starting catalog cluster. We read the contents of the directory into the dir_entry global buffer:

If(read_cluster(start_cluster, dir_entry)< 0) return -1;

Next_cluster = fat32;

If the directory occupies one cluster, exit, if not, increase the memory size and continue reading:

For(; ;i++) (

start_cluster = next_cluster;

Dir_entry = (__u8 *)realloc(dir_entry, i * byte_per_cluster);

If(!dir_entry) return -1;

If(read_cluster(start_cluster, (dir_entry + (i - 1) * byte_per_cluster))< 0) return -1;

Next_cluster = fat32;

If((next_cluster == EOF_FAT32) || (next_cluster == 0xFFFFFF8)) return 0;

return 0;

The last function we'll look at searches the contents of a directory for an element that matches the file we're looking for:

int get_dentry(struct split_name *sn)

Int i = 0;

The dir_entry pointer is set to a memory area containing an array of directory entries in which we are going to look for a file (or directory). To search, we organize a loop and place the found entry in the global dentry structure:

For(;;i++) (

Memcpy((void *)&dentry, dir_entry + i * sizeof(dentry), sizeof(dentry));

If(!(memcmp(dentry.name, sn->name, sn->name_len)) &&

!(memcmp(dentry.ext, sn->ext, sn->ext_len)))

break;

If(!dentry.name) return -1;

return 0;

This concludes our consideration of the module for reading a file from a FAT32 partition.

The source code of the module is located in the FAT32 directory, file fat32.c.

Differences in the organization of storing records about files in directories for FAT and EXT2 file systems

A few words about the differences in the organization of storing records about files in directories for FAT and EXT2 file systems. The structure of the EXT2 file system has been covered in .

We just got acquainted with FAT - in it all elements of the directory have a fixed value. When creating a file, the file system driver looks for the first empty position and fills it with information about the file. If the length of the directory does not fit in one cluster, then another cluster is allocated for it, and so on.

Consider how things are in EXT2.

Suppose we have a partition with the EXT2 file system, the block size is 4096 bytes. In this section, we create a directory. The directory size will be equal to the block size - 4096 bytes. In the directory, the operating system immediately creates two entries - an entry for the current directory and an entry for the parent directory. The current directory entry will take 12 bytes, while the parent directory entry will be 4084 bytes long. Let's create a file in this directory. After that, there will be three entries in the directory - the current directory entry is 12 bytes long, the parent directory entry is already 12 bytes long, and the created file entry is, you guessed it, 4072 bytes long. If we delete the created file, the length of the parent directory entry will increase again to 4084 bytes.

Thus, when creating a file, the EXT2 file system driver looks in the directory for an entry of the maximum length and splits it, allocating space for a new entry. Well, if there is still not enough space, one more block is allocated for the directory, and the length of the directory becomes equal to 8192 bytes.

And in conclusion - a small edit to the article "Architecture of the EXT2 file system".

This edit concerns the get_i_num() function for determining the inode number from the filename. The old version of this function looked like this:

int get_i_num(char *name)

int i = 0, rec_len = 0;

Struct ext2_dir_entry_2dent;

For(; i< 700; i++) {

If(!memcmp(dent.name, name, dent.name_len)) break;

Rec_len += dent.rec_len;

Return dent.inode;

Corrected version:

int get_i_num(char *name)

* Function parameter - file name. The return value is the inode number of the file.

int rec_len = 0;

Struct ext2_dir_entry_2dent; // this structure describes the format of the root directory entry:

* The global buffer buff contains an array of directory entries. To determine the inode number of a file, you need to find

* in this array is an entry with the name of this file. To do this, we organize a cycle:

For(;;) (

/* Copy the directory entries into the dent structure: */

Memcpy((void *)&dent, (buff + rec_len), sizeof(dent));

* A filename length of zero means that we have iterated over all directory entries

* and entries with the name of our file were not found. So it's time to go back:

If(!dent.name_len) return -1;

/* The search is done by comparing filenames. If the names match, exit the loop: */

If(!memcmp(dent.name, name, strlen(name))) break;

/* If the names don't match, move to the next entry: */

Rec_len += dent.rec_len;

/* If successful, return the inode number of the file: */

Return dent.inode;

Literature:

  1. V. Kulakov. Programming at the hardware level: a special reference. 2nd ed. / - St. Petersburg: Peter, 2003 - 848 p.
  2. A.V.Gordeev, A.Yu.Molchanov. System software / - St. Petersburg: Peter - 2002
  3. Meshkov V. Architecture of the ext2 file system. - Magazine "System Administrator", No. 11 (12), November 2003 - 26-32 p.

In contact with

FAT - File Allocation Table - This term refers to one of the ways in which a file system is organized on a disk. This table stores information about files on the hard drive as a sequence of numbers that specifies where each part of each file is located. With its help, the operating system finds out which clusters the required file occupies. FAT is the most common file system and is supported by the vast majority of operating systems. At first, FAT was 12-bit and allowed you to work with floppy disks and logical drives with a capacity of no more than 16 MB. In MS-DOS version 3.0, the FAT table became 16-bit to support larger drives, and a 32-bit FAT table is used for drives up to 2047 GB.

FAT32 is a newer file system based on the FAT format and is supported by Windows 95 OSR2, Windows 98, and Windows Millennium Edition. FAT32 uses 32-bit cluster IDs, but reserves the upper 4 bits, so the effective cluster ID size is 28 bits. Since the maximum size of FAT32 clusters is 32 KB, FAT32 can theoretically handle 8 terabyte volumes. Windows 2000 limits the size of new FAT32 volumes to 32 GB, although it does support existing larger EAT32 volumes (created on other operating systems). The larger number of clusters supported by FAT32 allows it to manage disks more efficiently than FAT 16. FAT32 can use 512-byte clusters for volumes up to 128 MB.

The FAT 32 file system in Windows 98 is used as the default. This operating system comes with a special disk conversion program from FAT 16 to FAT 32. Windows NT and Windows 2000 can also use the FAT file system, and therefore you can boot your computer from a DOS disk and have full access to all files. However, some of the most advanced features of Windows NT and Windows 2000 are provided by its own ntfs (NT File System) file system. ntfs allows you to create disk partitions up to 2 TB (like FAT 32), but, in addition, it has built-in file compression, security and auditing functions that are necessary when working in a network environment. And in Windows 2000, support for the FAT 32 file system is implemented. The installation of the Windows NT operating system begins on a FAT disk, but at the end of the installation, the data on the disk can be converted to ntfs format at the end of the installation.

You can also do this later using the Convert.exe utility that comes with the operating system. A disk partition converted to ntfs becomes inaccessible to other operating systems. To return to DOS, Windows 3.1, or Windows 9x, you need to remove the ntfs partition and create a FAT partition instead. Windows 2000 can be installed on a FAT 32 and ntfs drive.

The capabilities of EAT32 file systems are much broader than those of FAT16. Its most important feature is that it supports disks up to 2047 GB and works with smaller clusters, thereby significantly reducing the amount of wasted disk space. For example, a 2 GB hard drive in FAT16 uses 32 KB clusters, while FAT32 uses 4 KB clusters. To maintain compatibility with existing programs, networks, and device drivers wherever possible, FAT32 is implemented with minimal changes to the architecture, APIs, internal data structures, and disk format. But, since the size of the FAT32 table elements is now four bytes, many internal and disk data structures, as well as APIs, had to be revised or extended. Certain APIs on EAT32 drives are blocked to prevent legacy disk utilities from corrupting the contents of FAT32 drives. Most programs will not be affected by these changes. Existing tools and drivers will work on FAT32 drives as well. However, MS-DOS block device drivers (such as Aspidisk.sys) and disk utilities need to be modified to support FAT32. All disk utilities supplied by Microsoft (Format, Fdisk, Defrag, and ScanDisk for real and protected modes) have been redesigned to fully support FAT32. In addition, Microsoft is helping leading vendors of disk utilities and device drivers modify their products to support FAT32. FAT32 is more efficient than FAT16 when working with larger disks and does not require them to be partitioned into 2 GB partitions. Windows 98 necessarily supports FAT16, since it is this file system that is compatible with other operating systems, including third-party companies. In real mode MS-DOS and Windows 98 safe mode, the FAT32 file system is significantly slower than FAT16. Therefore, when running programs in MS DOS mode, it is desirable to include in the Autoexec.bat file or PIF file a command to load Smartdrv.exe, which will speed up disk operations. Some older FAT16 programs may report incorrect information about the amount of free or total disk space if it is more than 2 GB. Windows 98 provides new APIs for MS-DOS and Win32 that allow these metrics to be correctly determined. In table. 1 shows the comparative characteristics of FAT16 and FAT32.

Table 1. Comparison of FAT16 and FAT32 file systems

Implemented and used by most operating systems (MS-DOS, Windows 98, Windows NT, OS/2, UNIX).

On this moment only supported on Windows 95 OSR2 and Windows 98.

Very effective for logical drives smaller than 256 MB.

Does not work with disks smaller than 512 MB.

Supports disk compression, such as the DriveSpace algorithm.

Does not support disk compression.

Handles a maximum of 65,525 clusters, the size of which depends on the size of the logical drive. Since the maximum cluster size is 32 KB, FAT16 can only handle logical disks up to 2 GB.

Able to work with logical drives up to 2047 GB with a maximum cluster size of 32 KB.

The larger the size of the logical disk, the less efficient the storage of files in the FAT "16 system, since the size of the clusters also increases. The space for files is allocated by clusters, and therefore, with the maximum size of the logical disk, a file of 10 KB in size will require 32 KB, and 22 KB of disk space will be wasted.

On logical drives smaller than 8 GB, the cluster size is 4 KB.

The maximum possible file length in FAT32 is 4 GB minus 2 bytes. Win32 applications can open files of this length without special processing. Other applications should use interrupt Int 21h, function 716C (FAT32) with open flag equal to EXTEND-SIZE (1000h).

In the FAT32 file system, 4 bytes are allocated for each cluster in the file allocation table, while in FAT16 - 2 bytes, and in FAT12 - 1.5 bytes.

The upper 4 bits of the 32-bit FAT32 table entry are reserved and do not participate in the formation of the cluster number. Programs that directly read the PAT32 table must mask these bits and prevent them from being changed when new values ​​are written.

So, FAT32 has the following advantages over previous implementations of the FAT file system:

    supports drives up to 2 TB;

    organizes disk space more efficiently. FAT32 uses smaller clusters (4 KB for drives up to 8 GB), which saves up to 10-15% of space on large drives compared to FAT;

    the FAT 32 root directory, like all other directories, is now unlimited, it consists of a chain of clusters and can be located anywhere on the disk;

    has higher reliability: FAT32 is able to move the root directory and work with a FAT backup, in addition, the boot record on FAT32 drives has been expanded to include a backup of critical data structures, which means that FAT32 drives are less sensitive to the occurrence of separate bad patches than existing FAT volumes;

    programs load 50% faster.

Table 2. Comparison of cluster sizes

Disk capacity

Cluster size in FAT16, KB

Cluster size in FAT32, KB

256MB-511MB

Not supported

512 MB -1023 MB

1024 MB - 2 GB

2 GB - 8 GB

Not supported

8GB-16GB

Not supported

16GB-32GB

Not supported

Over 32 GB

Not supported

An advanced disk defragmentation utility optimizes the placement of application files loaded at the time of its launch. It is possible to convert a drive to EAT32 using the Drive Converter (FAT32) utility, but after that it is recommended to run the Disk Defragmenter utility, otherwise the computer will work with the drive more slowly than before. When using FAT32, alternate boot configuration of Windows 98 and Windows NT 4.0 becomes impossible because the latter does not support FAT32. FAT32 allocates disk space much more economically than previous versions of the FAT file system. This frees up tens or even hundreds of megabytes on large drives, and when combined with an advanced FAT32 disk defragmentation utility, significantly reduces application load times. The procedure for converting the file system on a hard drive to FAT32 using Drive Converter (FAT32) is quite simple. To do this, you must sequentially open the Start menu (Start), submenu programs (Programs), Accessories (Standard), System Tools (Utilities) and select the Drive Converter (FAT32) command (Converting the disk to FAT32). The conversion may affect the hibernate features (save computer state to disk) provided on many computers. Systems in which the sleep mode is implemented through the APM BIOS or ACPI (Advanced Configuration and Power Interface) S4 / BIOS must support FAT32 - only then will they work correctly in Windows 98.

Most BIOS manufacturers include virus protection tools that monitor changes to the MBR (Master Boot Record) in the BIOS. In addition, legacy anti-virus utilities installed as resident programs or real-mode drivers may detect the MBR change when MS-DOS boots. Since conversion to FAT32 inevitably modifies the MBR, some virus scanners may erroneously interpret this as a sign of a system infection. Therefore, if an anti-virus utility detects a change in the MBR, it offers to "cure" it. It is best to uninstall your antivirus software and disable the antivirus built into the BIOS before converting the drive to FAT32. Then you can reinstall the antivirus utility and activate the virus protection built into the BIOS.

Top Related Articles