Sikau

Operating systems · Day 11 · about 40 min

File systems

Directories, paths and files — a small file system in memory.

A tree of names

Disks only store numbered blocks. The file system turns them into a tree of named directories and files. Each file's metadata lives in an inode (size, permissions, which blocks hold its data); directories just map names to inodes. Resolving /docs/notes/todo.txt means walking that tree one name at a time.

The tree in code

function createFS() {
  const root = { type: "dir", children: {} };
  const parts = (path) => path.split("/").filter(Boolean);

  function find(path) {
    let node = root;
    for (const name of parts(path)) {
      if (node.type !== "dir" || !node.children[name]) return null;
      node = node.children[name];
    }
    return node;
  }

  function parentOf(path) {
    const names = parts(path);
    const name = names.pop();
    const dir = find("/" + names.join("/"));
    if (!dir || dir.type !== "dir") throw new Error(`No such directory: /${names.join("/")}`);
    return { dir, name };
  }

  return {
    mkdir(path) {
      let node = root;
      for (const name of parts(path)) {
        node.children[name] ??= { type: "dir", children: {} };
        node = node.children[name];
        if (node.type !== "dir") throw new Error(`Not a directory: ${path}`);
      }
    },
    write(path, text) {
      const { dir, name } = parentOf(path);
      if (dir.children[name]?.type === "dir") throw new Error(`Is a directory: ${path}`);
      dir.children[name] = { type: "file", data: text };
    },
    read(path) {
      const node = find(path);
      if (!node || node.type !== "file") throw new Error(`No such file: ${path}`);
      return node.data;
    },
    ls(path = "/") {
      const node = find(path);
      if (!node || node.type !== "dir") throw new Error(`No such directory: ${path}`);
      return Object.keys(node.children).sort().map((n) => (node.children[n].type === "dir" ? n + "/" : n));
    },
    rm(path) {
      const { dir, name } = parentOf(path);
      const node = dir.children[name];
      if (!node) throw new Error(`No such file: ${path}`);
      if (node.type === "dir" && Object.keys(node.children).length) throw new Error(`Directory not empty: ${path}`);
      delete dir.children[name];
    },
  };
}

The rest of this lesson

  • Names, inodes and blocksexplain
  • Walking a pathexplain
  • Resolve a pathfill
  • Where is it stored?match
  • Build the file systemwrite code
  • Badge quizquiz
  • What you learnedrecap

Continue this lesson free — run real code in your browser

Continue with Google

See all 12 lessons of Operating systems