AmigaDOS Filesystem On-Disk Structures

The AmigaDOS filesystem stores all data in fixed-size blocks (typically 512 bytes / 128 long-words). This article documents the internal layout of each block type — boot blocks, root blocks, directory blocks, file header blocks, data blocks, extension blocks, hard/soft links, and the bitmap — from Ralph Babel's The Amiga Guru Book (1993, Ch. 15). These structures are the basis for the ADF file format and are essential for disk-repair tools, disk editors, and filesystem-level programming.

Status note: This chapter documents the filesystem as of Kickstart 2.0 (V37). The same block structures are used in OS 3.1/3.2 — the core layout is unchanged. International filesystem types (DOS\2, DOS\3) were introduced in Workbench 2.1.

Block size and long-word numbering

All block types are treated as a series of 32-bit long-words. The block size is called SIZE (measured in long-words; 128 for 512-byte blocks). Long-word offsets run from 0 to SIZE - 1. Bytes within a word and words within a long-word are arranged in big-endian (descending) order, per the M68000 convention.

Strings: BCPL-style

All filesystem strings — names and comments — are stored as a length byte followed by the character bytes (ISO-8859-1 values). This BCPL-style storage (not NUL-terminated) is used everywhere except soft-link path names, which use NUL-terminated C strings.

String Max length
Disk/object name 30 characters
Comment 79 characters
Soft-link path (SIZE - 56) × 4 - 1 characters

Checksum algorithm

The longword at offset 5 holds a checksum for most block types (bitmap blocks store it at offset 0). The algorithm:

The checksum is the negative sum of all other longwords, discarding possible overflows. The sum (modulo 2³²) of all longwords in an uncorrupted block therefore always equals zero.

If the checksum doesn't match, the filesystem reports "Volume ... has a checksum error on disk block ..."

Boot block identification (DOS types)

The first longword of a disk's first boot sector identifies the filesystem format:

Identifier Constant Filesystem
'D','O','S',0 BBID_DOS Old FileSystem (OFS)
'D','O','S',1 BBID_FFS FastFileSystem (FFS)
'D','O','S',2 BBID_DOS2 International OFS (Workbench 2.1)
'D','O','S',3 BBID_FFS3 International FFS
'K','I','C','K' BBID_KICK Kickstart disk

The international versions (DOS\2, DOS\3) were introduced because their hash function handles ISO-8859-1 characters (diacritical marks) differently; using the old hash on international-named files would break lookups.

OFS vs FFS: the key difference

Steve Beats developed the FastFileSystem (FFS) to improve hard-disk performance. The core change: OFS data blocks carry 6 long-words of overhead per block (type, header key, sequence number, data size, next-data pointer, checksum), yielding only 488 bytes of payload per 512-byte block. FFS strips this overhead — the data region occupies the entire block, with no checksum. This allows multi-sector DMA transfers directly to/from the correct memory location.

Property OFS (DOS\0 / DOS\2) FFS (DOS\1 / DOS\3)
Data bytes per 512-byte block 488 512
Data block overhead 6 long-words + checksum None
Data block chaining Linked list (NEXT_DATA) File-header block-list only
Max partition ~50 MB (pre-FFS) ~2 GB (Kickstart 2.0)
Redundancy High (sequence numbers, pointers) Minimal

Block types

Root block (T_SHORT = 2, ST_ROOT = 1)

The root directory is installed at a fixed position — approximately in the middle of the partition:

rootKey = (numReserved + highKey) / 2

where highKey = numCyls × numSurfaces × numBlocksPerTrack - 1 and numCyls = highCyl - lowCyl + 1.

Key fields (long-word offsets):

Offset Field
0 Primary type: T_SHORT = 2
1 Header key (points to the block itself)
3 Hash table size (SIZE - 56)
5 Checksum
6 to SIZE-51 Hash table (pointers to entries)
SIZE-25 to SIZE-50 Bitmap pointers
SIZE-25 Bitmap extension pointer
SIZE-13 to SIZE-8 Root date (days, minutes, ticks)
SIZE-17 Disk name (BCPL string, max 30 chars)
SIZE-10 to SIZE-5 Volume creation date
SIZE-1 Secondary type: ST_ROOT = 1

User-directory block (T_SHORT = 2, ST_USERDIR = 2)

Same layout as the root block, but ST_USERDIR = 2 as secondary type. Contains a hash table for its entries, protection flags, comment, date, and parent pointer (SIZE-3).

File-header block (T_SHORT = 2, ST_FILE = -3)

