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.
Name | Full Name |
---|---|
FAT | File allocation table |
HFS | Hirearchal file system |
NTFS | New technology file system |
EXT4 | Extended journaling file system |
procfs | Process information pseudo file system |
sysfs | System file system |
tmpfs | Temporary 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--
.
Octal | Literal |
---|---|
0 | --- |
1 | --x |
2 | -w- |
3 | -wx |
4 | r-- |
5 | r-x |
6 | rw- |
7 | rwx |
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.