NAME

chroot-install - An aid to packaging


SYNOPSIS

chroot-install [-achmnsvDLSF] [-V level] [-R root_dir] [-r project_root] [-p prototype] [-u user] [-g group] [-U uid] [-l dir[:dir ...]] [-d dir[:dir ...]] [-x dir[:dir ...]] [-e file -E checksum] [-C c[opy]|m[ount]|n[one]] [-P c[opy]|m[ount]|n[one]] [-M file] [-Y file] [command] [arg ...]


DESCRIPTION

This script is designed to setup and then tear down an environment suitable for chroot()ing into where a program can be installed. In this way everything the installation process performs can be tracked.

It should be noted that due to the use of the chroot() system call this script will require root privilages. If the script is run by a non-root user then su will be invoked to gain root privilages.


OPTIONS

Supported options are:

chroot-install [-achmnsvDLSF] [-V level] [-R root_dir] [-r project_root] [-p prototype] [-u user] [-g group] [-U uid] [-l dir[:dir ...]] [-d dir[:dir ...]] [-x dir[:dir ...]] [-e file -E checksum] [-C c[opy]|m[ount]|n[one]] [-P c[opy]|m[ount]|n[one]] [-M file] [-Y file] [command] [arg ...]

More details on the options are shown below

Setup of chroot environment

The following options are related to how the chroot() environment is setup and configured.

-P c[opy]|m[ount]|n[one]
How perl is provided to the installation process in the chroot() environment. The option has to be one of the following:
  +--------+--------+--------------------------------+
  | Option | Abrev. | Action                         |
  +--------+--------+--------------------------------+
  |  copy  |   c    | Copy the directory             |
  | mount  |   m    | Read-only mount the directory  |
  |  none  |   n    | Not provided                   |
  +--------+--------+--------------------------------+

The default is ``m'', i.e. to mount the directory. If you are installing a perl module you will have to use -P copy which results in a large performance hit as the perl environment is copied into the chroot() environment.

-C c[opy]|m[ount]|n[one]
How the current working directory is provided to the installation process in the chroot() environment. The option has to be one of the following:
  +--------+--------+----------------------+
  | Option | Abrev. | Action               |
  +--------+--------+----------------------+
  |  copy  |   c    | Copy the directory   |
  | mount  |   m    | Mount the directory  |
  |  none  |   n    | Not provided         |
  +--------+--------+----------------------+

The default is ``m'', i.e. to mount the directory.

It should be noted that in this case the loopback mount of the directory is done on a read/write basis rather than a read-only basis. This means that any changes which occur inside the chroot()ed environment will be reflected outside it as well.

-R root_dir
The ``root'' directory to install into; this becomes the point the script is chroot()ed into. There are several different macros which can be used here:
  $PWD -> The current working directory of the
          script
 $USER -> The username of the person running the
          script

-S
Scrub the installation root directory; in other words clean the root directory before an installation

-F
Fixes modes; ensures that directory entries which have permissions such that only the owner can access them are changed so that everyone has at least read permission.

-r project_root
The root of the project, ie /usr/local - use of this option will not only create the root project directory, but also a number of standard sub-directories under it. Thus if the project root is given as /usr/local then the following directories will be created:
  o /usr/local
  o /usr/local/bin
  o /usr/local/man
  o /usr/local/lib
  o /usr/local/include

This is most useful for installation scripts which assume that the installation directories already exist so they don't need to create them; this is a depressingly frequent occurance as well.

-m
When combined with the -r flag, this moves the contents of the project root to the top of the project root.

It ensures that only files within the project root exist; if this is not the case then it will cause a fatal error.

-l dir[:dir ...]
A colon separated list of additional directories to mount into the chroot() area by loopback file system (i.e. lofs(7FS))

-d dir[:dir ...]
A colon separated list of additional directories to copy into the chroot() area.

