All projects

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.

C Operating SystemsFilesystemsC

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 — mmap and lseek/read/write backends 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_entrada walks 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 tree view.
  • 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