[pacman-dev] difficult symlink "puzzle"
Andrew Fyfe
andrew at neptune-one.net
Tue Jul 3 11:14:37 EDT 2007
Well this is how dpkg does it (src/processarc.c:471)
/*
* Now we unpack the archive, backing things up as we go.
* For each file, we check to see if it already exists.
* There are several possibilities:
* + We are trying to install a non-directory ...
* - It doesn't exist. In this case we simply extract it.
* - It is a plain file, device, symlink, &c. We do an `atomic
* overwrite' using link() and rename(), but leave a backup copy.
* Later, when we delete the backup, we remove it from any other
* packages' lists.
* - It is a directory. In this case it depends on whether we're
* trying to install a symlink or something else.
* = If we're not trying to install a symlink we move the directory
* aside and extract the node. Later, when we recursively remove
* the backed-up directory, we remove it from any other packages'
* lists.
* = If we are trying to install a symlink we do nothing - ie,
* dpkg will never replace a directory tree with a symlink. This
* is to avoid embarrassing effects such as replacing a directory
* tree with a link to a link to the original directory tree.
* + We are trying to install a directory ...
* - It doesn't exist. We create it with the appropriate modes.
* - It exists as a directory or a symlink to one. We do nothing.
* - It is a plain file or a symlink (other than to a directory).
* We move it aside and create the directory. Later, when we
* delete the backup, we remove it from any other packages' lists.
*
* Install non-dir Install symlink Install dir
* Exists not X X X
* File/node/symlink LXR LXR BXR
* Directory BXR - -
*
* X: extract file/node/link/directory
* LX: atomic overwrite leaving backup
* B: ordinary backup
* R: later remove from other packages' lists
* -: do nothing
*
* After we've done this we go through the remaining things in the
* lists of packages we're trying to remove (including the old
* version of the current package). This happens in reverse order,
* so that we process files before the directories (or symlinks-to-
* directories) containing them.
* + If the thing is a conffile then we leave it alone for the purge
* operation.
* + Otherwise, there are several possibilities too:
* - The listed thing does not exist. We ignore it.
* - The listed thing is a directory or a symlink to a directory.
* We delete it only if it isn't listed in any other package.
* - The listed thing is not a directory, but was part of the package
* that was upgraded, we check to make sure the files aren't the
* same ones from the old package by checking dev/inode
* - The listed thing is not a directory or a symlink to one (ie,
* it's a plain file, device, pipe, &c, or a symlink to one, or a
* dangling symlink). We delete it.
* The removed packages' list becomes empty (of course, the new
* version of the package we're installing will have a new list,
* which replaces the old version's list).
*
* If at any stage we remove a file from a package's list, and the
* package isn't one we're already processing, and the package's
* list becomes empty as a result, we `vanish' the package. This
* means that we run its postrm with the `disappear' argument, and
* put the package in the `not-installed' state. If it had any
* conffiles, their hashes and ownership will have been transferred
* already, so we just ignore those and forget about them from the
* point of view of the disappearing package.
*
* NOTE THAT THE OLD POSTRM IS RUN AFTER THE NEW PREINST, since the
* files get replaced `as we go'.
*/
Andrew
More information about the pacman-dev
mailing list