posted by Thomas Leonard on Tue 16th Jan 2007 00:32 UTC

"Avoiding Conflicts, Dependencies"
Avoiding conflicts

In the GnuPG example above, the package manager is providing a valuable service, but the situation still isn't ideal. What I really want is to be able to install all the programs I need at the same time!

The general solution is to avoid having packages place files with short names (such as gimp) into shared directories (such as /usr/bin). If we allow this, then we can never permit users to install software (one user might install a different, or even malicious, binary with the same name).

Also, supporting multiple versions of programs and libraries can only be done with a great deal of effort. For example, we could name our binaries gimp-2.2 and gimp-2.4 to support different major versions of the Gimp, but we still can't install versions 2.2.1 and 2.2.2 at the same time and we'll need to upgrade our scripts and other programs every time a new version comes out.

We can simplify the problem a great deal by having a separate directory for each package, and keeping all of the package's files (those that came in the package, not documents created by the program when run) in that directory. This technique is used by many systems, including the Application directories of ROX and RISC OS, the Bundles of NEXTSTEP, Mac OS X and GNUstep, Klik's disk images, the Filesystem Hierarchy Standard's /opt, and Bernstein's /package. Then we just need a way to name the directories uniquely.

So how do we name these directories? We can let the user decide, if the user explicitly downloads the package from the web and unpacks it to their home directory. This still has a few problems. Sharing packages between users still doesn't work (unless the users trust each other), and programs can't find the libraries they need automatically, since they don't know where the user has put them.

One solution to the library problem is to have each package include all of its dependencies, and not distribute libraries as separate packages at all. This is the technique Klik uses, but it is inefficient since libraries are never shared, even when they could be, and upgrading a library requires upgrading every package that uses it. Security patches cause particular problems here. As the Klik site acknowledges, this is only suitable for a small number of packages. Bundling the libraries with the package is also inflexible; I can't choose to use a customised version of a library with all my programs.

A solution that works with separate libraries and allows sharing between users is to store each package's directory in a shared system directory, but using the globally unique name of that version of the package as the directory name. For example:

/opt/gimp.org-gimp-2.2.1/...
/opt/gimp.org-gimp-2.4.3/...
/opt/example.org-libfoo-1.0/...
/opt/demo.com-libfoo-1.0/...

Two further issues need to be solved for this to work. First, we need some way to allow programs to find their libraries, given that there may be several possible versions available at once. Secondly, if we allow users to install software then we need to make sure that a malicious user cannot install one program under another program's name. That is, if /opt/gimp.org-gimp-2.4.3 exists then it must never be anything except gimp version 2.4.3, as distributed by gimp.org. These issues are addressed in the following sections.

Dependencies

GNU Stow works by creating symlinks with the traditional short names pointing to the package directories (e.g. /usr/bin/gimp to /opt/gimp.org-gimp-2.4.3/bin/gimp). This simplifies package management somewhat, but doesn't help us directly. However, with a minor modification - storing the symlinks in users' home directories - we get the ability to share package data without having users' version choices interfere with each other.

So we might have ~alice/bin/gimp pointing to /opt/gimp.org-gimp-2.2.1/bin/gimp, while ~bob/bin/gimp points to /opt/gimp.org-gimp-2.4.3/bin/gimp. Alice and Bob can use whatever programs and libraries they want without affecting each other, but whenever they independently choose the same version of something they will share it automatically. If both users have a default policy of using the latest available version, sharing should be possible most of the time.

Continuing our example above, Alice can now run the new gnupg, while Bob continues to use user-mode-linux, since each has a different ~/lib/libreadline5.so symlink. That is, Alice can't break Bob's setup by upgrading gnupg. We can go further. We can have a different set of symlinks per user per program. Now a single user can use gnupg, user-mode-linux and plash at the same time:

Sharing dependencies where possible

When an updated version of user-mode-linux becomes available, we simply update the symlink, so that user-mode-linux and gnupg share the new version of the library, while plash continues with the older version.

In fact, we don't need to use symlinks at all. Zero Install instead sets environment variables pointing to the selected versions when the program is run, rather than creating huge numbers of symlinks, but the principle is the same.

Table of contents
  1. "Introduction, Use Cases, Traditional Distributions"
  2. "Naming, Conflicts"
  3. "Avoiding Conflicts, Dependencies"
  4. "Publishing Software, Sharing Installed Software"
  5. "Security"
  6. "Compiling, Converting Between Formats"
  7. "Summary"
e p (8)    76 Comment(s)

Technology White Papers

See More