Offset Field
0 T_SHORT = 2
2 Block count (entries used in data-block list)
4 First data block
5 Checksum
6 to SIZE-51 Data-block pointer list (processed in reverse order)
SIZE-47 File size in bytes
SIZE-43 to SIZE-41 Protection bits (HSPARWED)
SIZE-39 Comment (BCPL string)
SIZE-24 to SIZE-22 Date of last alteration
SIZE-12 File name (BCPL string)
SIZE-4 Hash chain (next entry with same hash)
SIZE-3 Parent directory
SIZE-2 Extension block pointer
SIZE-1 ST_FILE = -3

Extension block (T_LIST = 16, ST_FILE = -3)

When a file exceeds SIZE - 56 data blocks (e.g. 35,136 bytes under OFS with 512-byte blocks), additional extension blocks provide more data-block table space. They form a linked list via SIZE-2. The SIZE-3 field points back to the file header (not the previous extension).

OFS data block (T_DATA = 8)

Offset Field
0 T_DATA = 8
1 Header key (points to file header)
2 Sequence number (starts at 1)
3 Data size (bytes actually used in this block)
4 Next data block (linked list; 0 = last)
5 Checksum
6+ Data bytes (max (SIZE-6) × 4 = 488 bytes for 512-byte blocks)

FFS data block

Under FFS, data blocks are raw — the entire block is data, with no header overhead or checksum. The number of bytes used in the final block is calculated from the file size stored in the file header.

Hard links can point only to file headers and user directories (not to the root or to soft links). The block contains an ORIGINAL pointer (SIZE-4) to the real object and a LINKCHAIN pointer (SIZE-3) to the next hard link referring to that object. If the original is deleted, the first hard link is converted to the original's type.

Soft links store a NUL-terminated C string (the only non-BCPL string in the filesystem) at offsets 6 to SIZE-51, containing the path to the referenced object. Soft links were not officially supported under Kickstart 2.0 — both design and implementation were flawed.

Bitmap block

The bitmap tracks which blocks on a volume are in use (1 bit per block). Unlike other blocks, the checksum is at offset 0. From long-word 1 onward, each bit represents one block (bit 0 of long-word 1 = block 0). The bitmap can be extended via extension blocks (linked list). The bitmap is fully redundant — it can be reconstructed from the rest of the filesystem.

The hash function

Directory lookups use key transformation (hashing). The name is converted to a hash value, which indexes into the parent's hash table (long-words 6 to SIZE-51). Collisions are resolved by chaining (HASHCHAIN at offset SIZE-4).

ULONG hash(const UBYTE *name, ULONG longwordsPerBlock)
{
    ULONG result = strlen(name);
    while (*name != '\0')
        result = (result * 13 + capitalch(*name++)) & 0x7ff;
    return result % (longwordsPerBlock - 56) + 6;
}

capitalch() depends on the filesystem type:

  • OFS/FFS (DOS\0, DOS\1): standard ASCII uppercasing (a-zA-Z)
  • International (DOS\2, DOS\3): also uppercases ISO-8859-1 characters \340-\376 (except \367), e.g. accented letters with diacritical marks

FFS ordering rule: Under the FastFileSystem, hash chains must be sorted in ascending order of block number. The OFS does not require this.

Protection bits (HSPARWED)

Stored in the file header at offset SIZE-43. The mnemonic reads left to right as bit 7 to bit 0; a set bit means protected (inverted from intuitive use):

Bit Flag FIBF_ constant Meaning when SET (protected)
7 H FIBF_HOLD Hold (script file)
6 S FIBF_SCRIPT Script (execute as script)
5 P FIBF_PURE Pure (resident-able)
4 A FIBF_ARCHIVE Archive flag (changed since last backup)
3 R FIBF_READ Read-protected (FFS only)
2 W FIBF_WRITE Write-protected
1 E FIBF_EXECUTE Execute-protected
0 D FIBF_DELETE Delete-protected

The archive flag (A) is set by a backup program to mark "backed up"; the filesystem automatically clears it whenever a file is modified and closed. This supports incremental backups.

Reserved blocks and boot blocks

The first blocks on any partition are reserved (default 2, configurable via Reserved in MountList / DE_BOOTBLOCKS in RDB). For bootable floppies, the boot block occupies these first two sectors. Only the first 3 long-words have system meaning (disk type, checksum, root-block pointer); the rest is boot code executed if the checksum is valid.

See Also


Sources: Ralph Babel, "The Amiga Guru Book" (Taunusstein, 1993), Chapter 15 — The AmigaDOS Filesystem. Raw: raw/rkm/guru-book.md Updated: 2026-08-08