tFS is a custom, original disk-based filesystem designed for tOS, a hobby x86 operating system. It is a from-scratch implementation that follows no existing filesystem standard (not ext2/4, not FAT32, not anything else).
| Feature | Capability |
|---|---|
| Block size | 4096 bytes |
| Inode size | 256 bytes |
| Inodes | Up to 65,536 |
| Max file size | ~64 GB (12 direct + 1024 indirect + 1M double-indirect blocks) |
| Max volume | ~64 GB (limited by inode count) |
| Inline data | Files ≤60 bytes stored inside the inode (no block overhead) |
| Block addressing | 48-bit (max ~262K blocks with uint32_t block numbers) |
| Directory entries | Fixed-size (264 bytes), inode-based |
| Permissions | Unix-style (owner/group/other, read/write/execute) |
| File types | Regular file, directory, symlink |
| Hard links | Supported |
| Symlinks | Inline (≤60 bytes) or block-backed |
| Timestamps | atime, mtime, ctime (Unix epoch, 32-bit) |
| Volume label | 64-byte volume name |
| UUID | 16-byte UUID |
| Mount state | Clean/dirty tracking, mount counter |
| Superblock checksum | CRC-like hash over metadata fields |
Block 0: Boot sector (reserved, zeroed)
Block 1: Superblock (4096 bytes)
Block 2: Inode bitmap (1 block)
Block 3-N: Block bitmap (variable, ~1 block per 32768 data blocks)
Block N+1 to M: Inode table (4096 blocks for 65536 inodes)
Remaining: Data blocks
| Offset | Size | Field | Description |
|---|---|---|---|
| 0 | 4 | magic | 0x54465301 |
| 4 | 4 | version | 1 |
| 8 | 8 | total_blocks | Total blocks on device |
| 16 | 8 | free_blocks | Free block count |
| 24 | 4 | total_inodes | Maximum inode count |
| 28 | 4 | free_inodes | Free inode count |
| 32 | 4 | inode_bmp_blk | Inode bitmap block number |
| 36 | 4 | block_bmp_blk | Block bitmap block number |
| 40 | 4 | inode_table_blk | Inode table start block |
| 44 | 4 | root_inode | Root directory inode number (2) |
| 48 | 4 | state | 0=clean, 1=dirty, 2=error |
| 52 | 4 | mount_count | Number of mounts |
| 56 | 4 | mount_time | Last mount timestamp |
| 60 | 4 | last_check | Last consistency check |
| 64 | 16 | uuid | Volume UUID |
| 80 | 64 | volume | Volume label (null-terminated) |
| 144 | 4 | checksum | Superblock hash (covers bytes 0-143) |
| 148 | 3948 | padding | Zeroed to fill block |
git clone https://github.com/Artfical/tfs.git
cd tfs
makeThis produces:
libtfs.a— Static library for embedding tFS in other programsmkfs.tfs— Tool to create tFS filesystem images
./mkfs.tfs test.img 65536 "My Volume"Creates a 256 MB filesystem image (65536 blocks × 4096 bytes) with the label "My Volume".
Include tfs.h and link against libtfs.a:
#include "tfs.h"
tfs_t fs;
if (tfs_mount(&fs, "test.img") < 0) { /* error */ }
/* Create files and directories */
tfs_mkdir(&fs, TFS_ROOT_INODE, "home");
tfs_creat(&fs, TFS_ROOT_INODE, "readme.txt");
/* Write data */
tfs_inode_t inode;
int ino = tfs_creat(&fs, TFS_ROOT_INODE, "data.bin");
tfs_inode_read(&fs, ino, &inode);
tfs_write_data(&fs, &inode, my_data, data_size, 0);
tfs_inode_write(&fs, ino, &inode);
/* Read directory */
uint32_t offset = 0;
tfs_dentry_t dent;
while (tfs_readdir(&fs, TFS_ROOT_INODE, &offset, &dent) == 0) {
printf("%.*s\n", dent.name_len, dent.name);
}
tfs_umount(&fs);int tfs_mount(tfs_t *fs, const char *device);
int tfs_umount(tfs_t *fs);
int tfs_format(const char *device, uint64_t blocks, const char *volume);int tfs_inode_alloc(tfs_t *fs);
int tfs_inode_free(tfs_t *fs, uint32_t ino);
int tfs_inode_read(tfs_t *fs, uint32_t ino, tfs_inode_t *inode);
int tfs_inode_write(tfs_t *fs, uint32_t ino, tfs_inode_t *inode);int tfs_block_alloc(tfs_t *fs);
int tfs_block_free(tfs_t *fs, uint32_t blk);
int tfs_block_read(tfs_t *fs, uint32_t blk, void *buf);
int tfs_block_write(tfs_t *fs, uint32_t blk, void *buf);int tfs_read_data(tfs_t *fs, tfs_inode_t *inode, void *buf, uint32_t size, uint32_t offset);
int tfs_write_data(tfs_t *fs, tfs_inode_t *inode, const void *buf, uint32_t size, uint32_t offset);int tfs_lookup(tfs_t *fs, uint32_t dir_ino, const char *name, uint32_t *ino);
int tfs_readdir(tfs_t *fs, uint32_t dir_ino, uint32_t *offset, tfs_dentry_t *dent);
int tfs_link(tfs_t *fs, uint32_t dir_ino, const char *name, uint32_t ino, int filetype);
int tfs_unlink(tfs_t *fs, uint32_t dir_ino, const char *name);
int tfs_mkdir(tfs_t *fs, uint32_t parent_ino, const char *name);
int tfs_creat(tfs_t *fs, uint32_t dir_ino, const char *name);
int tfs_symlink(tfs_t *fs, uint32_t dir_ino, const char *name, const char *target);
int tfs_readlink(tfs_t *fs, uint32_t ino, char *buf, uint32_t size);make testRuns the test suite, which exercises:
- Format, mount, unmount, re-mount
- Directory creation and listing
- File creation (small and large)
- Data write and read integrity (64 KB file)
- Symlink creation and readlink
- Persistence across unmount/remount cycles
- Block allocation and deallocation
- Inline data vs. block-backed storage
- FUSE driver for mounting tFS images on Linux
-
fsck.tfs— Consistency checking and repair tool - Extended attributes
- Block group descriptors (for larger volumes)
- Journaling / write-ahead logging
- Integration into tOS kernel as VFS driver
Copyright (C) 2026 tOS Contributors
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License along with this program. If not, see https://www.gnu.org/licenses/.