Brain Dump

File System

Tags
comp-arch

A data format used to map information stored in disk partitions to files and hierarchies of files (directories) scattered across the disk.

When looking up a file in the file-system the OS recursively looks up i-nodes from the first directory entry in the path until it reaches the file.

Table 1: Listing of some common see page 4, [file systems].
NameFull Name
FATFile allocation table
HFSHirearchal file system
NTFSNew technology file system
EXT4Extended journaling file system
procfsProcess information pseudo file system
sysfsSystem file system
tmpfsTemporary file system

Note: Some file systems don't provide interfaces to things that are files. procfs is an example of a virtual file system, one that doesn't actually store anything on disk.

A file system commonly deals with:

  • Both storing local files and handling special devices that allow for safe communications between the kernel and user space.
  • Failures, scalability, indexing, encryption, compression and performance.
  • Handling the abstraction between a file that contains data and how the data is stored on disk, partitioned, and protected.

See writing a simple file systems.

File Ownership, Permissions and Security

Unix file systems in particular associate an owning user and an owning group with the file. Initially defaulting to the user and group that created the file.

Each ownership level is then given a specific read, write and execute permission. These come in threes, one set for the owner, the owning group and then any user not in the aforementioned categories. For example the permissions -rw-r--r-- means the owner can both read and write the file but both members of the same group and any other users can only read it. Permissions are commonly set using octal notation for read, write execute (see table tbl:octal-permissions). For example the octal permissions 754 correspond to the permissions rwxr-xr--.

Table 2: Listing of octal values and their various permissions. tbl:octal-permissions
OctalLiteral
0---
1--x
2-w-
3-wx
4r--
5r-x
6rw-
7rwx

For a directory read permissions allows you to list the directory (see files and directories it contains), write permissions allow you to create or delete files in the directory. Execute permissions are special. When given they allow you to access the i-nodes of the directories contents letting you cd into it and modify it if need be. A directory with execute completely disabled would be useless. The value of the execute bit is that a user could be forbidden from listing a directory, but they can access it because the executable bit is set. This means if a user knows in advance a file exists they can inspect it but otherwise their just shooting in the dark.

In some cases the executable bit for the owner can be replaced for an s-bit meaning the setuid bit. For example rwsr-xr-x. This bit has the special property that if you try to execute the program you take on the privileges of the owner of that program, regardless of whether they match your own or not. You can get the uid of within a process using the geteuid function and retrieve the original uid (ignoring the setuid bit) by using getuid.

Directories can also have a sticky-bit t-bit assigned which makes it so only the directories owner, the owner of a file in the directory, or the root user can rename or delete that file. This is useful for shared library directories where multiple users may put files in but they shouldn't be allowed to remove or delete all the executables.

The default permissions for a file created by a user uses a mix of the users own group permissions and a special variable of the users environment called the umask. This simply specifies the bits the user wants to disable and is often set to -------w- to remove the world-write bit.

System Call Kludges

While, technically many file-system system-calls such as open() or close() are implemented in the code for the file-system driver, the OS often provides a layer of abstraction over these calls and expect the file-system driver to satisfy the API of these abstractions (think imaginary functions like linux_open). This allows one file-system to be implemented for multiple OS APIs and makes adding a new OS file-system call easier since the file-system itself doesn't need to change its API.