6 (see http://www.linuxfromscratch.org/hints/downloads/files/LICENSES/gpl-2.txt)
8 SYNOPSIS: A UnionFS-based package management system
11 UnionFS is a kernel patch that allows one to merge the contents of many
12 disparate directories so they all appear as a single directory. This
13 functionality provides a basis for a minimal, yet effective,
14 package manager. This approach appeals to those who want a more rational
15 and organized directory structure.
18 1) http://www.linuxfromscratch.org/hints/downloads/files/ATTACHMENTS/pkg_unionfs/pkgs
19 2) http://www.linuxfromscratch.org/hints/downloads/files/ATTACHMENTS/pkg_unionfs/manager
22 Completion of the "Constructing a Temporary System" chapter in the LFS book.
28 UnionFS is a kernel patch that provides the ability to merge many directories
29 such that their contents appear together in one directory. The package manager
30 proposed here uses this ability to merge the contents of various packages so
31 directories like /bin and /lib have the appearance of containing all loaded
34 This type of package management is inspired by GoboLinux's unique take
35 on the archaic Unix directory structures*. Instead of installing all packages
36 into the /usr directory whose contents can become quite unwieldy, packages
37 are installed into their own directories. GoboLinux's package manager
38 creates symbolic links in the necessary directories in order to give the
39 appearance that the package is installed in traditional directories.
40 A package can be removed by deleting the directory a package was
41 installed in, causing the symbolic links pointing to that package to become
42 invalidated. GoboLinux demonstrates that a fully-functional GNU/Linux system
43 does not require packages to be installed in traditional directories.
45 * http://www.gobolinux.org/?page=k5
47 Section I.a. Advantages
49 The primary benefit of this type of package manager is simplicity. It only
50 requires a patched kernel, a startup script for setting up the UnionFS mount
51 points, and a script for loading and unloading packages. This approach refrains
52 from the canonical black-box style of package management where
53 the user issues specialized commands to a complex package manager consisting of
54 several tiers of programs and book-keeping files to install or
55 uninstall a pacakge. Here, the user issues commands to a script that,
56 in turn, merely issues mount commands to UnionFS.
58 There are some possible benefits of a simpler directory structure:
60 * The contents of /bin, /sbin, and /lib merely contain a few files necessary
63 * There is no chance an uninstalled package can leave behind stray files in
66 * It is convenient to tuck away special libraries and files needed by a
67 specific package but need to be kept hidden from the rest of the system.
69 * It is easier to find configuration files for a package. Instead of hunting
70 down a configuration file in /etc or /usr/share that contains files from
71 all packages, one can browse through a package's directory to look for
74 This approach is flexible in that determining what constitutes a package is
75 up to the user. One can combine several different packages together
76 into one super-package so their contents are loaded together. This is
77 useful for packages like X.Org, which consists of hundreds subpackages.
79 A secondary benefit of this approach is version management. In some cases it
80 is useful to have multiple versions of the same package installed at the same
81 time. One can try out a newer version of a package to see if it
82 is satisfactory without affecting the installation of an older version.
84 Section I.b. Disadvantages
86 There are several disadvantages to this type of package management.
88 First, this approach imposes a longer startup time. At system boot, necessary
89 packages must be loaded before the system can be fully functional. This
90 disadvantage is not a serious setback for most users, since loading one hundred
91 and thirty packages takes about four seconds on a relatively new computer.
93 Second, a package cannot be unloaded if its contents are in use. This
94 limitation primarily affects packages consisting of libraries. Running programs
95 must be terminated first in order to unload a package they depend on.
97 Section I.c. How It Works
99 Assume UnionFS is installed and is working. To demonstrate UnionFS, assume there
100 are the directories a, b, and c. a contains the file 1, b contains file 2, and
116 The following command is then issued:
117 # mount -t unionfs -o "ro,dirs=a:b" none c
118 This has the effect of performing a union operation on the contents of a and b
119 and storing them in c.
121 This produces the following result:
139 This functionality is the basis for the package manager. Assume there is a
140 binary in directory /pkgs/sed/4.1.5/bin/sed. The package manager
141 notices there is a bin directory at /pkgs/sed/4.1.5/bin. It determines that this
142 directory's contents should be mapped to the directory /bin.
143 The package manager issues mount commands to UnionFS. After the package is
144 loaded, /pkgs/sed/4.1.5/bin/sed appears as /bin/sed. A user of the system can
145 use the sed program as if it exists in /bin/sed. When a package is unloaded,
146 sed is no longer in /bin, yet remains as /pkgs/sed/4.1.5/bin/sed.
148 Section I.d. Some Preliminary Jargon
150 While jargon and specialized lexicon should be rigorously eschewed*, some
151 preliminary terminology is presented here to reduce the verbosity of this
152 document or to clarify potentially ambiguous phrases.
154 * Installing a package:
155 The programs, libraries, and configuration files are built and copied to
156 a designated directory for a package. This does not mean the package
157 is available and can be used by the system. Installation is not handled
158 in any way by the package manager proposed here.
161 The programs, libraries, and configurations of a package are made
162 available to the system. In other words, the package manager looks at a
163 package's contents and issues mounts to UnionFS so the appropriate files
164 will be presented in /bin, /lib, /etc, and so on. A package must be
165 installed before it can be loaded.
167 * Unloading a package:
168 The opposite of loading, where the contents of a package are made
169 unavailable to the system. A package's contents do not appear in /bin,
170 /lib, /etc, and so on, yet remain in its respective package directory.
172 * Uninstalling a package:
173 The opposite of installing, where the package's files are completely
174 removed from disk. A package, if it has been loaded, must be unloaded
175 first before it can be removed. Uninstalling is not handled by the
176 package manager, since rm is sufficient.
179 This is a directory, like bin, share, or lib, in a package's
180 directory. Its contents, along with other packages' source directories,
181 are the source for directories that are a target for UnionFS, like
182 /bin, /usr/share, or /lib. In the example demonstrated in Section I.c,
183 /pkgs/sed/4.1.5/bin is a source directory.
186 This is a directory, like /bin or /lib. Its contents are artificially
187 constructed by UnionFS. In the example demonstrated in Section I.c,
188 /bin is the target directory of the source directory /pkgs/sed/4.1.5/bin.
190 * See Orwell, G. "Politics of the English Language." 1946.
191 http://www.mtholyoke.edu/acad/intrel/orwell46.htm
193 Part II. Installation
195 Setting up the package manager is discussed here and should be done
196 after the chapter "Constructing a Temporary System" is completed.
198 Section II.a. The Directory Structure
200 The following directory structure is assumed in this
201 document and provided scripts. It is perfectly reasonable to change this
202 structure to one's tastes.
204 1) The general directory containing all packages is stored in /pkgs.
206 2) A package is installed in a subdirectory of /pkgs. For example, the
207 sed package is installed in /pkgs/sed.
209 3) A package's version is a subdirectory in the package's directory. For
210 example, if sed has the version 4.1.5, it is installed in /pkgs/sed/4.1.5.
211 Since each package version has its own directory, multiple versions of
212 the same package can be installed.
214 4) The target directories:
225 /usr/bin should link to /bin, and /usr/lib should link to /lib.
226 If one is using a 64-bit machine, the additional /lib64 and /usr/lib64
227 links should point to /lib.
229 Section II.b. Installing Packages
231 After the chapter "Constructing a Temporary System," the LFS book describes
232 steps for the actual installation of packages in the chapter
233 "Installing Basic System Software." The LFS book relies on a package's Makefile
234 to determine the location--typically /usr--where the package is to be
235 installed. Because packages are installed in non-standard locations, this
236 default behavior must be superseded. One can install all packages in the LFS
237 and BLFS books in their own directories, including fundamental packages like
240 Many packages only require the DESTDIR parameter be passed to the Makefile
241 when issuing the install command*. Here is an example of Bison-2.3 to
242 illustrate the process of installing a typical package.
244 1) Create the necessary directories:
245 mkdir -pv /pkgs/bison/2.3
247 2) Follow the steps provided by LFS, except for "make install":
248 ./configure --prefix=/usr
249 echo '#define YYENABLE_NLS 1' >> config.h
253 3) Run "make install" with the DESTDIR parameter:
254 make DESTDIR=/pkgs/bison/2.3 install
256 Most packages will follow this format. Unfortunately, not all packages
257 use the DESTDIR parameter for installation. Some packages require
258 the configure script's --prefix parameter to determine where the package is to
259 be installed. One must look at the README or INSTALL files provided with a
260 package to determine this.
262 Typically, if a package does not have a configure script,
263 the DESTDIR parameter will probably not work, and one must consult the
264 provided documentation to determine how to install a package in a non-standard
267 Some packages require the --sysconfdir parameter for the configure script.
268 The LFS book specifies this should be /etc. Since the package is to be
269 installed in a non-standard location, this should be set to
270 /pkgs/name/version/etc.
272 * See the section "Package Management" in the LFS book for further discussion.
273 http://www.linuxfromscratch.org/lfs/view/development/chapter06/pkgmgt.html
275 Section II.c. Setting up the Kernel
277 By now, all the packages specified in the chapter "Installing Basic System
278 Software" should be installed in their own directories.
280 In the chapter "Making the LFS System Bootable," the LFS book describes
281 how to compile and install the kernel. In order to add the UnionFS capability
282 to the Linux kernel, one must patch the kernel source code before compiling
283 it. Here are the steps to setting up the patch.
285 1) Download a kernel patch from:
286 http://www.filesystems.org/project-unionfs.html
289 2) Download the corresponding kernel version. The file name of the kernel
290 patch may be something like "unionfs-2.5_for_2.6.26.5.diff.gz". Therefore,
291 download the kernel version 2.6.26.5. Unpack the kernel source code.
293 4) Apply the kernel patch by first entering the kernel source code directory
295 patch -Np1 -i /path/to/unionfs/patch.diff
297 5) Follow the steps in the LFS book for setting up a menu configuration for
298 the kernel. While in the configuration program, ensure the UnionFS
299 module is built. The option can be found in
300 Drivers > Filesystems > Layered Filesystems. UnionFS can be built as a
301 module or can be statically linked with the kernel.
303 6) Build and install the kernel as specified in the chapter "Making the LFS
306 Section II.d. Setting up the Scripts
308 After finishing the "Setting up System Bootscripts" and "Making the LFS System
309 Bootable" chapters, one must setup the necessary scripts for package
310 management before restarting*. There are two attached scripts, pkgs and manager.
312 The manager script issues mount commands to UnionFS. This script can be
313 copied into /pkgs. This script will be discussed in depth later.
315 pkgs is an init script that (a) sets up all the mount points necessary for
316 package management and (b) loads all the necessary packages for system startup.
317 This script should be executed as early in the bootscripts as possible.
318 If UnionFS is built as a module, the script should be
319 executed after the module has been loaded. Otherwise, this script
320 should be executed first. To install this script assuming one is using LFS's
321 boot scripts, one should:
323 1) Copy pkgs into /etc/rc.d/init.d.
325 2) Make a link of pkgs to /etc/rc.sysinit:
326 a) If UnionFS was built as a module:
328 Have the script be executed after the necessary modules have been
330 (i) ln -sv /etc/rc.d/init.d/pkgs /etc/rc.d/rc.sysinit/S06pkgs
332 Add UnionFS to /etc/sysconfig/modules in order to have the UnionFS
333 module be loaded at startup:
334 (ii) echo unionfs >> /etc/sysconfig/modules
336 b) If UnionFS was built into the kernel:
338 Lower the execution order of mountkernfs:
339 (i) mv -v /etc/rc.d/rc.sysinit/S00mountkernfs \
340 /etc/rc.d/rc.sysinit/S01mountkernfs
342 Have the pkgs script to be executed first:
343 (ii) ln -sv /etc/rc.d/init.d/pkgs /etc/rc.d/rc.sysinit/S00pkgs
345 3) Create the pkgs_startup file:
346 This file is used by pkgs to determine what packages to load at
347 startup. This file is akin to /etc/sysconfig/modules. Each line in this
348 file has the following format:
349 package_name <SPACE> package_version
351 This file is typically located in /etc/sysconfig. If one wishes to use
352 another location, change the CONFIG_FILE variable in the pkgs script to
353 the location of this file.
355 This file should contain all the packages necessary for the init scripts
356 that follow the pkgs script, like sysklogd and udev, in order for
357 proper system startup. If one wishes to load all available packages
358 at system startup, type:
359 /pkgs/manager list > /etc/sysconfig/pkgs_startup
361 If the manager script was not copied into /pkgs, open the pkgs script and
362 look for the PKG_LOADER variable. This variable should be changed to the
363 location of the manager script.
365 * In fact, not setting up the package manager will produce a non-bootable
366 system because packages are installed in non-standard locations.
368 Section II.e. Creating the Necessary Symbolic Links
370 After the scripts have been installed, a few symbolic links must be created
371 for proper system startup, since essential programs like init are not installed
372 in standard locations.
374 The general process for creating the symbolic links is as follows.
375 All the programs (1) that are to be executed after the kernel has finished
376 initializing and before the pkgs script can be executed and (2) the libraries
377 these programs depend on must have symbolic links in the /bin, /sbin, or
378 /lib directories. The pkgs script calls the manager script to load the
379 packages, so all programs required by manager and the libraries they depend on
380 must also have symbolic links.
382 Subsection II.e.1. Program Symbolic Links
384 Here is a list of programs whose symbolic links are typically required.
385 Some systems may require additional programs. Those denoted by an
386 asterisk are mandatory.
388 *1) init -- this program is executed by the kernel after initialization
389 The kernel expects init to be in /sbin/init.
390 *2) bash -- this is executed by init to run the init scripts
391 *3) echo -- this is used by all init scripts to display messages
392 *4) ls -- used by the manager script
393 *5) find -- used by the manager script
394 *6) sed -- used by the manager script
395 *7) mount -- this is used by the mountkernfs, pkgs, and manager scripts
396 8) mountpoint -- this is used by the mountkernfs script
397 9) modprobe -- this is used by the modules script
398 10) dmesg -- this is used by the consolelog script
400 To create the symbolic link for a program, one must locate the program first.
401 This can be achieved by typing:
402 find /pkgs -name program_name
404 Next, the symbolic link can be created:
405 ln -sv /path/to/program_name /bin
407 ln -sv /path/to/program_name /sbin
409 For example, if one wants to create the symbolic link for init, one must first
411 find /pkgs -name init
413 If find produces the following result:
414 /pkgs/sysvinit/2.86/sbin/init
416 The symbolic link can then be created by typing:
417 ln -sv /pkgs/sysvinit/2.86/sbin/init /sbin
419 Subsection II.e.2. Library Symbolic Links
421 All of the above programs depend on shared libraries. It is for this reason
422 links to the required shared libraries must be in /lib. To determine the
423 required libraries, type:
426 Next, search for the location of the library by typing:
427 find /pkgs -name library_name
429 Finally, create the symbolic link in /lib if one does not exist:
430 ln -sv /path/to/library /lib
432 For example, if one wishes to create the symbolic links for bash, one must
433 first determine the libraries it requires:
436 The ldd program may produce the following output:
437 linux-vdso.so.1 => (0x00007ffff6bfe000)
438 libreadline.so.5 => /lib/libreadline.so.5 (0x00007fc8ee804000)
439 libhistory.so.5 => /lib/libhistory.so.5 (0x00007fc8ee6fc000)
440 libncursesw.so.5 => /lib/libncursesw.so.5 (0x00007fc8ee596000)
441 libdl.so.2 => /lib/libdl.so.2 (0x00007fc8ee492000)
442 libc.so.6 => /lib/libc.so.6 (0x00007fc8ee258000)
443 /lib64/ld-linux-x86-64.so.2 (0x00007fc8ee941000)
445 For each of the files listed, a symbolic link should be created.
446 "linux-vdso.so.1" is skipped because it does not point to an
447 actual file. The library "libhistory.so.5" can be located by typing:
448 find /pkgs -name libhistory.so.5
450 If find produces the result:
451 /pkgs/readline/5.2/lib/libhistory.so.5
453 The symbolic link can be created by typing:
454 ln -sv /pkgs/readline/5.2/lib/libhistory.so.5 /lib
456 Subsection II.e.3. Troubleshooting
458 During system startup, if the kernel, init, or an init script reports it cannot
459 find a certain program, there are two possible reasons: (a) a valid symbolic
460 link to the program is not in /bin or /sbin, or (b) all the necessary libraries
461 for the program do not have valid symbolic links in /lib.
463 Part III. Using the Package Manager
465 Now that installation is completed, one can boot into the LFS system. This
466 section describes how to use the package manager.
468 Section III.a. Loading and Unloading
470 The manager script does the grunt work for setting up the target directories.
471 It provides two functionalities: (1) loading a package and (2) unloading a
472 package. Loading and unloading can be done as follows:
474 /pkgs/manager load package-name [package-version]
476 For example, if one wishes to load the package sed, version 4.1.5, one types:
478 /pkgs/manager load sed 4.1.5
480 Specifying the package version is optional. If it is omitted, the first version
481 manager finds is used. Unloading the package follows the same format:
483 /pkgs/manager unload package-name [package-version]
485 To unload sed, version 4.1.5, type:
487 /pkgs/manager unload sed 4.1.5
489 The package version must match the same version used to load the package.
491 Section III.b. Upgrading a package
493 To upgrade a package, unload the package version that is already loaded, and
494 load the new package version.
496 Suppose there are two versions of the fluxbox package installed:
497 $ /pkgs/manager list fluxbox
500 To switch from 0.9.16 to 1.0.0, one types:
501 # /pkgs/manager unload fluxbox 0.9.16
502 # /pkgs/manager load fluxbox 1.0.0
504 Section III.c. Diagnostics
506 The manager script provides a few diagnostic tools:
508 * To list all of the packages available and their versions, type:
511 * To list all the available versions of a package, type:
512 /pkgs/manager list package-name
514 * To check that the correct directories are being unionized, type:
515 /pkgs/manager test package-name [package_version]
517 Section III.d. Limitations
519 One of the goals of the package manager is minimalism. Features
520 found in most package managers are not available in the one presented here
521 because of this choice. However, the limitations listed here can be overcome
522 by extending the functionality of the package manager. The scripts are not
523 designed to be a byzantine of code, and they contain comments to ease hacking.
525 The manager script cannot determine what packages are loaded. There are
526 no checks made when a package is loaded. Issuing a load command to a package
527 already loaded has no effect. Unloading a package that is not loaded will result
528 in an error from UnionFS.
530 If a package depends on another, it is up to the user to load that
531 package. No dependency calculations are performed by the package manager.
533 Section III.d. When to Reload a Package
535 If a package's contents are modified, there are certain situations where
536 reloading a package is necessary for changes to take effect.
538 Adding files or directories to a source directory like etc or bin does not
539 require a reload. Assume there is a package samba, version 2.10.13. There is
540 the directory share in the package. If a file called mynotes.txt is added to
541 the package's share directory, reloading the package will not be needed, since
542 mynotes.txt will immediately appear in /usr/share.
544 Adding a source directory where one did not exist before
545 requires a reload. Assume there is the package gtk with version 2.10.13.
546 This package only contains the directory usr; in other words, the directory
547 /pkgs/gtk/2.10.13 only contains the directory usr.
548 If an etc directory, which did not exist before, is created in
549 /pkgs/gtk/2.10.13, a reload is necessary.
551 Reloads can be accomplished by typing:
552 /pkgs/manager unload package-name package-version
553 /pkgs/manager load package-name package-version
555 To reload the gtk package with version 2.10.13, one types:
556 /pkgs/manager unload gtk 2.10.13
557 /pkgs/manager load gtk 2.10.13
559 Section III.e. Editing Files in a Package
561 When editing a file in a package, one should open the file from
562 the /pkgs directory, not from the target directory.
564 Suppose there is a file in /pkgs/x.org/7.2/etc/X11/x.org,
565 which also exists as /etc/X11/x.org. If one wishes to edit this file, it
566 should be opened from /pkgs/x.org/7.2/etc/X11/x.org, not /etc/X11/x.org.
567 Changes made to /pkgs/x.org/7.2/etc/X11/x.org will immediately become apparent
570 Even though they are technically the same file, if
571 /etc/X11/x.org is edited, UnionFS will physically create the directory
572 /etc/X11, save the changes made to /etc/X11/x.org, and delete
573 /pkgs/x.org/7.2/etc/X11/x.org. This behavior runs against the goal of
574 keeping files in separate directories as much as possible.
576 Section III.f. Uninstalling a package
578 To uninstall a package, (a) unload the package, then (b) delete the package
581 Part IV. Concluding Remarks
583 The goal of this document is to present an alternative package manager based
584 on UnionFS to the de-facto standard of black-box style package managers.
585 Users wishing for a higher degree of organization over files and directories
586 may find this type of package manager useful.
588 The ideas presented here can be extended, namely:
590 1. Other operating systems, like the BSDs, can also take advantage of this
591 type of package management. In fact, the BSD kernels have supported
592 union directories for many years.
594 2. The capabilities of the package manager can be improved by hacking the
595 manager script or write additional scripts that automate the
596 installation of packages.
598 Moreover, replacing the manager script with something in a different
599 scripting language may be better. Bash has been a difficult language for
600 the author, and rewriting the manager script in Python
601 would reduce the amount of code and make it cleaner. Adding functionality
602 to the package manager is probably much easier in Python than Bash.
604 3. Users can have personal packages in their home directories and can
605 load and unload them. This can be achieved by: (a) allowing mounting to
606 non-root users, (b) copying the manager script to the user's home
607 directory, and (c) modifying the script's "pkg_dir" and "target_dir"