-x file[:file ...]
A colon separated list of additional files to copy into the chroot() area. Note that if the file name does not have a full directory path it is considered to be a command name.

-M file
Fix the modes of the files so that they are readable by everyone; put the original modes into the given file in the format of:

  filename  mode

Where the filename is relative to the root directory

-Y file
Specifies a file where changes to the /etc/passwd and /etc/group files within the chroot() area are recorded. The file has the following format:
  FILE line

Where FILE is either passwd or group. line is the actual changed line from the file. It should be noted that only additions to the file are tracked.

This option is primarily used by build-pkg.

[command]
An optional command to run instead of spawning a shell in the chroot()ed environment

[args]
Optional arguments to the optional command

Helper options

The following options provide helpful features which may not be required in day-to-day usage of this script.

-a
Append prototype data to prototype file (requires -p)

-u user
Force files/directories/etc to be owned by the given user. This can be a numeric UID or a valid username in /etc/passwd. Does not apply to setuid files. Note that -s (strip setuid/setgid/save text) will ensure that all files are forced to this user.

-g group
Force files/directories/etc to be in the given group. This can be a numeric GID or a valid group name in /etc/group. Does not apply to setgid files. Note that -s (strip setuid/setgid/save text) will ensure that all files are forced to this group.

-p prototype
Output prototype file to named file

Informational options

The following options provide information about the running of this script

-h
This help

-v
Make output more verbose than it is already. Equivalent to -V 2

-V level
Set verboseness level - integer numeric value. There are several keywords which can be used in place of a numeric value:
  most - Enable most messages (equivalent is -V 5)
  all  - Enable all messages

Debugging options

The following options are useful in debugging the script and should not be required in day-to-day usage of this script.

-c
Only do the cleanup

-n
Do not run commands

-s
Strip the setuid, setgid and save text flags from files

-L
Do not clean up, leave everything in place

-D
Debugging - disables cleanup even in the event of an error and sets -V all

Internal options

The following options are used internally by the script if it has to call itself again using su. They are only listed here for informational usage; it is not expected that they are used by end users.

-U uid
The numeric user id of the user who originally called the script. This option is only used if the user is not running as root when the script is run; i.e. su has to be called.

-e file
A file which contains a list of environment variables to set. Each line has its own environment variable, in the format of ``Key%%%_%%%Value''. Note that this option requires the -E flag. This option is used internally by the script and should not be used by users.

-E checksum
The MD5 checksum of the environment file. This option is used internally by the script and should not be used by users.


HOW IT WORKS

This script builds an environment suitable for a chroot()ed environment by doing the following:

Whilst this may appear to be a large amount of work the result is that it appears to the installation process occuring within the chroot() jail that it has access to the entire system can do what it wants.

This is due to chroot() changing the root directory of the process which calls the chroot() system call. Every process has a pointer to the physical directory the root file system, or / resides on. This pointer is used in all file handling operations where the system is called upon to find the location of /. Thus to open the file /somefile the system will do something similar to the following:

This means that if the pointer for / in a process is changed to a different directory then the entire world view of the process will be changed.

This is what the chroot() system call does.

Due to this world view change, a working environment has to be built for the chroot()ed process as essential system files will not be present within the new world view the process has.

So if the following lines of code were executed:

    chdir("/some/directory");
    chroot("/some/directory");

Then the root directory for the calling process would stop being / and start being /some/directory. Effectively this would mean that chdir("/") would actually take you to /some/directory.

This does cause some problems as there are files which are essential to the sane running of the system. For example if you wanted to run the most basic shell, /bin/sh in a chroot()ed environment, you'd have to provide at least the following inside the directory the process was going to be chroot()ed to:

USAGE

The script, whilst having a large number of command line options, is relatively simple to use. In the simplest case all you need to do is use:

    % chroot-install

