Prompt and Applicable Context
A service deploys /srv/releases/v1/app.conf. It creates /srv/live/pinned.conf as a hard link and /srv/live/current.conf as a relative symbolic link. A worker opens the release file before an operator renames and later removes directory entries.
Explain what a filename, hard link, symbolic link, inode, and open file descriptor refer to. Predict the result after each operation. Then choose the right mechanism for an immutable snapshot, a movable release pointer, and a cross-filesystem reference. The answer targets Linux systems and ordinary files; filesystem-specific snapshots and Windows shortcuts are outside scope.
What the Interviewer Evaluates
The first signal is the object model. A directory entry binds one name to an inode. A hard link is another directory entry for the same inode; neither name is the original. A symbolic link is a different filesystem object whose payload is a pathname resolved when it is used.
The second signal is lifecycle reasoning. unlink removes one directory entry, not necessarily the file object. The inode and data remain while another hard link or an open file description still references them. A symbolic link can remain present while its stored path no longer resolves.
The third signal is predicting operations rather than reciting a comparison table. Renaming one hard link does not change its peers. Renaming a symlink operates on the symlink itself. Moving a symlink or its target can change a relative path's meaning. Cross-filesystem hard links fail because inode identity is local to one filesystem.
The final signal is operational judgment: inspect link identity and counts, distinguish stat from lstat, perform same-filesystem atomic replacement where required, and avoid pathname check-then-open races on attacker-controlled paths.
Questions to Clarify Before Answering
- Are the source and new hard-link name on the same mounted filesystem? If not,
linkfails with
EXDEV; copying data or using a symlink solves a different problem.
- Does the caller need a stable object or a movable name? A hard link pins one inode. A release
alias should usually be a symlink whose directory entry can be replaced.
- Is the target a regular file or a directory? Linux normally prohibits hard links to directories,
while a symlink may name either.
- Is the symlink absolute or relative? A relative target is resolved from the directory containing
the symlink, not from the process's current working directory.
- Will any process already have the file open? Renaming or unlinking a pathname does not redirect an
existing descriptor; that process continues using the opened object.
- Must the switch be atomic for readers? Replacement with
renameis atomic only within the same
mounted filesystem. A cross-filesystem move needs a different publication protocol.
- Are path components controlled by an untrusted user? If so, a prior
lstatfollowed byopenis
racy. The open itself must enforce the traversal policy.
30-Second Answer Framework
“A hard link is a second directory entry to the same inode, so both names share data and metadata. A symlink has its own inode and stores a path, which is resolved when accessed. Removing one hard-link name decrements the link count; the object survives through other hard links and open descriptors. Removing or renaming the target can leave a symlink dangling.
I would verify with ls -li, stat, lstat or readlink, and an already-open descriptor. I would use a hard link to pin the exact file within one filesystem, a symlink for a replaceable release alias or cross-filesystem reference, and a temporary symlink plus same-filesystem rename for an atomic alias switch. Untrusted paths require an atomic no-symlink or beneath-directory open policy, not a separate check.”
Step-by-Step Deep Dive
Step 1: Build the name-to-object model
For an ordinary file, the directory stores a name and inode reference. The inode carries file type, ownership, mode, timestamps, size, block mapping, and hard-link count. File contents do not belong to one privileged “original filename.”
A hard link adds another directory entry to that inode. Changing bytes or mode through either name is visible through the other. A symlink instead has its own inode and stores a string such as ../releases/v1/app.conf; normal pathname lookup follows that string to another name.
Step 2: Run a concrete experiment
The following commands establish the scenario. The shell file descriptor is deliberately kept open:
mkdir -p /srv/releases/v1 /srv/live
printf 'version=1\n' > /srv/releases/v1/app.conf
ln /srv/releases/v1/app.conf /srv/live/pinned.conf
ln -s ../releases/v1/app.conf /srv/live/current.conf
exec 3< /srv/releases/v1/app.conf
ls -li /srv/releases/v1/app.conf /srv/live/pinned.conf
readlink /srv/live/current.conf
stat -L -c '%F %i %h' /srv/live/current.conf
stat -c '%F %i %h' /srv/live/current.conf
mv /srv/releases/v1/app.conf /srv/releases/v1/app.conf.moved
cat /srv/live/pinned.conf
cat /srv/live/current.conf
cat <&3
rm /srv/releases/v1/app.conf.moved /srv/live/pinned.conf
cat <&3
exec 3<&-Before the rename, the release path and pinned.conf show the same inode and a hard-link count of two. readlink prints the symlink payload. Ordinary stat follows the symlink to the target, while the non-following inspection in the example reports the symbolic-link object itself.
Step 3: Predict rename behavior
mv within this filesystem uses a rename operation for the source entry. The inode does not move, so pinned.conf and descriptor 3 continue to work. current.conf still stores ../releases/v1/app.conf; because that old name disappeared, dereferencing it now fails. Renaming a symlink itself would move that link object, not its target, and could change the meaning of a relative payload because resolution starts from the link's new containing directory.
If a deployment needs to switch current without a missing-name interval, create a fully prepared temporary symlink in the same directory and replace current with rename. Readers opening after the replacement resolve either the old or new directory entry. Processes that already opened the old target keep their old descriptor.
Step 4: Predict unlink and reclamation
Removing app.conf.moved drops one hard link. pinned.conf still names the inode, so its data remains. Removing pinned.conf drops the final directory entry, but descriptor 3 still holds an open reference; cat <&3 continues to read the file. Storage becomes reclaimable only after the last hard link and the last open reference are gone.
This explains why deleting a large active log may not free space, but it is not a reason to truncate an arbitrary descriptor. First identify the owning process and its rotation contract, then signal or restart it safely if required.
Step 5: Apply filesystem and directory boundaries
An inode number is unique only inside its filesystem. A hard link cannot name that inode from another filesystem and link returns EXDEV. A symlink can store a path that crosses a mount boundary because lookup resolves names at access time. It can also name a directory or a target that does not yet exist.
Linux prevents ordinary hard links to directories to avoid cycles and traversal ambiguity. A symlink to a directory is allowed, but moving a relative one can break it and recursive tools may choose different follow policies. State those policies for backup, deletion, and deployment tools.
Step 6: Choose by invariant
Use a hard link when the invariant is “this additional name must keep the exact inode reachable,” the objects share one filesystem, and shared metadata is intended. Use a symlink when the invariant is “resolve this alias to whatever path it currently stores,” especially for directories, release pointers, or cross-filesystem names. Use a copy when independent bytes, metadata, retention, or filesystem placement are required.
Neither link is a backup by itself. Hard-linked names share mutation and corruption. A symlink contains no target data. A backup requires independent failure and retention boundaries plus restore testing.
Step 7: Verify identity and safe traversal
Compare device and inode, not inode alone, because inode numbers can repeat on different filesystems. Check hard-link count with stat, inspect the symlink itself with lstat-style behavior, print its payload with readlink, and test the exact rename/unlink sequence while a descriptor is open.
For untrusted paths, lstat(path) followed by open(path) lets an attacker replace a component between the calls. On Linux, open relative to a trusted directory descriptor and apply the required openat2 resolution restrictions, such as forbidding symlinks or escape above the directory. Security must be enforced by the lookup that returns the descriptor.
Strong Sample Answer
“I start with directory entries. app.conf and pinned.conf are two equal names for one inode, so they share content, permissions, ownership, and timestamps. current.conf is a separate symlink inode whose payload is ../releases/v1/app.conf. The relative path starts at /srv/live, where the symlink lives.
After renaming the release path, the hard link and the already-open descriptor still reference the same file object. The symlink becomes dangling because its stored pathname still names the old entry. After removing the moved name, the hard link keeps the object alive. After removing the hard link too, the open descriptor still works; the kernel can reclaim the object only when that descriptor closes.
I would use a hard link to pin an exact same-filesystem artifact, a symlink for the movable current alias, and a real copy for independent retention. I would update current by creating a temporary symlink and atomically renaming it in the same directory. I would prove the result with device/inode, link count, readlink, a dangling-link access, and an open-descriptor test. If the path is untrusted, I would enforce no-symlink and directory-boundary rules during the open itself.”
Common Mistakes
- Calling the hard link a pointer to the original name → all hard links are peer directory entries
for one inode → describe names, inode identity, and link count.
- Saying deletion always destroys the file immediately → other names or open references may remain
→ trace both hard-link count and open descriptors.
- Treating a symlink as a stored inode reference → it stores a pathname that can later resolve
differently or fail → inspect the payload and resolution base.
- Comparing inode numbers without device identity → inode numbers are only filesystem-local →
compare device plus inode.
- Using a hard link across mounts or for a directory → Linux rejects those cases → **use a symlink
or a copy according to the required independence.**
- Moving a relative symlink without reevaluating it → its containing directory defines the base →
recompute or regenerate the target after relocation.
- Calling either link a backup → one shares the object and the other stores only a path → **create
an independently restorable copy.**
- Checking a path and opening it later → an attacker can swap a symlink between operations →
enforce traversal constraints atomically during open.
Follow-up Questions and Answers
Follow-up 1: Do hard links have separate permissions or owners?
No. Permissions, owner, size, and timestamps belong to the shared inode. Changing them through one hard link changes what every peer observes. Directory-entry names and their parent-directory permissions are separate; renaming or unlinking a name is governed by the containing directory.
Follow-up 2: Why does a relative symlink sometimes break after being moved?
Its payload is interpreted relative to the directory containing the symlink. Moving the link changes that base while preserving the stored string. An absolute symlink keeps one pathname but may be wrong inside a container, chroot, alternate mount, or another host. Choose after defining relocation needs.
Follow-up 3: Can rename replace current atomically across filesystems?
No. Linux rename returns EXDEV across mounted filesystems. Publish the completed target within the destination filesystem, create the temporary alias there, then rename that alias over current in the same directory. Define cleanup and recovery for any earlier copy phase.
Follow-up 4: Why does disk space remain used after the last pathname is deleted?
An open file description may still reference the inode. Locate the owning descriptor and process, then use the application's safe rotation or restart procedure. Space is reclaimed after the last name and last open reference disappear; removing the pathname alone proves only that name is gone.
Follow-up 5: How do stat, lstat, and readlink differ?
stat normally follows the final symlink and reports the target. lstat reports the symlink object. readlink returns its stored pathname without resolving it. Use all three concepts when proving both the alias and the object it currently reaches.
Follow-up 6: How would you prevent a symlink race in an upload directory?
Open relative to a trusted directory descriptor and make the lookup enforce that it stays beneath that directory and does not follow forbidden symlinks. Then validate the returned descriptor with descriptor- based operations. A pathname check followed by a separate open leaves a replacement window.