# Computer file

## What it is

A computer file is what a program asks the operating system for when it wants the same bytes back
tomorrow: it opens the file by name, reads or writes, closes it, and trusts that the next program to
open that name will see what was left there. Documents, photos, programs, settings and logs are all
files, and on Unix-like systems so are several things that are stored nowhere at all.

POSIX, the standard behind Linux, macOS and the other Unix-like systems, defines a file as an object
that can be written to, read from, or both, with attributes that include its access permissions and
its type. It then lists the types: regular files, directories, symbolic links, FIFOs, sockets, and
character and block special files, which stand for devices such as a terminal or a disk. When people
say file they nearly always mean the first kind, which the standard describes as a randomly
accessible sequence of bytes on which the system imposes no structure of its own. The system neither
knows nor cares whether those bytes are a spreadsheet, a photo or a page of a database; structure
belongs to the program that reads them. POSIX even declines to separate text files from binary ones,
while noting that many utilities only give meaningful output on text.

The name is held outside the file. A directory is a list of entries, and each entry links a filename
to a file. A filename is a single component that may contain any byte except a slash and the null
byte, up to a limit the system sets; a pathname such as `/srv/site/index.html` is the chain of names
the system walks to reach it. Because names live in directories, one file can have several of them,
and the system keeps a count. When the last name is removed and no process still has the file open,
the space is freed.

Everything else the system knows about a file is metadata, and a long listing shows most of it:

```text
$ ls -li notes.txt
1048577 -rw-r----- 2 ana staff 4096 Oct 16 09:14 notes.txt
```

The first number is the file serial number, unique within its file system: that number is the file,
and the names only point at it. Then come the permission bits for the owner, the group and everyone
else, the number of names the file has, the owner and group, the size in bytes, and the time of last
data modification. POSIX keeps two more times beside that one: the last data access and the last
change to the file's status. A program that has opened a file holds a file descriptor, a small
integer private to the process. Descriptors 0, 1 and 2 are standard input, output and error, which
is why a shell can send a program's output into a file without the program knowing.

## Why it matters

Files are the oldest interface between programs that were never introduced to each other. A tool
written decades ago can hand data to one written yesterday through a file, with no agreement beyond
the bytes and the name. Configuration, logs, exports, backups and the content of most websites all
travel this way, so keeping files trustworthy is most of keeping a system trustworthy.

The metadata is where the subtle trouble lives. The modification time says when the bytes were last
written, which is a different fact from when what they say last changed, and the two part company
the moment a tool rewrites a file with identical content. Ownership is stored as a number, so the
same file can belong to a different person on another machine.

Then there is durability. A write that returns has handed the bytes to the operating system, which
may keep them in a cache. POSIX says cached data reaches storage when a program asks for it with a
call such as `fsync`, and may get there earlier on its own, and it warns that after a crash later
operations may be on disk while earlier ones are missing. It gives the example of a rename that
leaves the new name created and the old one still in place.

Finally, a file is one copy on one device until someone arranges otherwise. Storage fails in ways
that depend on the medium, and the only protection that holds across all of them is a second copy
somewhere else that has been read back.

## What it looks like in practice

A file's modification time records when its bytes were last written, which is a different moment
from when its content last changed, and the site's sitemap once showed the gap: its dates put 172 of
the 176 pages at one identical moment of change.
[The fix traced the date back to the file itself](/portfolio/fixed-a-sitemap-with-one-shared-timestamp-140/):
the content export writes every file afresh on each run, so whatever a page said, one sync gave the
whole site a single timestamp. The date now comes from version history through a
fallback chain that tries an explicit field, then the commit history, then the file. The page
records the trap in that chain: the literal field name has to be in the list, or the generator never
reads it. A missing date leaves the field empty rather than holding a guess, and a re-sync after a
month of edits now touches eight files of 186.

The company's
[backups end with a file being read back](/portfolio/built-encrypted-backups-with-a-monthly-restore-drill-114/).
On a systemd timer the database is dumped to a file where one exists, and that file leaves with the
rest in an encrypted, deduplicated snapshot sent over SFTP to a second provider, followed by a
retention prune and an integrity check. Once a month a drill pulls a known
file out of the repository and compares it, so what gets tested is a restore rather than a backup.
Even the passphrase is a file, on purpose: the units read it from disk, while a value placed in the
environment would pass through the supervisor's escape handling, and a single backslash would
quietly have turned it into a different passphrase from the one the repository was created with.

Years earlier the job was rescuing files, often the only copy, from failed hardware:
[data recovery](/portfolio/performed-data-recovery-across-a-wide-range-of-92/) across SD cards,
spinning hard drives, SSDs, RAID arrays, external drives and Mac systems. Each of those fails and
gives up its data differently, and a Mac filesystem has its own quirks, so the work was as much
about the right approach for the medium as about any single technique. The measure was the plain
one: files handed back intact.

## Where it goes wrong

**Every page looks changed at once.** A copy, checkout, restore or export rewrites the file and
resets its modification time, and every system downstream that trusts that time sees a change that
never happened. A copy that preserves times does the opposite and hides a change that did. Take
content dates from the content or from version history, and leave the file time to mean what it
means.

**A reader finds half a file.** A program that rewrites a file in place leaves a window in which
another process, or the next boot, sees part of the old version and part of the new. Write a
temporary file in the same directory, call `fsync` on it, then rename it over the original. POSIX
requires that the replaced name stays visible throughout a rename and points at either the old file
or the new one.

**A script trips over a legal name.** A filename may contain spaces, newlines and a leading dash,
and a script that splits names on whitespace or passes them to a command unquoted will act on the
wrong files. POSIX's own advice is to avoid a leading hyphen and to stick to letters, digits, the
full stop, the underscore and the hyphen for names that must travel. Quote every expansion, and end
option parsing with `--` before a list of names.

**A secret file is readable by everyone.** The permission bits on a new file come from the defaults
of the process that created it, and those defaults usually let the group and others read. A key or
passphrase written that way is shared with every account on the host. Create secret files with
owner-only permissions from the start rather than tightening them afterwards.

## Further reading

- [NIST CSRC glossary: file](https://csrc.nist.gov/glossary/term/file) — the definitions used in
  NIST security publications, each with the document it comes from.
- [POSIX.1-2024 Base Definitions: Definitions](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html)
  — the formal meaning of file, regular file, filename, pathname, directory entry and file
  descriptor.
- [POSIX.1-2024 Base Definitions: General Concepts](https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap04.html)
  — permissions, the three file times, filename portability and what a crash can leave behind in the
  cache.
- [POSIX.1-2024: rename()](https://pubs.opengroup.org/onlinepubs/9799919799/functions/rename.html) —
  the guarantee that a name being replaced points at either the old file or the new one throughout,
  which safe saving relies on.

<https://engineer.company/glossary/file/>
