Author: robert Date: 2008-11-17 13:03:07 -0700 (Mon, 17 Nov 2008) New Revision: 1093
Added: trunk/ATTACHMENTS/pkg_unionfs/ trunk/ATTACHMENTS/pkg_unionfs/manager trunk/ATTACHMENTS/pkg_unionfs/pkgs trunk/pkg_unionfs.txt Log: Added pkg_unionfs hint and attachments. Added: trunk/ATTACHMENTS/pkg_unionfs/manager =================================================================== --- trunk/ATTACHMENTS/pkg_unionfs/manager (rev 0) +++ trunk/ATTACHMENTS/pkg_unionfs/manager 2008-11-17 20:03:07 UTC (rev 1093) @@ -0,0 +1,236 @@ +#!/bin/sh + +# The "pkg_dir" variable points to the directory containing the packages. +# This path must be absolute. +pkg_dir="/pkgs" + +# The "target_dir" variable points to the directory where the target +# directories are located. This path must be absolute. +target_dir="/" + + +command="${1}" +pkg_name="${2}" +pkg_version="${3}" + +# Unfortunately, bash does not support map or dictionary data structures. +# The goal of map_dir is to simulate this data structure. Given a source +# directory, it will map it to a target directory. +# +# Input: ${1} - the path of the source directory; the path cannot be absolute +# but must be relative to the package's directory. +# Result: the target directory if the source directory has a target, otherwise +# an empty string. +function map_dir () +{ + dir_entries () + { + # target-point source-dir + echo "${target_dir}/bin bin" + echo "${target_dir}/bin jre/bin" + echo "${target_dir}/bin usr/bin" + echo "${target_dir}/bin usr/local/bin" + + echo "${target_dir}/sbin sbin" + echo "${target_dir}/sbin usr/sbin" + echo "${target_dir}/sbin usr/local/sbin" + + echo "${target_dir}/lib lib" + echo "${target_dir}/lib jre/lib" + echo "${target_dir}/lib usr/lib" + echo "${target_dir}/lib usr/local/lib" + echo "${target_dir}/lib lib64" + echo "${target_dir}/lib usr/lib64" + echo "${target_dir}/lib usr/local/lib64" + + echo "${target_dir}/usr/include include" + echo "${target_dir}/usr/include usr/include" + echo "${target_dir}/usr/include usr/local/include" + + echo "${target_dir}/usr/share share" + echo "${target_dir}/usr/share usr/share" + echo "${target_dir}/usr/share usr/local/share" + + echo "${target_dir}/usr/man man" + echo "${target_dir}/usr/man usr/man" + echo "${target_dir}/usr/man usr/share/man" + echo "${target_dir}/usr/man usr/local/share/man" + + echo "${target_dir}/etc etc" + echo "${target_dir}/var var" + } + + ( dir_entries ) | while read mount_point source_dir; do + if [ "${source_dir}" == "${1}" ]; then + echo "${mount_point}" + exit 0 + fi + done + echo +} + +function print_usage() +{ + echo "Usage: ${0} <command> <parameters>" + echo "Commands:" + echo " list" + echo " list all packages" + echo " list package-name" + echo " list versions of specified package" + echo " load package-name [package-version]" + echo " load a package" + echo " unload package-name" + echo " unload a package" + echo " test package-name [package-version]" + echo " dump mount points of a package" +} + +# Find all the sub-directories in a package directory. The prefix of ./ is +# stripped off from all sub-directory paths returned by find. +# Input: ${1} - the package name +# ${2} - the package version +# Result: all of the sub-directories +function find_dirs() +{ + dir="${pkg_dir}/${1}/${2}/" + cd ${dir} + find . -maxdepth 3 -mindepth 1 -type d | sed 's/\.\///' +} + +# Checks the variable ${pkg_name} to see if the package name exists. +# It prints messages to standard error if the package is not found. +# Input: ${pkg_name} - the name of the package. +# Result: 0 if the package directory is found, 1 if not. +function check_pkg_name() +{ + if [ "${pkg_name}" == "" ]; then + echo "No package was specified" >&2 + exit 1 + elif [ ! -d "${pkg_dir}/${pkg_name}" ]; then + echo "Package \`${pkg_name}' does not exist" >&2 + potential_pkg_names="" + for potential_pkg_name in `${0} list`; do + matches=`echo ${potential_pkg_name} | grep ${pkg_name}` + if [ ! "${matches}" == "" ]; then + potential_pkg_names="${matches} ${potential_pkg_names}" + fi + done + if [ ! "${potential_pkg_names}" == "" ]; then + echo "Possible packages are: ${potential_pkg_names}" >&2 + fi + exit 1 + else + exit 0 + fi +} + +# Checks the package version in order to determine if it is valid. +# If ${pkg_version} is empty, the default package version is used instead. +# Input: ${pkg_version} - the package version to check +# Result: the package version to use. This can be different from the supplied +# ${pkg_version} if it is an empty string. +function check_pkg_version() +{ + if [ "${pkg_version}" == "" ]; then + cd "${pkg_dir}/${pkg_name}" + for version in `ls -r`; do pkg_version=${version}; done + if [ "${pkg_version}" == "" ]; then + echo "No package versions are available for package \`${pkg_name}'" >&2 + exit 1 + else + echo "No package version was specified for \`${pkg_name}'; defaulting to \`${pkg_version}'" >&2 + fi + else + if [ ! -d "${pkg_dir}/${pkg_name}/${pkg_version}" ]; then + echo "Version \`${pkg_version}' does not exist for package \`${pkg_name}'" >&2 + echo -n "Available versions are: " >&2 + ${0} list ${pkg_name} >&2 + exit 1 + fi + fi + echo "${pkg_version}" + exit 0 +} + +# Performs a supplied function on each directory returned by map_dir. +# On each directory returned, the function will be called with the parameters: +# ${1} set to the absolute path to the source directory, and ${2} set to +# the path to the target directory. +# Input: ${1} - the function name to execute +# ${2} - the package name +# ${3} - the package version +# Result: 0 if the supplied function succeeded for each directory, 1 otherwise. +function for_each_mapped_dir () +{ + for dir in `( find_dirs ${2} ${3} )`; do + dest=`( map_dir ${dir} )` + if [ "${dest}" != "" ]; then + ( "${1}" "${pkg_dir}/${2}/${3}/${dir}" "${dest}" ) + if [ ! $? -eq 0 ]; then exit 1; fi + fi + done +} + +case "${command}" in + list) + if [ "${pkg_name}" == "" ]; then + cd ${pkg_dir} + for pkg_name in *; do + if [ -d ${pkg_dir}/${pkg_name} ]; then + echo -n "${pkg_name} " + cd ${pkg_name} + for version in *; do + echo -n "${version} " + done + echo + cd .. + fi + done + echo + else + ( check_pkg_name ); if [ ! $? -eq 0 ]; then exit 1; fi + cd ${pkg_dir}/${pkg_name} + for version in *; do + echo -n "${version} " + done + echo + fi + ;; + load) + ( check_pkg_name ); if [ ! $? -eq 0 ]; then exit 1; fi + pkg_version=`( check_pkg_version )`; if [ ! $? -eq 0 ]; then exit 1; fi + do_load () + { + mount -n -t unionfs -o "remount,add=:${1}=rw" none "${2}" + } + ( for_each_mapped_dir "do_load" ${pkg_name} ${pkg_version} ) + exit ${?} + ;; + unload) + ( check_pkg_name ); if [ ! $? -eq 0 ]; then exit 1; fi + pkg_version=`( check_pkg_version )`; if [ ! $? -eq 0 ]; then exit 1; fi + do_unload () + { + mount -n -t unionfs -o "remount,del=${1}" none "${2}" + } + ( for_each_mapped_dir "do_unload" ${pkg_name} ${pkg_version} ) + exit ${?} + ;; + test) + ( check_pkg_name ); if [ ! $? -eq 0 ]; then exit 1; fi + pkg_version=`( check_pkg_version )`; if [ ! $? -eq 0 ]; then exit 1; fi + do_test () + { + echo ${2} \<== ${1} + } + ( for_each_mapped_dir "do_test" ${pkg_name} ${pkg_version} ) + exit $? + ;; + *) + if [ ! "${command}" == "" ]; then + echo "Command \`${command}' not understood" + fi + ( print_usage ) + exit 1 + ;; +esac Added: trunk/ATTACHMENTS/pkg_unionfs/pkgs =================================================================== --- trunk/ATTACHMENTS/pkg_unionfs/pkgs (rev 0) +++ trunk/ATTACHMENTS/pkg_unionfs/pkgs 2008-11-17 20:03:07 UTC (rev 1093) @@ -0,0 +1,67 @@ +#!/bin/sh + +CONFIG_FILE="/etc/sysconfig/pkgs_startup" +PKG_LOADER="/pkgs/manager" + +case "${1}" in + start) + # setup the union mounts before loading any packages + + echo -n "Setting up package management for directories:" + # mount read-only unions + for dir in /bin /sbin /lib /usr/include /usr/man /usr/share; do + echo -n " ${dir}" + mount -n -t unionfs -o "ro,dirs=$dir" none "$dir" + done + + # mount read-write unions + for dir in /etc /var; do + echo -n " ${dir}" + mount -n -t unionfs -o "rw,dirs=$dir" none "$dir" + done + echo + + # begin loading packages + + echo -n "Loading packages:" + if [ ! -r "${CONFIG_FILE}" ]; then + echo " \`${CONFIG_FILE}' not found" + exit 1 + fi + + while read pkg version; do + # ignore comments + case "$pkg" in + ""|"#"*) continue ;; + esac + + # load the package + ${PKG_LOADER} load ${pkg} ${version} + + # check the result of the package loader + if [ $? -eq 0 ]; then + echo -n " ${pkg}" + else + failed="${failed} ${pkg}" + fi + done < ${CONFIG_FILE} + echo + + if [ -n "${failed}" ]; then + echo "WARNING: Failed to load${failed}" + fi + ;; + not) + cd /pkgs + for pkg in *; do + result=`grep ${pkg} ${CONFIG_FILE}` + if [ "${result}" == "" ]; then + echo ${pkg} + fi + done + ;; + *) + echo "Usage: ${0} {start}" + exit 1 + ;; +esac Added: trunk/pkg_unionfs.txt =================================================================== --- trunk/pkg_unionfs.txt (rev 0) +++ trunk/pkg_unionfs.txt 2008-11-17 20:03:07 UTC (rev 1093) @@ -0,0 +1,612 @@ +AUTHOR: Samad Lotia + +DATE: 21 October, 2008 + +LICENSE: GNU GPL 2 +(see http://www.linuxfromscratch.org/hints/downloads/files/LICENSES/gpl-2.txt) + +SYNOPSIS: A UnionFS-based package management system + +DESCRIPTION: + UnionFS is a kernel patch that allows one to merge the contents of many + disparate directories so they all appear as a single directory. This + functionality provides a basis for a minimal, yet effective, + package manager. This approach appeals to those who want a more rational + and organized directory structure. + +ATTACHMENTS: + 1) http://www.linuxfromscratch.org/hints/downloads/files/ATTACHMENTS/pkg_unionfs/pkgs + 2) http://www.linuxfromscratch.org/hints/downloads/files/ATTACHMENTS/pkg_unionfs/manager + +PREREQUISITES: + Completion of the "Constructing a Temporary System" chapter in the LFS book. + +HINT: + +Part I. Introduction + +UnionFS is a kernel patch that provides the ability to merge many directories +such that their contents appear together in one directory. The package manager +proposed here uses this ability to merge the contents of various packages so +directories like /bin and /lib have the appearance of containing all loaded +packages. + +This type of package management is inspired by GoboLinux's unique take +on the archaic Unix directory structures*. Instead of installing all packages +into the /usr directory whose contents can become quite unwieldy, packages +are installed into their own directories. GoboLinux's package manager +creates symbolic links in the necessary directories in order to give the +appearance that the package is installed in traditional directories. +A package can be removed by deleting the directory a package was +installed in, causing the symbolic links pointing to that package to become +invalidated. GoboLinux demonstrates that a fully-functional GNU/Linux system +does not require packages to be installed in traditional directories. + +* http://www.gobolinux.org/?page=k5 + +Section I.a. Advantages + +The primary benefit of this type of package manager is simplicity. It only +requires a patched kernel, a startup script for setting up the UnionFS mount +points, and a script for loading and unloading packages. This approach refrains +from the canonical black-box style of package management where +the user issues specialized commands to a complex package manager consisting of +several tiers of programs and book-keeping files to install or +uninstall a pacakge. Here, the user issues commands to a script that, +in turn, merely issues mount commands to UnionFS. + +There are some possible benefits of a simpler directory structure: + + * The contents of /bin, /sbin, and /lib merely contain a few files necessary + for init scripts. + + * There is no chance an uninstalled package can leave behind stray files in + /etc or /usr/share. + + * It is convenient to tuck away special libraries and files needed by a + specific package but need to be kept hidden from the rest of the system. + + * It is easier to find configuration files for a package. Instead of hunting + down a configuration file in /etc or /usr/share that contains files from + all packages, one can browse through a package's directory to look for + a file. + +This approach is flexible in that determining what constitutes a package is +up to the user. One can combine several different packages together +into one super-package so their contents are loaded together. This is +useful for packages like X.Org, which consists of hundreds subpackages. + +A secondary benefit of this approach is version management. In some cases it +is useful to have multiple versions of the same package installed at the same +time. One can try out a newer version of a package to see if it +is satisfactory without affecting the installation of an older version. + +Section I.b. Disadvantages + +There are several disadvantages to this type of package management. + +First, this approach imposes a longer startup time. At system boot, necessary +packages must be loaded before the system can be fully functional. This +disadvantage is not a serious setback for most users, since loading one hundred +and thirty packages takes about four seconds on a relatively new computer. + +Second, a package cannot be unloaded if its contents are in use. This +limitation primarily affects packages consisting of libraries. Running programs +must be terminated first in order to unload a package they depend on. + +Section I.c. How It Works + +Assume UnionFS is installed and is working. To demonstrate UnionFS, assume there +are the directories a, b, and c. a contains the file 1, b contains file 2, and +c is empty. + + $ ls + a b c + $ ls -a a + . .. 1 + $ cat a/1 + one + $ ls -a b + . .. 2 + $ cat b/2 + two + $ ls -a c + . .. + +The following command is then issued: + # mount -t unionfs -o "ro,dirs=a:b" none c +This has the effect of performing a union operation on the contents of a and b +and storing them in c. + +This produces the following result: + $ ls + a b c + $ ls -a a + . .. 1 + $ cat a/1 + one + $ ls -a b + . .. 2 + $ cat b/2 + two + $ ls -a c + . .. 1 2 + $ cat c/1 + one + $ cat c/2 + two + +This functionality is the basis for the package manager. Assume there is a +binary in directory /pkgs/sed/4.1.5/bin/sed. The package manager +notices there is a bin directory at /pkgs/sed/4.1.5/bin. It determines that this +directory's contents should be mapped to the directory /bin. +The package manager issues mount commands to UnionFS. After the package is +loaded, /pkgs/sed/4.1.5/bin/sed appears as /bin/sed. A user of the system can +use the sed program as if it exists in /bin/sed. When a package is unloaded, +sed is no longer in /bin, yet remains as /pkgs/sed/4.1.5/bin/sed. + +Section I.d. Some Preliminary Jargon + +While jargon and specialized lexicon should be rigorously eschewed*, some +preliminary terminology is presented here to reduce the verbosity of this +document or to clarify potentially ambiguous phrases. + + * Installing a package: + The programs, libraries, and configuration files are built and copied to + a designated directory for a package. This does not mean the package + is available and can be used by the system. Installation is not handled + in any way by the package manager proposed here. + + * Loading a package: + The programs, libraries, and configurations of a package are made + available to the system. In other words, the package manager looks at a + package's contents and issues mounts to UnionFS so the appropriate files + will be presented in /bin, /lib, /etc, and so on. A package must be + installed before it can be loaded. + + * Unloading a package: + The opposite of loading, where the contents of a package are made + unavailable to the system. A package's contents do not appear in /bin, + /lib, /etc, and so on, yet remain in its respective package directory. + + * Uninstalling a package: + The opposite of installing, where the package's files are completely + removed from disk. A package, if it has been loaded, must be unloaded + first before it can be removed. Uninstalling is not handled by the + package manager, since rm is sufficient. + + * Source directory: + This is a directory, like bin, share, or lib, in a package's + directory. Its contents, along with other packages' source directories, + are the source for directories that are a target for UnionFS, like + /bin, /usr/share, or /lib. In the example demonstrated in Section I.c, + /pkgs/sed/4.1.5/bin is a source directory. + + * Target directory: + This is a directory, like /bin or /lib. Its contents are artificially + constructed by UnionFS. In the example demonstrated in Section I.c, + /bin is the target directory of the source directory /pkgs/sed/4.1.5/bin. + +* See Orwell, G. "Politics of the English Language." 1946. + http://www.mtholyoke.edu/acad/intrel/orwell46.htm + +Part II. Installation + +Setting up the package manager is discussed here and should be done +after the chapter "Constructing a Temporary System" is completed. + +Section II.a. The Directory Structure + +The following directory structure is assumed in this +document and provided scripts. It is perfectly reasonable to change this +structure to one's tastes. + + 1) The general directory containing all packages is stored in /pkgs. + + 2) A package is installed in a subdirectory of /pkgs. For example, the + sed package is installed in /pkgs/sed. + + 3) A package's version is a subdirectory in the package's directory. For + example, if sed has the version 4.1.5, it is installed in /pkgs/sed/4.1.5. + Since each package version has its own directory, multiple versions of + the same package can be installed. + + 4) The target directories: + * /bin, + * /etc, + * /lib, + * /var, + * /usr/share, + * /usr/man, + * /usr/include, + * and /usr/info + should be created. + + /usr/bin should link to /bin, and /usr/lib should link to /lib. + If one is using a 64-bit machine, the additional /lib64 and /usr/lib64 + links should point to /lib. + +Section II.b. Installing Packages + +After the chapter "Constructing a Temporary System," the LFS book describes +steps for the actual installation of packages in the chapter +"Installing Basic System Software." The LFS book relies on a package's Makefile +to determine the location--typically /usr--where the package is to be +installed. Because packages are installed in non-standard locations, this +default behavior must be superseded. One can install all packages in the LFS +and BLFS books in their own directories, including fundamental packages like +glibc and sysvinit. + +Many packages only require the DESTDIR parameter be passed to the Makefile +when issuing the install command*. Here is an example of Bison-2.3 to +illustrate the process of installing a typical package. + + 1) Create the necessary directories: + mkdir -pv /pkgs/bison/2.3 + + 2) Follow the steps provided by LFS, except for "make install": + ./configure --prefix=/usr + echo '#define YYENABLE_NLS 1' >> config.h + make + make check + + 3) Run "make install" with the DESTDIR parameter: + make DESTDIR=/pkgs/bison/2.3 install + +Most packages will follow this format. Unfortunately, not all packages +use the DESTDIR parameter for installation. Some packages require +the configure script's --prefix parameter to determine where the package is to +be installed. One must look at the README or INSTALL files provided with a +package to determine this. + +Typically, if a package does not have a configure script, +the DESTDIR parameter will probably not work, and one must consult the +provided documentation to determine how to install a package in a non-standard +location. + +Some packages require the --sysconfdir parameter for the configure script. +The LFS book specifies this should be /etc. Since the package is to be +installed in a non-standard location, this should be set to +/pkgs/name/version/etc. + +* See the section "Package Management" in the LFS book for further discussion. + http://www.linuxfromscratch.org/lfs/view/development/chapter06/pkgmgt.html + +Section II.c. Setting up the Kernel + +By now, all the packages specified in the chapter "Installing Basic System +Software" should be installed in their own directories. + +In the chapter "Making the LFS System Bootable," the LFS book describes +how to compile and install the kernel. In order to add the UnionFS capability +to the Linux kernel, one must patch the kernel source code before compiling +it. Here are the steps to setting up the patch. + + 1) Download a kernel patch from: + http://www.filesystems.org/project-unionfs.html + Unpack the patch. + + 2) Download the corresponding kernel version. The file name of the kernel + patch may be something like "unionfs-2.5_for_2.6.26.5.diff.gz". Therefore, + download the kernel version 2.6.26.5. Unpack the kernel source code. + + 4) Apply the kernel patch by first entering the kernel source code directory + and then typing: + patch -Np1 -i /path/to/unionfs/patch.diff + + 5) Follow the steps in the LFS book for setting up a menu configuration for + the kernel. While in the configuration program, ensure the UnionFS + module is built. The option can be found in + Drivers > Filesystems > Layered Filesystems. UnionFS can be built as a + module or can be statically linked with the kernel. + + 6) Build and install the kernel as specified in the chapter "Making the LFS + System Bootable." + +Section II.d. Setting up the Scripts + +After finishing the "Setting up System Bootscripts" and "Making the LFS System +Bootable" chapters, one must setup the necessary scripts for package +management before restarting*. There are two attached scripts, pkgs and manager. + +The manager script issues mount commands to UnionFS. This script can be +copied into /pkgs. This script will be discussed in depth later. + +pkgs is an init script that (a) sets up all the mount points necessary for +package management and (b) loads all the necessary packages for system startup. +This script should be executed as early in the bootscripts as possible. +If UnionFS is built as a module, the script should be +executed after the module has been loaded. Otherwise, this script +should be executed first. To install this script assuming one is using LFS's +boot scripts, one should: + + 1) Copy pkgs into /etc/rc.d/init.d. + + 2) Make a link of pkgs to /etc/rc.sysinit: + a) If UnionFS was built as a module: + + Have the script be executed after the necessary modules have been + loaded: + (i) ln -sv /etc/rc.d/init.d/pkgs /etc/rc.d/rc.sysinit/S06pkgs + + Add UnionFS to /etc/sysconfig/modules in order to have the UnionFS + module be loaded at startup: + (ii) echo unionfs >> /etc/sysconfig/modules + + b) If UnionFS was built into the kernel: + + Lower the execution order of mountkernfs: + (i) mv -v /etc/rc.d/rc.sysinit/S00mountkernfs \ + /etc/rc.d/rc.sysinit/S01mountkernfs + + Have the pkgs script to be executed first: + (ii) ln -sv /etc/rc.d/init.d/pkgs /etc/rc.d/rc.sysinit/S00pkgs + + 3) Create the pkgs_startup file: + This file is used by pkgs to determine what packages to load at + startup. This file is akin to /etc/sysconfig/modules. Each line in this + file has the following format: + package_name <SPACE> package_version + + This file is typically located in /etc/sysconfig. If one wishes to use + another location, change the CONFIG_FILE variable in the pkgs script to + the location of this file. + + This file should contain all the packages necessary for the init scripts + that follow the pkgs script, like sysklogd and udev, in order for + proper system startup. If one wishes to load all available packages + at system startup, type: + /pkgs/manager list > /etc/sysconfig/pkgs_startup + +If the manager script was not copied into /pkgs, open the pkgs script and +look for the PKG_LOADER variable. This variable should be changed to the +location of the manager script. + +* In fact, not setting up the package manager will produce a non-bootable + system because packages are installed in non-standard locations. + +Section II.e. Creating the Necessary Symbolic Links + +After the scripts have been installed, a few symbolic links must be created +for proper system startup, since essential programs like init are not installed +in standard locations. + +The general process for creating the symbolic links is as follows. +All the programs (1) that are to be executed after the kernel has finished +initializing and before the pkgs script can be executed and (2) the libraries +these programs depend on must have symbolic links in the /bin, /sbin, or +/lib directories. The pkgs script calls the manager script to load the +packages, so all programs required by manager and the libraries they depend on +must also have symbolic links. + +Subsection II.e.1. Program Symbolic Links + +Here is a list of programs whose symbolic links are typically required. +Some systems may require additional programs. Those denoted by an +asterisk are mandatory. + + *1) init -- this program is executed by the kernel after initialization + The kernel expects init to be in /sbin/init. + *2) bash -- this is executed by init to run the init scripts + *3) echo -- this is used by all init scripts to display messages + *4) ls -- used by the manager script + *5) find -- used by the manager script + *6) sed -- used by the manager script + *7) mount -- this is used by the mountkernfs, pkgs, and manager scripts + 8) mountpoint -- this is used by the mountkernfs script + 9) modprobe -- this is used by the modules script + 10) dmesg -- this is used by the consolelog script + +To create the symbolic link for a program, one must locate the program first. +This can be achieved by typing: + find /pkgs -name program_name + +Next, the symbolic link can be created: + ln -sv /path/to/program_name /bin + or + ln -sv /path/to/program_name /sbin + +For example, if one wants to create the symbolic link for init, one must first +locate it by typing: + find /pkgs -name init + +If find produces the following result: + /pkgs/sysvinit/2.86/sbin/init + +The symbolic link can then be created by typing: + ln -sv /pkgs/sysvinit/2.86/sbin/init /sbin + +Subsection II.e.2. Library Symbolic Links + +All of the above programs depend on shared libraries. It is for this reason +links to the required shared libraries must be in /lib. To determine the +required libraries, type: + ldd /path/to/program + +Next, search for the location of the library by typing: + find /pkgs -name library_name + +Finally, create the symbolic link in /lib if one does not exist: + ln -sv /path/to/library /lib + +For example, if one wishes to create the symbolic links for bash, one must +first determine the libraries it requires: + ldd /bin/bash + +The ldd program may produce the following output: + linux-vdso.so.1 => (0x00007ffff6bfe000) + libreadline.so.5 => /lib/libreadline.so.5 (0x00007fc8ee804000) + libhistory.so.5 => /lib/libhistory.so.5 (0x00007fc8ee6fc000) + libncursesw.so.5 => /lib/libncursesw.so.5 (0x00007fc8ee596000) + libdl.so.2 => /lib/libdl.so.2 (0x00007fc8ee492000) + libc.so.6 => /lib/libc.so.6 (0x00007fc8ee258000) + /lib64/ld-linux-x86-64.so.2 (0x00007fc8ee941000) + +For each of the files listed, a symbolic link should be created. +"linux-vdso.so.1" is skipped because it does not point to an +actual file. The library "libhistory.so.5" can be located by typing: + find /pkgs -name libhistory.so.5 + +If find produces the result: + /pkgs/readline/5.2/lib/libhistory.so.5 + +The symbolic link can be created by typing: + ln -sv /pkgs/readline/5.2/lib/libhistory.so.5 /lib + +Subsection II.e.3. Troubleshooting + +During system startup, if the kernel, init, or an init script reports it cannot +find a certain program, there are two possible reasons: (a) a valid symbolic +link to the program is not in /bin or /sbin, or (b) all the necessary libraries +for the program do not have valid symbolic links in /lib. + +Part III. Using the Package Manager + +Now that installation is completed, one can boot into the LFS system. This +section describes how to use the package manager. + +Section III.a. Loading and Unloading + +The manager script does the grunt work for setting up the target directories. +It provides two functionalities: (1) loading a package and (2) unloading a +package. Loading and unloading can be done as follows: + + /pkgs/manager load package-name [package-version] + +For example, if one wishes to load the package sed, version 4.1.5, one types: + + /pkgs/manager load sed 4.1.5 + +Specifying the package version is optional. If it is omitted, the first version +manager finds is used. Unloading the package follows the same format: + + /pkgs/manager unload package-name [package-version] + +To unload sed, version 4.1.5, type: + + /pkgs/manager unload sed 4.1.5 + +The package version must match the same version used to load the package. + +Section III.b. Upgrading a package + +To upgrade a package, unload the package version that is already loaded, and +load the new package version. + +Suppose there are two versions of the fluxbox package installed: + $ /pkgs/manager list fluxbox + 0.9.16 1.0.0 + +To switch from 0.9.16 to 1.0.0, one types: + # /pkgs/manager unload fluxbox 0.9.16 + # /pkgs/manager load fluxbox 1.0.0 + +Section III.c. Diagnostics + +The manager script provides a few diagnostic tools: + + * To list all of the packages available and their versions, type: + /pkgs/manager list + + * To list all the available versions of a package, type: + /pkgs/manager list package-name + + * To check that the correct directories are being unionized, type: + /pkgs/manager test package-name [package_version] + +Section III.d. Limitations + +One of the goals of the package manager is minimalism. Features +found in most package managers are not available in the one presented here +because of this choice. However, the limitations listed here can be overcome +by extending the functionality of the package manager. The scripts are not +designed to be a byzantine of code, and they contain comments to ease hacking. + +The manager script cannot determine what packages are loaded. There are +no checks made when a package is loaded. Issuing a load command to a package +already loaded has no effect. Unloading a package that is not loaded will result +in an error from UnionFS. + +If a package depends on another, it is up to the user to load that +package. No dependency calculations are performed by the package manager. + +Section III.d. When to Reload a Package + +If a package's contents are modified, there are certain situations where +reloading a package is necessary for changes to take effect. + +Adding files or directories to a source directory like etc or bin does not +require a reload. Assume there is a package samba, version 2.10.13. There is +the directory share in the package. If a file called mynotes.txt is added to +the package's share directory, reloading the package will not be needed, since +mynotes.txt will immediately appear in /usr/share. + +Adding a source directory where one did not exist before +requires a reload. Assume there is the package gtk with version 2.10.13. +This package only contains the directory usr; in other words, the directory +/pkgs/gtk/2.10.13 only contains the directory usr. +If an etc directory, which did not exist before, is created in +/pkgs/gtk/2.10.13, a reload is necessary. + +Reloads can be accomplished by typing: + /pkgs/manager unload package-name package-version + /pkgs/manager load package-name package-version + +To reload the gtk package with version 2.10.13, one types: + /pkgs/manager unload gtk 2.10.13 + /pkgs/manager load gtk 2.10.13 + +Section III.e. Editing Files in a Package + +When editing a file in a package, one should open the file from +the /pkgs directory, not from the target directory. + +Suppose there is a file in /pkgs/x.org/7.2/etc/X11/x.org, +which also exists as /etc/X11/x.org. If one wishes to edit this file, it +should be opened from /pkgs/x.org/7.2/etc/X11/x.org, not /etc/X11/x.org. +Changes made to /pkgs/x.org/7.2/etc/X11/x.org will immediately become apparent +in /etc/X11/x.org. + +Even though they are technically the same file, if +/etc/X11/x.org is edited, UnionFS will physically create the directory +/etc/X11, save the changes made to /etc/X11/x.org, and delete +/pkgs/x.org/7.2/etc/X11/x.org. This behavior runs against the goal of +keeping files in separate directories as much as possible. + +Section III.f. Uninstalling a package + +To uninstall a package, (a) unload the package, then (b) delete the package +directory. + +Part IV. Concluding Remarks + +The goal of this document is to present an alternative package manager based +on UnionFS to the de-facto standard of black-box style package managers. +Users wishing for a higher degree of organization over files and directories +may find this type of package manager useful. + +The ideas presented here can be extended, namely: + + 1. Other operating systems, like the BSDs, can also take advantage of this + type of package management. In fact, the BSD kernels have supported + union directories for many years. + + 2. The capabilities of the package manager can be improved by hacking the + manager script or write additional scripts that automate the + installation of packages. + + Moreover, replacing the manager script with something in a different + scripting language may be better. Bash has been a difficult language for + the author, and rewriting the manager script in Python + would reduce the amount of code and make it cleaner. Adding functionality + to the package manager is probably much easier in Python than Bash. + + 3. Users can have personal packages in their home directories and can + load and unload them. This can be achieved by: (a) allowing mounting to + non-root users, (b) copying the manager script to the user's home + directory, and (c) modifying the script's "pkg_dir" and "target_dir" + variables. + +CHANGELOG: + [2008-10-30] + * Hint created. -- http://linuxfromscratch.org/mailman/listinfo/hints FAQ: http://www.linuxfromscratch.org/faq/ Unsubscribe: See the above information page