Systems Programming Project
Virtual File System
Overview
I built a virtual file system in C that operates on top of a virtual disk,
implementing core file system concepts such as mounting, unmounting, file
creation, file deletion, open file tracking, and persistent block-based storage.
The system uses a superblock, a FAT-style allocation structure, and a root
directory to organize files and manage data blocks. It supports common file
operations such as read, write, seek, and stat while maintaining file offsets
for open descriptors.
Core Capabilities
- Mount and unmount a virtual file system
- Create, delete, open, and close files
- Track open file descriptors and offsets
- Read and write file contents across disk blocks
- Seek within files and query file size
- Persist metadata and data to a virtual disk
What I Learned
This project gave me hands-on experience with how file systems organize
persistent data on disk, including allocation, metadata layout, and open-file
state management. It also reinforced how small implementation details such as
offsets, boundary conditions, and FAT updates can affect correctness across
the entire system.
On-Disk Layout
The file system is organized around a superblock describing the disk layout,
a FAT structure for block allocation, a fixed-size root directory, and data
blocks used to store file contents. This structure provides a compact but
realistic model of how a disk-backed file system works.
File Management
Files are stored in the root directory with metadata such as file name,
size, and starting block. Open files are tracked through a separate table
that stores file descriptor state and current offsets for reads and writes.
Block Allocation
File contents are stored across data blocks and linked through a FAT-style
allocation table. This allows the file system to handle files spanning multiple
blocks while supporting append, overwrite, and partial reads or writes.
Persistence
Metadata structures and file contents are written back to the virtual disk so
that files persist across mount and unmount cycles. This makes the project a
true disk-backed system rather than an in-memory simulation.
Interface Surface
The implementation supports the key file system operations expected from the
provided interface, including mounting, directory management, and random-access
file operations through file descriptors.
Supported operations:
- fs_mount(...)
- fs_umount()
- fs_info()
- fs_create(filename)
- fs_delete(filename)
- fs_ls()
- fs_open(filename)
- fs_close(fd)
- fs_stat(fd)
- fs_lseek(fd, offset)
- fs_read(fd, buffer, count)
- fs_write(fd, buffer, count)
Validation & Testing
Since this project is a backend systems implementation, correctness was
demonstrated through scripted and programmatic tests rather than a GUI.
The provided test harness covered behaviors such as small reads/writes,
multi-block writes, overwrite cases, overread handling, offset-based reads,
and other boundary conditions that are critical in file system logic.
Example testing scenarios:
- create → open → write → seek → read
- write data across multiple blocks
- overwrite existing file regions
- read past current offset / file boundaries
- mount → persist → unmount → remount → verify contents
Challenges
One of the main challenges was correctly handling block-oriented storage
while still exposing a byte-oriented file interface. Reads and writes had
to work correctly both within a single block and across block boundaries,
while keeping metadata, FAT entries, and file size consistent.
Managing file offsets and ensuring that data remained correct after seeking,
remounting, and partial overwrites required careful debugging and strong
attention to edge cases.
Why It Matters
This project helped me understand how higher-level file operations map onto
low-level disk structures. It strengthened my systems programming skills and
gave me experience implementing persistent storage, metadata management, and
file access semantics from the ground up.
Notes
Source code is available upon request due to academic collaboration
constraints. The project was validated using the provided testing framework
and custom created scripts designed to stress file system behavior across
realistic edge cases.