Master the fundamental concepts of file systems through this focused micro-challenge.
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
Every task includes starter code, theory, and hidden tests so you can implement and verify locally in the browser.
How it worksAn in-memory filesystem models paths as a tree of struct inode nodes: directories point to children, files hold data blocks or inline buffers. No disk means you focus on naming, permissions, and lookup without driver noise.
Each inode stores:
For example, path /etc/hosts walks root → etc dir inode → hosts file inode.
The inode/dentry split you build here is the same design Linux's VFS layer uses for every real filesystem, and it's exactly how tmpfs (the filesystem behind /tmp and /dev/shm) organizes files entirely in RAM. Get path resolution wrong and you reproduce real VFS bugs , like directory loops or dangling dentries , that have caused kernel panics in production.
Before you call the implementation done, walk failure modes on purpose. Test empty structures, single-element edge cases, maximum concurrency, and errno paths that must not crash the program. OS code usually fails in production when happy-path tests pass but invariants break under contention or memory pressure.
Keep structures small and name fields after kernel counterparts when possible. That lets you read man pages and kernel source side by side while you work. Print observable events during development; remove noisy logs once tests pass reliably.
You will implement lookup, create, read, and write on the tree API. This exercise requires enforcing that unlinking a directory with children fails, matching POSIX expectations.
Build an in-memory filesystem the way Linux's VFS and tmpfs organise one. Every file and directory is an inode (number, type, size, link count, data), and a directory's contents are dentries that map a name to a child inode. Operations resolve slash-separated paths by walking dentries from the root, and report POSIX-style errors when a walk goes wrong.
| Command | Effect |
|---|---|
mkdir PATH | create a directory (the parent must exist) |
create PATH TEXT... | create a file whose content is the rest of the line (may be empty); an existing file is overwritten |
append PATH TEXT... | append the text to an existing file |
read PATH | print the file's content |
ls PATH | list a directory, or show a single file |
rm PATH | remove a file, or an empty directory |
stat PATH | show an inode |
tree | print the whole tree |
Paths are absolute (/a/b). Repeated or trailing slashes are ignored, and / is the root.
The root is inode 1. Every new inode takes the next unused number (numbers are never reused). A directory's size is its number of entries; a file's size is its byte count. A directory's link count is 2 + number of subdirectories; a file's is 1.
mkdir/create/append/rm: ok followed by the inode number, e.g. mkdir /home: ok (inode 2).read: read /a.txt: "hello"ls: ls /home: docs/ notes.txt. Entries are sorted by name, directories get a trailing /, and an empty directory shows (empty). On a file, ls prints the file's own name.stat: stat /home: inode 2 dir size 2 links 3 or ... file size 5 links 1.tree: one line per inode, depth-first with children sorted by name, indented 2 spaces per level. The root is /, directories end in /, and files show name (N bytes).Every line starts with the command and the path exactly as written in the input. Errors are printed as COMMAND PATH: error ENAME:
ENOENT: a path component doesn't exist.ENOTDIR: a component used as a directory is a file.EEXIST: mkdir on an existing name, or create over a directory.EISDIR: read/append on a directory.ENOTEMPTY: rm of a non-empty directory.EBUSY: rm /.Input:
cLoading…
Output:
cLoading…
The text of create/append starts after exactly one space following the path, so append /f world appends " world".
resolve(path) function returning the inode or an error.Hidden tests cover every error, overwriting a file with create, removing a file and an empty directory (and the parent's link count dropping), ls on a file, deep paths with redundant slashes, and a tree with several branches.