6.6. Details of unpack phase of installation or upgrade

The procedure on installation/upgrade/overwrite/disappear (i.e., when running dpkg --unpack, or the unpack stage of dpkg --install) is as follows. 5 In each case, if a major error occurs (unless listed below) the actions are, in general, run backwards - this means that the maintainer scripts are run with different arguments in reverse order. These are the “error unwind” calls listed below.

  1. Notify the currently installed package:

    1. If a version of the package is already “Installed”, call

      1. old-prerm upgrade new-version
    2. If the script runs but exits with a non-zero exit status, dpkg will attempt:

      1. new-prerm failed-upgrade old-version

      If this works, the upgrade continues. If this does not work, the error unwind:

      1. old-postinst abort-upgrade new-version

      If this works, then the old-version is “Installed”, if not, the old version is in a “Half-Configured” state.

  2. If a “conflicting” package is being removed at the same time, or if any package will be broken (due to Breaks):

    1. If --auto-deconfigure is specified, call, for each package to be deconfigured due to Breaks:

      1. deconfigured's-prerm deconfigure \
      2. in-favour package-being-installed version

      Error unwind:

      1. deconfigured's-postinst abort-deconfigure \
      2. in-favour package-being-installed-but-failed version

      The deconfigured packages are marked as requiring configuration, so that if --install is used they will be configured again if possible.

    2. If any packages depended on a conflicting package being removed and --auto-deconfigure is specified, call, for each such package:

      1. deconfigured's-prerm deconfigure \
      2. in-favour package-being-installed version \
      3. removing conflicting-package version

      Error unwind:

      1. deconfigured's-postinst abort-deconfigure \
      2. in-favour package-being-installed-but-failed version \
      3. removing conflicting-package version

      The deconfigured packages are marked as requiring configuration, so that if --install is used they will be configured again if possible.

    3. To prepare for removal of each conflicting package, call:

      1. conflictor's-prerm remove \
      2. in-favour package new-version

      Error unwind:

      1. conflictor's-postinst abort-remove \
      2. in-favour package new-version
  3. Run the preinst of the new package:

    1. If the package is being upgraded, call:

      1. new-preinst upgrade old-version

      If this fails, we call:

      1. new-postrm abort-upgrade old-version
      1. If that works, then

        1. old-postinst abort-upgrade new-version

        is called. If this works, then the old version is in an “Installed” state, or else it is left in an “Unpacked” state.

      2. If it fails, then the old version is left in an “Half-Installed” state.

    2. Otherwise, if the package had some configuration files from a previous version installed (i.e., it is in the “Config-Files” state):

      1. new-preinst install old-version

      Error unwind:

      1. new-postrm abort-install old-version

      If this fails, the package is left in a “Half-Installed” state, which requires a reinstall. If it works, the packages is left in a “Config-Files” state.

    3. Otherwise (i.e., the package was completely purged):

      1. new-preinst install

      Error unwind:

      1. new-postrm abort-install

      If the error-unwind fails, the package is in a “Half-Installed” phase, and requires a reinstall. If the error unwind works, the package is in the “Not-Installed” state.

  4. The new package’s files are unpacked, overwriting any that may be on the system already, for example any from the old version of the same package or from another package. Backups of the old files are kept temporarily, and if anything goes wrong the package management system will attempt to put them back as part of the error unwind.

    It is an error for a package to contain files which are on the system in another package, unless Replaces is used (see Overwriting files and replacing packages - Replaces).

    It is a more serious error for a package to contain a plain file or other kind of non-directory where another package has a directory (again, unless Replaces is used). This error can be overridden if desired using --force-overwrite-dir, but this is not advisable.

    Packages which overwrite each other’s files produce behavior which, though deterministic, is hard for the system administrator to understand. It can easily lead to “missing” programs if, for example, a package is unpacked which overwrites a file from another package, and is then removed again. 6

    A directory will never be replaced by a symbolic link to a directory or vice versa; instead, the existing state (symlink or not) will be left alone and dpkg will follow the symlink if there is one.

  5. If the package is being upgraded:

    1. Call:

      1. old-postrm upgrade new-version
    2. If this fails, dpkg will attempt:

      1. new-postrm failed-upgrade old-version

      If this works, installation continues. If not, Error unwind:

      1. old-preinst abort-upgrade new-version

      If this fails, the old version is left in a “Half-Installed” state. If it works, dpkg now calls:

      1. new-postrm abort-upgrade old-version

      If this fails, the old version is left in a “Half-Installed” state. If it works, dpkg now calls:

      1. old-postinst abort-upgrade new-version

      If this fails, the old version is in an “Unpacked” state.

    This is the point of no return. If dpkg gets this far, it won’t back off past this point if an error occurs. This will leave the package in a fairly bad state, which will require a successful re-installation to clear up, but it’s when dpkg starts doing things that are irreversible.

  6. Any files which were in the old version of the package but not in the new are removed.

  7. The new file list replaces the old.

  8. The new maintainer scripts replace the old.

  9. Any packages all of whose files have been overwritten during the installation, and which aren’t required for dependencies, are considered to have been removed. For each such package

    1. dpkg calls:

      1. disappearer's-postrm disappear \
      2. overwriter overwriter-version
    2. The package’s maintainer scripts are removed.

    3. It is noted in the status database as being in a sane state, namely “Not-Installed” (any conffiles it may have are ignored, rather than being removed by dpkg). Note that disappearing packages do not have their prerm called, because dpkg doesn’t know in advance that the package is going to vanish.

  10. Any files in the package we’re unpacking that are also listed in the file lists of other packages are removed from those lists. (This will lobotomize the file list of the “conflicting” package if there is one.)

  11. The backup files made during installation, above, are deleted.

  12. The new package’s status is now sane, and recorded as “Unpacked”.

    Here is another point of no return: if the conflicting package’s removal fails we do not unwind the rest of the installation. The conflicting package is left in a half-removed limbo.

  13. If there was a conflicting package we go and do the removal actions (described below), starting with the removal of the conflicting package’s files (any that are also in the package being unpacked have already been removed from the conflicting package’s file list, and so do not get removed now).