In the OS, directories (aka folders) are a format on the File system that contain a list of directory entries.

  • Directories are files themselves!
  • Each entry contains the file name, the first block number, etc. The exact information will depend on the file system implementation.
  • It can also include other directories

Directory entries

Technically are structs that represent the files/subdirectories within a directory. This example stores Inodes but for FAT it would point at the first block number of the file.

struct dirent {
    ino_t d_ino;    /* This file/directory's inode number */
    char d_name[];  /* Null-terminated name of file */
    uint8_t d_type; /* Indicator of file type. Only in Linux */
}

There is no natural ordering of the directory entries e.g. they’re not sorted alphabetically, by inode number etc.

Additional features

  • Directory entries can also store what file type it’s holding. This helps us implement subdirectories (because now we can differentiate between regular files and folders)
  • . and .. as pseudo-folders in a directory. For the root, .. would simply refer to itself just like how . usually does. They are literal directory entries.
    • Since there is no natural ordering of directory entries, these two entries can be interspersed anywhere

Growing a directory

Since directories are also files on the file system, they can also start filling up. When the time comes, we can expand a directory to another block. We then need some way of tracking the second block, which is handled differently depending on the file system.

  • For FAT we just update the next pointer for the root directory’s initial table entry node.
  • For Inodes I assume we can just add another logical block to the array of 12, and expand into the indirect pointers as necessary.

Also see

When we’re using inodes, Directory entries store the inode number for the file (instead of the file’s initial block like in FAT).

Link to original