ext2 Filesystem
A Unix-like filesystem written in C, inspired by ext2 — an mmap block layer, inodes with single/double/triple indirect pointers, path resolution with pluggable caching, and POSIX semaphores for safe concurrent access, all exposed as a suite of mi_* command-line tools.
The problem
Project for the Operating Systems II course at the Universitat de les Illes Balears.
Build a Unix-like filesystem in C, inspired by ext2, on top of an mmap block layer and with POSIX named semaphores for inter-process safety. The whole state lives in a single regular file — the virtual disk — and every user-facing feature is a standalone binary following the mi_* naming convention.
It targets the parts that make a real filesystem work rather than the parts that make it look finished: on-disk metadata layout, indirect-pointer translation, path resolution and safe concurrent access.
How it works
- Block I/O —
mmapandlseek/read/writebackends over fixed 1024-byte blocks. - Metadata layout — superblock, free-block bitmap and inode array, laid out on disk exactly as the format dictates.
- Inode model — 12 direct pointers plus 1 single, 1 double and 1 triple indirect pointer, reaching ~16M logical blocks per file; the translation between a logical block number and its physical location is the heart of the project.
- Path resolution —
buscar_entradawalks a path down the directory tree, with an optional last / FIFO / LRU cache selectable at compile time. - Files and directories — read/write by inode and by path, hard links, recursive copy / move / remove and a
treeview. - Concurrency — a POSIX named semaphore guards the critical sections, so several processes can mount and write the same disk at once without corrupting it; a stress test (
simulacion) and a log validator (verificacion) check that the invariants hold.
Each command is a small program that links against the core library in src/: mi_mkfs, mi_mkdir, mi_ls, mi_stat, mi_touch, mi_escribir, mi_cat, mi_link, mi_mv, mi_rm, mi_rm_r, mi_tree, and more.
Running it
You only need gcc, make and a Linux/macOS shell. Build all the binaries from the repository root with make, then create a virtual disk and start using it:
$ make
$ ./mi_mkfs disco 100000 # create a 100k-block FS
$ ./mi_mkdir disco 7 /docs/
$ ./mi_touch disco 6 /docs/notes.txt
$ ./mi_escribir disco /docs/notes.txt "hello world" 0
$ ./mi_cat disco /docs/notes.txt
hello world
$ ./mi_tree disco /
└── /
└── docs
└── notes.txt
To exercise larger scenarios, run any of the bundled scripts from the repository root — they invoke ./mi_mkfs, ./mi_ls, … with relative paths and expect the binaries in the current directory:
bash tests/test5a.sh # write/read across all pointer ranges
bash tests/test10.sh # hard links, unlink and recursive removal
bash scripts/estructura.sh # build a sample tree used by the other demos