And the following will be displayed; note the asking of the root password for gaining root privilages by using su. This is only done if you do not already have root privilages.

    chroot-install: You have to be root to run this command
    Password: 
    chroot-install: Creating /home/simes/work/install
    chroot-install: Setting environment variables
    chroot-install: Creating directories
    chroot-install: Copying file
    chroot-install: Ensuring certain commands exist
    chroot-install: Building devices
    chroot-install: Working on copying directories
    chroot-install: Working on mounting via lofs
    chroot-install: Working on mounting via lofs
    chroot-install: No command line arguments - spawning a shell
    chroot-install: chroot()ing to /home/simes/work/install
    chroot-install: You are chroot()ed, you will be limited in what you can do
    root@host[1]%

At this point you can then type commands in as normal, although as the message above says, since you are chroot()ed there will be limits as to what you can do. When you exit the shell above the script will then clean up what it created:

    root@yardie[1]% exit
    chroot-install: Cleaning up random files
    chroot-install: Unmounting lofs
    chroot-install: Removing copied directories
    chroot-install: Removing devices
    chroot-install: Removing specific commands
    chroot-install: Removing files
    chroot-install: Removing directories
    chroot-install: Cleaning up after CreateDir()

Whatever was done in the chroot() jail will be held in the directory $PWD/install, although this can be changed by the -R option.

One of the more useful command line options is -r which allows you to specify a project root. This then creates not only that directory, but the directories bin, man, lib and include under it. This is very useful for packages who have what could be best described as naive installation scripts which assume that such project roots exist on the machine already.

You can also give the script a command with arguments to run inside the chroot() jail instead of a shell. For example:

    % chroot-install make install

Would result in make install being run inside the chroot()ed environment.

For the full list of command line arguments, please run:

    % chroot-install -h


ENVIRONMENT VARIABLES

IN_CHROOT_INSTALL
This variable is set to ``yes'' so that scripts run from within an environment provided by chroot-install can tell that they are within said environment.


SEE ALSO

chroot(1M), mount(1M), chroot(2), lofs(7FS), build-pkg(1)


BUGS

There are issues with the use of this program with NFS mounted directories. Since the majority of the work performed by this program is done as the root user the default options for NFS serving will break this program. By default the root user (i.e. UID 0) has the same privilages the nobody user (actually takes the UID of the nobody user) when accessing an NFS mounted directory unless the NFS server has been configured not to do this.

As a result of this it is recommended that this program is not used on a directory which is mounted via NFS unless the NFS server has been configured to give the root user the privilages of the root user on the NFS server.

You need to have the system provided version of perl (installed at /usr/perl5) available

It is not possible to provide software from within the area being installed into by loopback mount. For example, the installation process of some software requires the command some-prog which has been installed under the /usr/local/ tree. Now, if the software in question is also to be installed under the /usr/local/ tree we have a problem. It is not possible to just loopback mount the /usr/local/ directory as this would make the directory tree you are attempting to install under read-only and thus prevent the installation of the package from occuring. It may also not be sensible to copy all of the /usr/local/ tree into the chroot() environment; on most systems this would add a large amount of time to the package building process.

The only real solution is a kludge; you avoid the use of chroot-install by having the software package install in the InstallPackage/build directory as described in the manual page for build-pkg. For example with software which uses GNU autoconf this could mean doing the following:

    make prefix=`pwd`/InstallPackage/build/usr/local install

However this also means that you have to check the Makefile of the software to ensure that it does not install anything outside of the prefix tree.


AUTHOR

Simon Burr <simes@bpfh.net>


LICENSE

Copyright (c) 2002, Simon Burr <simes@bpfh.net> All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  * Redistributions of source code must retain the above copyright notice,
    this list of conditions and the following disclaimer. 
  * Redistributions in binary form must reproduce the above copyright
    notice, this list of conditions and the following disclaimer in the
    documentation and/or other materials provided with the distribution. 
  * Neither the name of the author nor the names of its contributors may
    be used to endorse or promote products derived from this software
    without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.