Updated hint
[linux_from_scratch_hints.git] / pkg_unionfs.txt
blob5a263a5b542cfa9cccda51b7729a57a84884152e
1 AUTHOR: Samad Lotia
3 DATE: 2008-10-21
5 LICENSE: GNU GPL 2
6 (see http://www.linuxfromscratch.org/hints/downloads/files/LICENSES/gpl-2.txt)
8 SYNOPSIS: A UnionFS-based package management system
10 DESCRIPTION:
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.
17 ATTACHMENTS:
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
21 PREREQUISITES:
22   Completion of the "Constructing a Temporary System" chapter in the LFS book.
24 HINT:
26 Part I. Introduction
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
32 packages.
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
61     for init scripts.
63   * There is no chance an uninstalled package can leave behind stray files in
64     /etc or /usr/share.
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
72     a file.
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
101 c is empty.
103   $ ls
104   a b c
105   $ ls -a a
106   . .. 1
107   $ cat a/1
108   one
109   $ ls -a b
110   . .. 2
111   $ cat b/2
112   two
113   $ ls -a c
114   . ..
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:
122   $ ls
123   a b c
124   $ ls -a a
125   . .. 1
126   $ cat a/1
127   one
128   $ ls -a b
129   . .. 2
130   $ cat b/2
131   two
132   $ ls -a c
133   . .. 1 2
134   $ cat c/1
135   one
136   $ cat c/2
137   two
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.
160  * Loading a package:
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.
178   * Source directory:
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.
184   
185   * Target 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:
215        * /bin,
216        * /etc,
217        * /lib,
218        * /var,
219        * /usr/share,
220        * /usr/man,
221        * /usr/include,
222        * and /usr/info
223      should be created.
224      
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
238 glibc and sysvinit.
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
250        make
251        make check
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
265 location.
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
287      Unpack the patch.
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
294      and then typing:
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
304      System Bootable."
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
329          loaded:
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
406     or
407   ln -sv /path/to/program_name /sbin
409 For example, if one wants to create the symbolic link for init, one must first
410 locate it by typing:
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:
424   ldd /path/to/program
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:
434   ldd /bin/bash
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
498   0.9.16 1.0.0
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:
509       /pkgs/manager list
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
568 in /etc/X11/x.org.
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
579 directory.
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.
597      
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"
608      variables.
610 CHANGELOG:
611   [2008-10-30]
612     * Hint created.