Symbolic links need to be modified atomically. If you're halfway through writing them, they won't work.
The content of a symbolic link is pretty small (at most 4095 characters on Linux: the maximum length of a path to a file), so there would be little point in editing part of a symbolic link at the kernel level. Therefore the kernel does not offer any interface to edit a symbolic link, only an interface to create a new one, the symlink
system call (plus the generic interface unlink
to remove any file).
The symlink
system call only creates a new symbolic link, it does not remove any existing file. This is annoying, but consistent with other system calls to create files such as open
(which can create a new file or truncate an existing file, but not replace an existing file by a newly-created file) and mkdir
.
In the shell, as you've discovered, while you can't replace a symbolic link atomically with the ln
command (ln -sf
unlinks the previous file then creates the symbolic link), you can do it by first creating a symbolic link under a temporary name and then moving it into place.
tmp=$(TMPDIR=$(dirname -- "$link") mktemp)
ln -sf -- "$target" "$tmp"
mv -f "$tmp" "$link"