Nix
Store Path and Store Directory
Store Path and Store Directory
Nix's store object and file system object data models are minimal and abstract. But to actually be used by software, store objects need to be made available through the operating system's file system.
This is done by exposing all the store objects in a single store directory. Every entry in that directory is a store path base name pointing to a store object. Store objects exposed in this way can then be referenced by store paths.
Store Path Base Name {#base-name}
Nix implements references to store objects as store path base names.
Think of a store path base name as an opaque, unique identifier: The only way to obtain a store path base name is by adding or building store objects. A store path base name will always reference exactly one store object.
Store path base names are pairs of
- A 20-byte [digest]{#digest} for identification
- A symbolic [name]{#name} for people to read
Example
- Digest:
q06x3jll2yfzckz2bzqak089p43ixkkq- Name:
firefox-33.1
A store path base name is rendered to a string as the concatenation of
- Digest rendered in Nix32, a variant of Base32 (20 hash bytes become 32 ASCII characters)
- Hyphen (
-) - Name
Example
q06x3jll2yfzckz2bzqak089p43ixkkq-firefox-33.1 |------------------------------| |----------| digest name
Exactly how the digest is calculated depends on the type of store object being referenced. Store path digests are supposed to be opaque, and so for most operations, it is not necessary to know the details. That said, the manual has a full specification of store path digests.
Store Directory Path
Every Nix store has a store directory path.
This is an absolute, lexically canonical (not containing any .., ., or similar) path which points to the directory where all store objects are to be found.
Note
The store directory defaults to
/nix/store, but is in principle arbitrary.
Store Path
A store path is the pair of a store directory path and a store path base name. It is rendered to a file system path as the concatenation of
- Store directory path (typically
/nix/store) - Path separator (
/) - The store path base name
Example
/nix/store/q06x3jll2yfzckz2bzqak089p43ixkkq-firefox-33.1 |--------| |------------------------------| |----------| store directory digest name
When we have fixed a given store, or given store directory path (that all the stores in use share), the abstract syntax for store paths and the abstract syntax for store path base names coincide: the store directory path is known from context, so only the other two fields vary from one store path to the next.
Exposing Store Objects in OS File Systems {#exposing}
Not every store can be accessed through the file system. But if the store has a file system representation, the following should be true:
The store directory path is canonical: no prefix of the path (i.e. path of the first n path segments) points to a symlink. In other words, the store directory can be looked up from the store directory path without following any symlinks. (This condition is a separate condition in addition to the "lexical canonicity" described above, which is a property of just the path itself. This (regular) "canonicity" is a property about the path and the filesystem it navigates jointly.)
Note
The
allow-symlinked-storesetting can be used to relax this requirement.The store directory path in fact points to a directory.
The store directory contains, for every store object in the store, the file system object of that store object at the (rendered) store path base name. The permissions and other metadata for these files in the store directory is in the normal form described in Exposing in OS file systems.
The above properties mean that the following file accesses will work.
Suppose we have a store available on the file system per the above rules, and b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1 is the store path base name of a store object in that store.
Suppose that the store directory (path) is
/foo/bar. Then,/foo/bar/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1exists and is the file system object of that store object.Suppose that we don't know what the store directory path of the store is, but we do have a capability
storeDirto the store directory on the file system. (This would be a "file descriptor" on Unix, or a "file handle" on Windows.) Then (using the Unix notation for this):openat(storeDir, "b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1", O_NOFOLLOW)will succeed (so long as the file system object is not a symlink), and the yielded capability will point to the file system object of that store object.
(The behavior for symlinks is harder to specify because of limitations in POSIX.)
Relocating store objects
The inclusion of the store directory path in the full rendered store path means that the full rendered store path is not just derived from the referenced store object itself, but depends on the store that the store object is in. (And actually, all of the currently-supported ways of computing the digest of a store path also depend on the store directory path, as described in the specification of store path digests. So this is also true even just for store path base names, in general.)
It is therefore important to consider which store a given store object belongs to: Files in the store object can contain store paths, and processes may read these paths. Nix can only guarantee referential integrity if store paths do not cross store boundaries.
One can only copy store objects to a different store if
The source and target stores' directories match
or
The store object in question has no references, that is, contains no store paths
One cannot copy a store object to a store with a different store directory. Instead, it has to be rebuilt, together with all its dependencies. It is in general not enough to replace the store directory string in file contents, as this may render executables unusable by invalidating their internal offsets or checksums.