urpkg 20110630
I hereby release this software in the public domain. This means that you can use and distribute it in whatever way you see fit. However, if you want to re-publish it, I ask you to please put a link to its web page, and mention my name. You are not forced to do it, but that would be a way to say thanks ! See also: My copyright page
Table of Contents
This is the user manual for urpkg, a software to install programs in a safe and easily undoable way. Urpkg is public-domain software, written in C.
I first begun working on urpkg after reading the More Control and Package Management using Package Users LFS hint so a lot of ideas implemented in urpkg come from the hint's author Matthias S. Benkmann which I would like to credit here.
Even though this document should be complete enough, I strongly recommend you to read the hint first, as to better understand the ideas behind urpkg.
Table of Contents
urpkg is a software to install programs in a safe and undoable way. One could call it a package management software, although its features are somewhat scarce compared to the other tools in that domain. Urpkg let you install programs (usually from source, although you could also consider using another package manager for example) in such a way that you have complete controls over where the installation program has access. Once your software is installed, it is very easy to list its files and uninstall it in case you are not satisfied.
Under the hood, urpkg creates a user for each program that you install
and run the installation command as this user. The command is therefore
never given root access and will not be allowed to do any unwanted
damages as it may happen if you run the usual sudo make
install
for example.
The first goal I had in mind when creating urpkg was to prevent installation programs from overwriting files or getting suid behind my back. I did not want to let the program run as root for a task as delicate as installing a program. So that's the first idea: complete control over what gets installed and how. You may trust your package manager, but do you trust all the installation scripts of all the programs you are ever going to install, remove and upgrade ?
The second goal was to be able to uninstall any software, even if there
is no available package (for example for development
versions), make uninstall
target, or other means of
uninstalling it. Urpkg lets you run any command, and then remove all
files generated by that command easily. This way it is much easier to
install software from source or to create packages for your favorite
distro in an automated way, much like
checkinstall.
By the way, since version 1.4, you can easily create Slackware packages using urpkg. See the section called “Creating a Slackware package”
In short, urpkg can be used to...
Keep control over what any installation program (including your favorite package manager) is doing
Install any program from source
Generate package for your favorite distribution
Anything you think it can be good at...
Table of Contents
This section details how to compile and install urpkg from source on your machine.
You need a UNIX-like system for urpkg to work. I have tested it on GNU/Linux
(LFS and Slackware 12.1), but other systems should work as well. You will
also need root access on that system. By design, urpkg is useless if you
cannot get root access, since it needs to be able to create new users to
install a package. Some scripts assume that your user list is in
/etc/passwd
and your group list in
/etc/group
. If that is not the case, you should
change them accordingly.
urpkg uses CMake as build system, so you will need to download and install it. You will also need the standard make and gcc tools.
If you want to build the documentation yourself (this should not be necessary if you are installing a release tarball), you should have the necessary tools to build docbook documentation, that is
You must also have the useradd, usermod, etc. programs available, because urpkg looks for them before compiling the software. Any standard linux distribution has these tools.
urpkg relies on some external shell scripts using standard tools that should be available on your system. Those are:
Most of those software should already be on your system, so urpkg is indeed very light on dependencies.
First, extract the urpkg tarball and cd to it.
$
tar -xf<Your .tar.gz file>
$
cd<filename without .tar.gz>
Then, you should create a build directory
$
mkdir build$
cd build
Now it is time to configure your build. The command is of the form
cmake -DBuildVariable1=Content1
...
-DBuildVariablen=Contentn
..
In general, you should not need to set a lot of variables. A simple
$
cmake ..
should be enough. The possible variables and their default values are listed below.
CMAKE_BUILD_TYPE
: specify what kind of build you
want to do. It is either "release" or "debug". The default is
"release".
DEBUG
: If this variable is 1, the program will act in
debug mode, e.g it will coredump if something is wrong. The default is 0
if CMAKE_BUILD_TYPE
is release, 1 otherwise.
DESTDIR
: The destination directory, defaulting
to /
. This is the root directory where everything
will be copied. This can be useful if for example you want to install
urpkg on some other filesystem, and then mount it as the root
filesystem.
CMAKE_INSTALL_PREFIX
: The installation prefix,
defaulting to /usr/local
. All urpkg files will be
installed there.
DOCDIR
: Where all the documentation will be
installed. It defaults to
${CMAKE_INSTALL_PREFIX}/share/doc
MANDIR
: Where the manpage are on the system. Default to
${CMAKE_INSTALL_PREFIX}/share/man
PKGDIR
: Path to the package directories,
where all package user will have their home directory. See
the section called “Package directories” for more information. The default is
${CMAKE_INSTALL_PREFIX}/urpkg/
CONFIGDIR
: Path to the configuration directory,
where urpkg keeps its scripts and some information about what is
installed (see the section called “The configuration directory”). The default is
${CMAKE_INSTALL_PREFIX}/etc/urpkg/
INST_LOG
: Where error outputted by the installation
script will be logged. By default,
/var/tmp/install.log
FINDCMD
: The script urpkg uses to find the files
belonging to a given package. See also
the section called “The find script”. You should not change that variable
unless you know what you are doing. It defaults
to ${CONFIGDIR}/find
PREINST
: The script urpkg runs before any
installation. See also the section called “Pre and post install scripts”. You should not
change that variable unless you know what you are doing. It defaults
to ${CONFIGDIR}/preinst
POSTINST_DIR
: Directory where all the scripts urpkg
runs after an installation should be. See also
the section called “Pre and post install scripts”. You should not change that variable
unless you know what you are doing.
It defaults to ${CONFIGDIR}/postinst/
UADD_PATH
, UMOD_PATH
,
UDEL_PATH
, GADD_PATH
,
GDEL_PATH
: Specify the path for respectively
useradd, usermod,
userdel, groupadd and
groupdel. You need to change those only if cmake
cannot find them automatically.
Now everything should be ready. Compile the program.
$
make
If you want to compile the documentation as well (if you downloaded a release tarball that should not be necessary, as it has already been compiled to most format for you), run
$
make doc
To install urpkg, you have two choices: the first is to directly run
$
make install
with root privileges if necessary. However, if you have read all I said in the section called “How can urpkg be useful ?” about installation programs changing file permissions behind your back, you may not even want to trust the installation commands generated by cmake.
This is perfectly fine. Since you have compiled urpkg, you can use it
to install itself in a secure way. The following
section lists the necessary steps. I recommend this
method only to users already familiar with how urpkg
works. If you are doing this often, you should write yourself a script that
automates this action. One such script is in
helpers/bootstrap.sh
in the top level directory of
urpkg's source.
In these instructions, I assume you are at urpkg's top level directory and
you have already build the software in build/
. The
shell variable VERSION
is assumed to contain urpkg's
version number. You can replace it with whatever you like.
First, cd to the build directory.
$
cd build/
For various reasons, you should create the package directory
first, as root. Replace PKGDIR
in the
following instructions with whatever you configured the program
with in the section called “Configuring the build”
$
mkdir ${PKGDIR}
You should not forget to create the install and shared group, and then mark places where you want urpkg to be installed as install directories.
$
groupadd urpkgrp-install$
groupadd urpkgrp-shared$
src/urpkg --gen ${CMAKE_INSTALL_PREFIX}/bin$
src/urpkg --gen $DOCDIR$
src/urpkg --gen ${MANDIR}/man*$
src/urpkg --gen $(dirname $CONFIGDIR)
Then, you have to create a temporary package directory where urpkg will put all files of the urpkg package. You will then copy this temporary package directory to the real package directory (which is created during urpkg's installation).
$
PKGDIR="$(mktemp -d /var/tmp/urpkg.XXXXXXX)"
To avoid any permission problem when the install script tries to create files in the build directory, change its access permissions.
$
chmod -Rv o+xrw .
You are now ready to run urpkg. Be aware though that no find command, no postinstall script and no preinstall script are available so you have to either specify the path explicitly or disable them when you invoke urpkg.
$
src/urpkg --install --pkg-name=urpkg-$VERSION \
--findcmd=../scripts/find --pkg-dir=$PKGDIR --no-preinst --no-postinst \
make install
Normally, everything should go fine and urpkg should be installed. Check it by running
$
urpkg --info
You still have to copy the temporary package directory to the real package
directory. You can know its location by looking at the output
of urpkg --info
. I will refer to it
as TRUE_PKGDIR
$
cp -rav ${PKGDIR}/urpkg-$VERSION $TRUE_PKGDIR
That's not completely finished. The package user has been created with the temporary package directory as its home directory. To change that, you need to know what the package user is. You can find it using
$
USERNAME="$(stat --format=%U ${TRUE_PKGDIR}/urpkg-$VERSION)"
Finally, change the package user's home directory and remove the temporary package directory
$
usermod --home ${TRUE_PKGDIR}/urpkg-$VERSION $USERNAME$
rm -rv $PKGDIR
I leave up to you whether you want the package to own the package directory. I like to keep the package directory owned by root, because even if you remove urpkg from your system, you might want to keep some files from various package directories.
In order to test urpkg's feature, we are going to create a test package, with some files and an installation command that will try everything it can to mess up with the system. We will then install this package using urpkg, play a little bit with it, and finally uninstall it.
We will create two destination directories. One where the program will be
allowed to be installed, and one where it should not write any files. We
will create those directories in /usr/urpkg-test
, or
any other directory you wish (just be sure that it is not listed in the
EXCLUDE
variable of the find command). We will
assume /usr/urpkg-test/
has been chosen.
$
cd /usr$
sudo mkdir urpkg-test$
cd urpkg-test$
sudo mkdir allowed$
sudo mkdir restricted
Now we put some files in the two directories. Those files should not be overwritten by our test package.
$
sudo touch allowed/{file1,file2}$
sudo touch restricted/{file1,file2}
Let's name our package foo, and create some files in it.
$
sudo mkdir foo$
sudo touch foo/{foo1,file2}$
cd foo
Let's say that foo1
is specific to the package foo,
while file2
is a more recent version of
allowed/file2
. So we would like to
overwrite allowed/file2
with foo/file2
.
The installation command will be given to urpkg in the next chapter.
Once you have installed urpkg, you cannot install a program with it right
away. If you try, you will find that files can only be written where everybody
has write permission. Concretely, the package foo cannot be installed in
allowed
or in restricted
at the
moment. Let's make sure of this.
$
sudo urpkg --install install -v foo1 ../restricted/.
Should output something like this
Installing package foo-20080527... Preinstall script Running install command: install -v foo1 ../restricted/. install: cannot create regular file `../restricted/./foo1': Permission denied `foo1' -> `../allowed/./foo1' *** WARNING: The install command printed something to stderr (see /var/tmp/install.log): install: cannot create regular file `../restricted/./foo1': Permission denied *** ERROR *** urpkg: Command install with arguments '-v foo1 ../restricted/.' returned non-zero status 1 Cleaning up... Terminating all processes... Closing all files... Uninstalling uncompletely installed package. PLEASE DO NOT KILL Uninstalling package foo-20080527... Listing and removing files... Removing package user...
What happened was that our package user had no permission to write in
../restricted
, so the installation command failed and the
program was immediately uninstalled.
To allow programs to be installed in a directory, you need to change the directory's permissions.
Before doing that, you have to create two special groups. They are described in more details in the section called “Package user groups”
$
sudo groupadd urpkgrp-install$
sudo groupadd urpkgrp-shared
Now you can invoke the gen
command on the directories in
which you want to allow packages to be installed.
$
sudo urpkg --gen ../allowed
This allows any package user to write
in ../allowed
. However, existing files in these
directories cannot be overwritten or removed by anything else than the package
those files belong to. As an example
$
sudo urpkg --install install -v file2 ../allowed/file2
Will not work. You might simply want to
remove ../allowed/file2
and then retry, but what if the
installation script needs the content of file2
? For
example, file2
could be an index, and the installation
script might just want to append something to the index. The solution to this
is to change the permission of file2
to allow it to be
overwritten. It will still not be possible to remove it though. This is done
using the share
command.
$
sudo urpkg --share ../allowed/file2
Directories where one can install program are referred to
as installation directories while regular files that
package user can overwrite are called shared files. In a
real system, installation directories would for example
be /usr/bin/
or /etc
. Shared files
are rarer but can for example
include /usr/share/info/dir
, the index of all installed
info documentation files.
To make a shared file a normal file, or make an install directory a usual
directory, use respectively --unshare
and --ungen
. If you want to list your shared files,
use --list-shared
, --list-instdir
is used to
list installation directories.
We are finally ready to install our foo package. Make sure
that ../allowed
is an installation directory and
that ../allowed/file2
is a shared file. Then run
$
sudo urpkg --install cp -v foo1 file2 ../allowed/.
The command should terminate without error. The package foo has now been installed and is part of the system. To list all installed packages, do
$
urpkg --list
Notice that a date string has been happened to foo. In fact, the package name
was guessed from the current directory. Had the directory
been named foo-1.1
, the package name would have been
foo-1.1 , as a version string already existed. If you don't want the name to
be guessed, you can use --pkg-name
to give any name you want.
You can also use --list
with the package name
as an argument to list all files belonging to a given package.
$
urpkg --list foo
Notice that there is no need to give the package's full name. An unambiguous name is enough (e.g if there were two versions of foo installed, say foo-1.1 and foo-1.2, then we would have had to be more precise).
You should also see that there is only one file, foo1
that is listed. This is because file2
is a shared
file. Now what if you want to add it to the package, so that it is removed if
we uninstall foo ?
We first have to strip file2
of its status of shared
file. Even though urpkg does not forbid shared files part of a package, it is
a bad habit to take. Then we simply use the --add-files
action.
$
sudo urpkg --unshare ../allowed/file2$
sudo urpkg --add-files --change-owner --change-group foo ../allowed/file2
The --change-owner
and --change-group
deserve a more detailed explanation on what it exactly means to add a file
to a package. This is presented in the section called “Owned and added files”. For the
moment, it is enough to say that unless it is necessary for the file to keep
its owner or group (e.g because it's a suid file), then those options should
be used.
Another option since version 1.4 is to use the urpkgize script. This script adds a bunch of files to a given package, trying to figure out the correct options for each file on the way. For example, to perform the same action as before you would do:
$
sudo urpkgize foo ../allowed/file2
In general, you should use --add-files
, and
take care of the options yourself. urpkgize only comes in
handy when you want to add a lot of files to a package. You can find more
information on urpkgize in urpkgize(1).
Now let's check that the file has correctly been added
$
urpkg --list foo
What if you don't want foo1
to be part of the package
anymore ? In that case, you should do
$
sudo urpkg --free-files --change-owner=OWNER --change-group=GROUP foo ../allowed/foo1
You should replace OWNER and GROUP by the owner and group you want the file to have. If those options are not specified, they will both be set to root.
What if you don't remember which package(s) the
file file2
belongs to ? Then you can
use --find
$
urpkg --find ../allowed/file2
You might have remarked by looking at the output of
the --install
command that some commands are run after the
installation, like ldconfig for example. In fact, it is very easy to add
scripts to be automatically executed before or after a package's installation.
The preinstall script should be
in ${CONFIGDIR}/preinst
, by default
/usr/local/etc/urpkg/preinst
. The default script that
comes with the urpkg tarball does not run any command. It is up to you to
change it if you want certain command to be run before any package is
installed. Pay attention though, because this script will be invoked with the
same privileges you had when you invoked urpkg. They
will not be run as the package user. If you want to
exclude the preinstall script from being run, you have to use the
--no-preinst
option.
Every postinstall script should be put in
${CONFIGDIR}/postinst/
, by
default /usr/local/etc/urpkg/postinst/
. Every script
here is run after the installation. The scripts are run in an
undefined order. By default, ldconfig and a
script installing the program's source are run.
The source script is run only if it is passed the source files as an
argument. To pass an argument to a postinstall script,
use --SCRIPT-arg
. For example, if the sources of foo are in
a foo.tar.gz file, you would do
$
sudo urpkg --install --source-arg=foo.tar.gz make install
The sources are installed in the package directory,
in src/
. For a package named foo-1.1 that would be
${PKGDIR}/foo-1.1/src
You can use the --no-postinst
option to not
run any postinstall script
or --exclude-script
to exclude a particular one.
Since version 1.4, it is possible to create a slackware package of whatever
program we installed with urpkg. In this section, we are going to create a
Slackware package of foo, the test package we are using. To do that, you will
need to download and install another of my utilities:
list2pkg . This is a
tool which converts a list of files to a Slackware package. The idea is to use
urpkg's --list
action to create a file list to be used by
list2pkg.
Note that you should first read list2pkg's user manual before using it to create “serious” packages. The content of this section is just meant as an overview of list2pkg's possibilities.
We already know we can use the --list
action to list all
files which are part of foo. However, what is outputted does not only
contain files, as list2pkg require. We must add the --quiet
option for a “pure” list of files to be generated.
That's all we need. We now only have to use the file listing command, and pipe its output to list2pkg.
$
urpkg --list --quiet foo | sudo list2pkg foo-0.1-noarch-1usr.tgz
Note that we absolutely need to invoke list2pkg with root privilege, in order for all metadata to be preserved.
Finally, it is time to remove foo from the system. It is a good idea to list
the files that would be removed before actually removing anything. To do that,
you should use the --pretend
option.
$
urpkg --uninstall --pretend foo
Once you have checked that the action the program would take satisfy you, you can uninstall it.
$
urpkg --uninstall foo
You can check that foo has been correctly removed using
$
urpkg --list
Table of Contents
This chapter details the concept behind urpkg and you should read it if you want to know exactly what is being done to your system e.g when you install a package. It also provides useful hint in the terminology that is used in this manual. Last but not least once you understand how things are done you will be better prepared to deal with the problems you might encounter when you install a program.
There is an importance distinction to make between a package name and a package user. As already mentioned, urpkg creates a new user for each program (urpkg calls them package) you install. The files that are then created all have the new user as owner and can therefore easily be found.
However, urpkg first has to come up with a name for this user. The name should conform to the syntax of a username (e.g, no dot in the name) and should not be the same as other users in the system. One could simply come up with a unique number as username, however that would be really confusing and not really helpful e.g to someone listing a file belonging to that package.
The solution that urpkg uses is the following. We ask the user for, or
guess, a package name that is basically the name of the
program we are installing. This name can syntactically be anything the user
wants. Then, from that name we generate a package user
name. The package name is kept in the comment field of the user
name in /etc/passwd
.
The package user name always begins with “urpkg-”. This is a prefix to avoid that the name collides with another user of the system. Urpkg then generates the rest of the username using the beginning of the package name, and adding some numbers if necessary. You should look at the source if you want more details on the exact algorithm which is used. Special characters in the package name are replaced by “_”. For example, from a package name “emacs-22”, the package user could be “urpkg-emacs-22”. You shouldn't rely on this, however, as the algorithm used by urpkg to generate user names can change at any release without notice !
Note that package names (and package users) are always all in lowercase letters. Even if you give your name explicitly, the case does not matter and your name will automatically be converted to lowercase. For example, running
$
urpkg --install --pkg-name=Emacs-22 make install
Will still create a package name “emacs-22” and a package user “urpkg-emacs-22”.
In general, you don't have to worry about package users, but it's good to know about them, as you can still see them mentioned from time to time. For example, assuming you really have emacs installed as a package named emacs-22, doing
$
ls -l $(which emacs)
-rwxr-xr-t 2 urpkg-emacs-22 urpkg-emacs-22 13576490 2008-03-21 17:59 /usr/bin/emacs
will really give you the package user name of the package the
file /usr/bin/emacs
belongs to.
As you learned in the previous chapter, you can specify a package name
explicitly using --pkg-name
. Urpkg can also guess a
package name for you from the current directory. Now how does it do it ?
Urpkg will simply take the basename of your current directory (i.e if your
current directory is /var/tmp/emacs-22.1
, the basename
is emacs-22.1
). It will then check if it has a version
string. A version string is defined as anything following a dash
(-
). In our example, there is a version string so the package
name would be “emacs-22.1”. If there is no version string,
urpkg will append one with the date in the following
format: YYYYmmdd
. For example, if you are developing your own
program, foo which is in a directory /var/tmp/foo
, then
if you install it on June, 30th 2010 the package name will
be “foo-20100630”.
Of course, there cannot be two package with the same name installed on the system, so urpkg will signal an error if you try to give a package name which is already the name of an existing package.
Now that we have created a user for the package, we still have to decide
where it has permission to write. This is done, as seen previously, using
the --gen
option. Ideally, we would like the package not to
be able to overwrite other package files in the install directories, nor
remove them. There is a permission bit on UNIX systems that achieve just
that: the sticky bit.
The sticky bit prevents unprivileged user (i.e the package user in our
case) from changing or removing a file that they don't own. It is typically
used in directories like /tmp
, where everyone has write
access.
The idea is that you are going to give write access in the install directory to all package users, but since the sticky bit is on, they won't be able to damage files from other packages.
How do we give write access to all package users ? In short, we put every
package user in a given group, called the install group, as they are
created. When --gen
is invoked, all urpkg do is to change
the directory's group to this install group, enable write access for this
group and turn on the sticky bit.
Something similar happens for shared files, although we don't need the sticky bit here, and a different group is used: the shared group.
The install group is “urpkgrp-install” and the shared group is “urpkgrp-group”. Every package user is a member of those groups once it is created. This means it is possible for any package to write to a shared file or put files in an installation directory. Keep this in mind when you make a file shared for example.
As we have already seen, all files created by a package user have by default its name as owner and its group as group. Why do we need to have both ? In fact we don't, for simple cases. As a matter of fact, urpkg will consider any file that has the package user as its owner or as its group. The nice thing about this is that you can easily change the owner or group of any file of the package.
For example, suppose you are installing the sudo program. It obviously needs to be suid root by the very nature of the task it performs. In that case, you can just change its owner to root and set the suid bit as usual. The file will still be detected as belonging to the sudo package since its group still has the package user name of sudo.
Sometimes it may happen that both the group and the owner have to be
changed. This is the case for some daemon that uses both the suid and the
sgid bit. Fcron is an example of
this. In that case, you can still force the file to belong to the package
using --add
without
any --change-owner
or --change-group
option. The file name will then be added to a text file containing a list of
supplementary files belonging to fcron. The disadvantage here is that you
cannot move or remove the file without having urpkg complaining, so don't do
it unless you really have to. More details are given in
the section called “Owned and added files”
Every user on a UNIX system has a home directory. The question is, where do we put a package user's home directory, and what do we do with it ?
Urpkg deals with this problem the following way. A root package
directory is created (by default /usr/local/urpkg
) where
each package has its home directory, named like the package name. For example,
the package “emacs-22.1” would have a home directory
at /usr/local/urpkg/emacs-22.1
. Users can put anything
they want in the home directory. It is typically used for putting the
program's source.
Urpkg stores some metadata concerning the package (for the moment only the
files that belong to the package but whose owner or group have not been
changed) in a subdirectory .urpkg
of the package's home
directory. This directory should not be modified by the human user.
It is possible to give another package directory root when installing the
package, using the --pkg-dir
option.
Urpkg's configuration directory is kept by default
in /usr/local/etc/urpkg
. This is where all the files
urpkg needs to run correctly are stored. Those are mostly shell scripts that
you can change to fit your needs. They are documented here. Pay attention:
they are invoked with the privileges that were used to invoke urpkg.
This is the script urpkg uses to find files whose owner or group is a given package user. It is also used to list install directories or shared files. It takes one argument: a user or group name. It should print the list of files in the system that are owned by this user or group, excluding the package's home directory
By default, a few locations such as /tmp
or /mnt
, or the package home directory are excluded
from the search. They are given in the EXCLUDE
variable
at the beginning of the script. Please check that they match your
expectation.
It is run before any installation. It takes no argument, and by default does nothing but printing a line or two to confirm it was executed.
All files in the directory postinst
relative to the
configuration directory will be run after the installation. Each can be
passed exactly one argument using the --SCRIPT-arg
option.
The complog script will install a compilation log in the package's home
directory. The file must be named svcompile.log
, or
you must pass it as argument. If no such file exist, nothing will be
done.
The ldconfig script will only run the ldconfig command and exit.
The source script will install the source file/directory, given as its
argument in a subdirectory src/
of the package
directory.
If you decide to write your own scripts, you can count on several environment variables to help you:
URPKG_USER
: gives the package username
URPKG_PKGNAME
: gives the package name
URPKG_HOMEDIR
: gives the package directory
PWD
is set to the directory from which urpkg was
invoked.
What do I exactly mean when I say that a file belongs to a package ? Can a file belong to more than one package ? What exactly gets uninstalled or listed then ? This section tries to answer those questions.
Urpkg considers a file as belonging to a given package if one of the two conditions below is satisfied.
The file has the package user as owner or group
The file is listed in ${HOMEDIR}/.urpkg/added
,
where HOMEDIR
is the path to the package's home
directory.
Given this definition, it is easy to see that a file can belong to more than one package. For example, it could have a given package user as its owner , another as its group, and be listed in the added list of a third package. Most of the time though, a file will be only part of one package and you should really keep it that way.
If you use the --find
command, urpkg will list you all
packages the given file belongs to.
When you use the --list
action, urpkg will list you the
files that are unique to the given package, and the
files that are shared with other packages. Only the
former category will be deleted when you uninstall the package. Keep in mind
that you can always use --pretend
to know for sure what
would be removed.
First, urpkg will never remove a directory that does not belong to the package you want to uninstall, even if it is empty. Second, a directory that belongs to the package you are considering must be empty (after you deleted all the other files in it belonging to the package) to be deleted. This prevents other files from other packages that are in the directory to be deleted as well. This can happen if, for example you temporarily set a directory as an install directory and then revert it to belong to the given package.
Urpkg will take no risk and only warn you that the directory is not empty. The uninstallation will not fail just because of that. You will have to remove those directories manually. If you are careful the way you manage your system, this should only happen rarely.
Table of Contents
This section contains the manpages of the commands part of urpkg.
urpkg — Install programs in a safe and undoable way
urpkg
{ACTION
} [OPTIONS
] [ARGUMENTS
]
Urpkg is a software to install programs so that we can easily uninstall them afterward. It does so by creating a new user for each package that gets installed on the system. The package is then installed with this user's privileges instead of root's. This guarantees a much better security during installation.
Note that this manpage is only a short reference. You should read the user manual (published on urpkg's homepage) if you want to know more about urpkg.
When invoking urpkg, you must always specify exactly one action first. You can then give options and arguments if required.
-h
, --help
Print a short description of each option and exit.
-v
, --version
Output information about the program's version and exit.
-I
, --info
Output some information on the settings urpkg was compiled with and exit.
-i
, --install
Install a package by running the command given as argument.
-u
, --uninstall
Uninstall the package(s) whose name(s) are given as argument.
-l
, --list
Without argument, list all installed packages on the system. Otherwise, list all files part of the package(s) that are given.
-W
, --list-instdir
List all the installation directories that are in the path(s)
specified as argument. If no path is given, /
is
assumed.
-L
, --list-shared
Same as --list-instdir
but for shared directories.
-a
, --add-files
Add some files to a package, without changing their owner or group
unless the --change-owner
and/or --change-group
options are given. The package
name must be the first argument, then the files should follow
-T
, --free-files
Remove some files from a given package i.e urpkg will not remove those files if we remove the package. The files are of course not removed from the filesystem.
-g
, --gen
Make the given directories to install directories (i.e place where package can install files).
-w
, --ungen
Make the given install directories normal directories again.
-s
, --share
Make the given files shared files (i.e files packages can write to)
-S
, --unshare
Make the given shared files ordinary file again.
-f
, --find
Find which package the given files belong to.
Global options can be used with any action
-D
, --debug
Print debugging information to
stderr. Implies --verbose
-V
, --verbose
Print more details on what urpkg is doing to stdout.
-q
, --quiet
Only print warnings, errors, and what the user asks for.
-p
, --pretend
Print what would have been done but do not install the package.
-P
, --no-preinst
Don't run the preinstall script.
-G
, --no-postinst
Don't run any postinstall scripts
-e
,
--exclude-script=NAME
Do not run the postinstall script NAME
,
where NAME
is the beginning of the script's
name such that it can be recognized unambiguously.
--NAME
-arg=A
Pass the argument A
to the postinstall
script NAME
.
-H
, --pkg-dir=PATH
Use PATH/NAME
as the package's home directory,
where NAME
is the package's name (guessed or
given explicitly using --pkg-name
).
-n
, --pkg-name=NAME
Explicitly specify the package's name. Otherwise, urpkg will try to guess it from the current directory.
-F
, --findcmd=SCRIPT
Give a custom script to be used to find files part of a given package.
-U
, --change-owner
Change the file's owner (set it to the package user). By default, the file's owner is not changed.
-d
, --change-group
Change the file's group (set it to the package user). By default, the file's group is not changed.
-U
, --change-owner=USER
Restore the file's owner to USER
. By default,
the program will set it to root.
-d
, --change-group=GROUP
Restore the file's group to GROUP
. By default,
the program will set it to root.
-d
, --change-group=GROUP
-m
, --change-perm=PERM
Change the files access permission to PERM
(given in octal form). If not given, urpkg will try to set the
permissions to a reasonable default.
Please report bugs and other inconsistencies you find to the author (address is below). If you have implemented a patch, please do send it there. Any contribution is welcome. See also urpkg's website: http://svasey.org/projects/urpkg/
urpkgize — Add a bunch of file to an existing urpkg package
urpkgize
[OPTIONS
] {PKGNAME
} {FILES
}
Urpkgize is a small script to add files to an existing urpkg package. For each file, it tries to invoke urpkg with the correct options so that the file is added cleanly. It is especially useful when you have a lot of files to add and don't want to figure out the options for each one.
There are three ways urpkg can add a file to a package. It can change the file's owner to the package username, it can change the file's group to the package username or it can add the file to a list of all files belonging to the package. It is usually better to change the file's owner or group (often, both are changed), since the information is then embedded in the file itself. However, this is not always possible as sometimes the file's owner matters (e.g because the file is set user id). Urpkgize tries to keep it simple and adopts the following rules concerning how a file is added to a package.
First of all, if the file is set user id or set group id, urpkgize will not
change respectively the owner or the group of the file. Otherwise, urpkgize
will consider its list of "neutral" user and group name. A neutral
name is one that can be overwritten without problem. By default, only root
is in this list, since most system-wide files have the root owner. You can
use the --neutral
family of options to add other user/group
names to that list, or the --no-neutral-root
option to
remove root from the neutral list.
If a file owner or group name is considered neutral, then it will be changed to the package username to add the file to the package. Otherwise, urpkgize will not modify it. In the end, if neither the owner, nor the group of a file can be changed, then the file will be added to the list of all files belonging to the given package.
Note that each option can be abbreviated and will be recognized if unambiguous.
--help
Print a short description of each option and exit.
--neutral=NAMES
Specify group and owner names that are not considered important and that can be replaced by the package user name (except if the file is set user id or set group id). Each value should be comma-separated. By default, only root is in this list.
--neutral-owners=NAMES
Same as --neutral
but concerns only owner names.
--neutral-groups=NAMES
Same as --neutral
but concerns only group names.
--no-neutral-root
If this is given, then root will not be in the list of neutral owner and group names anymore.
Please report bugs and other inconsistencies you find to the author (address is below). If you have implemented a patch, please do send it there. Any contribution is welcome. See also urpkg's website: http://svasey.org/projects/urpkg/
Urpkg is enforcing a lot of restrictions on the installation script it runs,
compared to a "classical" installation with root privileges. Since a
lot of installation programs were not written to deal with an unprivileged
installation, problems involving “permission denied” errors can
and will occur occasionally. You can usually find the installation command's
error message in urpkg's installation log file (by default
in /var/tmp/install.log
). You should always read that
file after an installation, successful or not.
Those errors are not considered bugs in urpkg, as they are due to the installation command. However, you should know how to deal with them as they occur pretty often when installing large software. In the LFS package user hint, the author suggests using special versions of commonly used programs, like install, modified to catch possible errors and arrange for the installation scripts to use them. In my opinion, this is not general enough, so this has not been implemented in urpkg (you could try to do it using the preinstall script though). If you have ideas on how to solve the problems described in this section, please share them. See Chapter 5, Contributing to urpkg.
Sometimes the installation command needs write access to the current directory. This is often due to libtool wanting to relink some libraries at installation time. Sometimes also the installation program wants to use some log file or touch some temporary file.
Most of the time, the package user does not have write access to the build directory. What you usually do is to extract the tarball as a normal user, cd to it and begin to build. In that case, the default permission of the current, build directory should be something like 0755. Therefore the package user does not have write access.
If you want to allow the program to write there, just
use --gen
to make the location an install directory.
If you don't want the program to write there, then you have a bit more
work to do. Maybe you made a mistake specifying the destination paths at
configure time (e.g you gave the /usr/local
prefix
instead of /usr
). Sometimes the program just wants to
install some locales and in that case you just have to create the
destination directories, make them installation directories and run the
install command again. As a last resort, you can consider going into the
Makefile (or whatever installation script you are using) and changing the
lines that cause problems. You can then complain to the program's
maintainer about this unexpected behavior.
The installation program wants to change the permission of some
directories like /usr
or /usr/bin
, e.g to 0755 while they are install
directories. It can also happen that it wants to change their owner and
group to root.
The installation program could also want to change the ownership of some of its executable to root, or some other user.
The permission / ownership change of install directories is due to poorly written installation script. The command that causes this is usually something like
$
install -d /usr/bin
If the directory already exists, its permissions will be changed to 0755 which is typically not wanted in our case. A command like
$
install -d --owner=root --group=root /usr/bin
is even worse since it does not take into account the possibility of installation in a user's home directory for example. In both cases, the solution is simple: remove those commands from the offending Makefile / installation script and complain to the maintainer.
If the installation program tries to change the ownership of its own executable, this is also unwanted except if the executable are suid or sgid. In any case, you cannot allow this change to happen so just remove the offending lines from the Makefile and change the ownership and / or permissions of the files afterward if you really want to.
Regarding suid and sgid programs, you should never use the package user as a user or group for a suid or sgid file. The reason for this is that package user still have more privileges than ordinary user, and should not be used for anything else but installing packages.
Some installation program sometimes try to overwrite files from another package, or even delete them so that they can be replaced with the new versions the installation program provides. Since urpkg does not allow them to overwrite files, the installation command fails.
The solution depends on what the installation command intends to do with
the files. If they are e.g index files,
like /usr/share/info
then you can consider making
them shared files using --share
. If you don't want your
old files to be erased, just copy them somewhere and copy them back after
the installation. If you want your old files to be erased, just remove
them or move them somewhere else.
In the end, make sure to check what packages the files you moved around
belong to. Don't hesitate to use the --free-files
and --add-files
options to move files to a different
package.
Urpkg is far from perfect. Here is a list of bugs that are known and should be fixed in a subsequent release. If you want to help, see Chapter 5, Contributing to urpkg
Urpkg does not support users or groups of more than 127 characters. If you
have any user or group with 128 characters or more on your system,
consider changing their name or changing
UGRP_RE_MAX_LENGTH
in
src/ugrp.h
to fit your maximum size.
This section lists some tasks that haven't been done and might show up in a future release. They are only at the stage of random ideas. If you want to implement one of them, please see Chapter 5, Contributing to urpkg
Implement a better system of package group so that some packages are
allowed to write to some file but others are not (e.g if they are part of
urpkgrp-emacs they can write into /usr/share/emacs
but otherwise it is not possible).
Write scripts to create binary packages for various distributions
Write the find script in C and integrate it better with urpkg.
Write some tests so that we can make sure urpkg works more or less before releasing a new version.
Don't hesitate to ask questions. See Chapter 5, Contributing to urpkg
There are several ways you can contribute to urpkg. One way is to report bugs, another way is to help writing documentation (or correct the existing one. I think there is already a fair number of English mistakes in that document :-) ). You could also try writing patches implementing the features you want that are not yet in urpkg. Also, simply asking questions (that are not answered within this manual) is a great way to participate.
Whatever you decide to do, please send the content to sebastien dot
vasey at gmail dot com
Urpkg also has a webpage. See the urpkg webpage for the most up to date information.
So you have found a bug ? Great ! Please report it to me. But before doing that, ensure that...
The bug still exists in the latest version of urpkg
You are able to reproduce the bug.
When you report a bug, you should always, if possible
Include information on how to reproduce the bug
Include as verbose as possible output from your program. This means
running urpkg with the --debug
switch if possible.
Include the versions of urpkg on which the bug applies
(use --version
).
Include the output of urpkg
--info