diff options
Diffstat (limited to 'doc/manual')
-rw-r--r-- | doc/manual/builddependencies | 178 | ||||
-rw-r--r-- | doc/manual/buildroot | 122 | ||||
-rw-r--r-- | doc/manual/conditionalbuilds | 106 | ||||
-rw-r--r-- | doc/manual/dependencies | 370 | ||||
-rw-r--r-- | doc/manual/format | 273 | ||||
-rw-r--r-- | doc/manual/hregions | 89 | ||||
-rw-r--r-- | doc/manual/macros | 258 | ||||
-rw-r--r-- | doc/manual/multiplebuilds | 47 | ||||
-rw-r--r-- | doc/manual/queryformat | 173 | ||||
-rw-r--r-- | doc/manual/relocatable | 57 | ||||
-rw-r--r-- | doc/manual/signatures | 83 | ||||
-rw-r--r-- | doc/manual/spec | 217 | ||||
-rw-r--r-- | doc/manual/triggers | 165 | ||||
-rw-r--r-- | doc/manual/tsort | 159 |
14 files changed, 2297 insertions, 0 deletions
diff --git a/doc/manual/builddependencies b/doc/manual/builddependencies new file mode 100644 index 0000000..a3938fd --- /dev/null +++ b/doc/manual/builddependencies @@ -0,0 +1,178 @@ +/*! \page builddependencies Generating build dependencies automatically + +As we start updating packages for the next Red Hat distro, I'd like to see +packages start to make use of build dependencies. Basically build +dependencies are just like install dependencies, but they are resolved +against the build system just after parsing the spec file. Syntactically, +build dependencies look just like install dependencies in a spec file with +"Build" prefixed: + +\verbatim + BuildPreReq: + BuildRequires: + BuildConflicts: +\endverbatim + +All the above dependencies include versions, files, existence/range tests, etc. +The build dependency checking can also be turned off with --nodeps if necessary +just like install dependency checking can. Eventually, build dependencies will +be automated in rpm, but the major impediment to that effort is the engineering +required to maintain the pretense that src rpm's are "noarch". + +Meanwhile, I've added a package called "InDependence-1.0" to powertools-6.2 +that may be of use in detecting build dependencies that can be added to +spec files as part of rebuilding packages for Red Hat 6.2. + +Here's a short example of how to generate the package/file names that were used +while building gnorpm using InDependence: + +\verbatim + rpm -U /mnt/redhat/comps/powertools/6.2/i386/InDependence-1.0-3.i386.rpm + rpm -i /mnt/redhat/comps/dist/6.2/SRPMS/gnorpm-0.9-11.src.rpm + cd /usr/src/redhat/SPECS + dep -detail rpmbuild -ba gnorpm.spec >& xxx + ... + (the build will take longer since both dep and strace are pigs) + ... + grep -- '::' xxx > yyy +\endverbatim + +\verbatim +Aside: The dep perl wrapper is a "pig" only because it's exec'ing + rpm -qf <filename> + in order to turn filenames into package names. There are easier/faster + ways to get this information... + + There's no way to speed up the + /sbin/strace -q -etrace=open,execve -o ... + command itself. The eventual implementation in rpm will snatch the + same open/execve syscalls using LD_PRELOAD. + + Patches cheerfully accepted :-) +\endverbatim + +Here's what's in yyy (\<packagename\>::\<filename\> format): + +\verbatim + ORBit-devel-0.4.95-2::/usr/bin/orbit-config + XFree86-libs-3.3.5-6::/usr/X11R6/lib/libICE.so.6 + XFree86-libs-3.3.5-6::/usr/X11R6/lib/libSM.so.6 + XFree86-libs-3.3.5-6::/usr/X11R6/lib/libX11.so.6 + XFree86-libs-3.3.5-6::/usr/X11R6/lib/libXext.so.6 + audiofile-0.1.9-1::/usr/lib/libaudiofile.so.0 + autoconf-2.13-5::/usr/bin/autoconf + autoconf-2.13-5::/usr/bin/autoheader + autoconf-2.13-5::/usr/share/autoconf/acgeneral.m4 + autoconf-2.13-5::/usr/share/autoconf/autoconf.m4f + automake-1.4-5::/usr/bin/aclocal + automake-1.4-5::/usr/bin/automake + bash-1.14.7-16::/bin/sh + bash-1.14.7-16::/etc/bashrc + binutils-2.9.1.0.23-7::/usr/bin/strip + binutils-2.9.1.0.23-7::/usr/lib/libbfd-2.9.1.0.24.so + binutils-2.9.1.0.23-7::/usr/lib/libopcodes-2.9.1.0.24.so + bzip2-0.9.5c-1::/usr/lib/libbz2.so.0 + dev-2.7.10-2::/dev/null + diffutils-2.7-16::/usr/bin/cmp + egcs-1.1.2-25::/usr/bin/gcc + egcs-1.1.2-25::/usr/lib/gcc-lib/i386-redhat-linux/egcs-2.91.66/specs + esound-0.2.14-1::/usr/lib/libesd.so.0 + file-3.27-3::/usr/bin/file + file-3.27-3::/usr/share/magic + fileutils-4.0-8::/bin/chgrp + fileutils-4.0-8::/bin/chmod + fileutils-4.0-8::/bin/chown + fileutils-4.0-8::/bin/cp + fileutils-4.0-8::/bin/ln + fileutils-4.0-8::/bin/ls + fileutils-4.0-8::/bin/mkdir + fileutils-4.0-8::/bin/mv + fileutils-4.0-8::/bin/rm + fileutils-4.0-8::/usr/bin/install + findutils-4.1-32::/usr/bin/xargs + gawk-3.0.4-1::/bin/awk + gawk-3.0.4-1::/bin/gawk + gettext-0.10.35-13::/usr/bin/xgettext + glib-1.2.5-1::/usr/lib/libglib-1.2.so.0 + glib-1.2.5-1::/usr/lib/libgmodule-1.2.so.0 + glib-devel-1.2.5-1::/usr/bin/glib-config + glibc-2.1.2-13::/etc/localtime + glibc-2.1.2-13::/etc/nsswitch.conf + glibc-2.1.2-13::/lib/ld-linux.so.2 + glibc-2.1.2-13::/lib/libc.so.6 + glibc-2.1.2-13::/lib/libcrypt.so.1 + glibc-2.1.2-13::/lib/libdb.so.2 + glibc-2.1.2-13::/lib/libdl.so.2 + glibc-2.1.2-13::/lib/libm.so.6 + glibc-2.1.2-13::/lib/libnsl.so.1 + glibc-2.1.2-13::/lib/libnss_dns.so.2 + glibc-2.1.2-13::/lib/libnss_files.so.2 + glibc-2.1.2-13::/lib/libnss_nis.so.2 + glibc-2.1.2-13::/lib/libnss_nisplus.so.2 + glibc-2.1.2-13::/lib/libresolv.so.2 + glibc-2.1.2-13::/usr/bin/ldd + gnome-libs-1.0.54-1::/usr/lib/libart_lgpl.so.2 + gnome-libs-1.0.54-1::/usr/lib/libgnome.so.32 + gnome-libs-1.0.54-1::/usr/lib/libgnomesupport.so.0 + gnome-libs-1.0.54-1::/usr/lib/libgnomeui.so.32 + gnome-libs-devel-1.0.54-1::/usr/bin/gnome-config + grep-2.3-2::/bin/egrep + grep-2.3-2::/bin/fgrep + grep-2.3-2::/bin/grep + gtk+-1.2.5-2::/usr/lib/libgdk-1.2.so.0 + gtk+-1.2.5-2::/usr/lib/libgtk-1.2.so.0 + imlib-1.9.7-1::/usr/lib/libgdk_imlib.so.1 + libghttp-1.0.4-1::/usr/lib/libghttp.so.1 + libtool-1.3.3-1::/usr/bin/libtoolize + libtool-1.3.3-1::/usr/share/libtool/config.guess + libtool-1.3.3-1::/usr/share/libtool/config.sub + libtool-1.3.3-1::/usr/share/libtool/ltconfig + libtool-1.3.3-1::/usr/share/libtool/ltmain.sh + libxml-1.4.0-1::/usr/lib/libxml.so.1 + libxml-devel-1.4.0-1::/usr/bin/xml-config + m4-1.4-12::/usr/bin/m4 + make-3.77-6::/usr/bin/make + mktemp-1.5-1::/bin/mktemp + net-tools-1.53-1::/bin/hostname + patch-2.5-9::/usr/bin/patch + rootfiles-5.2-5::/root/.bashrc + rpm-3.0.4-0.16::/bin/rpm + rpm-3.0.4-0.16::/usr/lib/librpm.so.0 + rpm-3.0.4-0.16::/usr/lib/rpm/find-provides + rpm-3.0.4-0.16::/usr/lib/rpm/find-requires + rpm-3.0.4-0.16::/usr/lib/rpm/macros + rpm-3.0.4-0.16::/usr/lib/rpm/rpmpopt + rpm-3.0.4-0.16::/usr/lib/rpm/rpmrc + sed-3.02-4::/bin/sed + setup-2.0.5-1::/etc/group + setup-2.0.5-1::/etc/host.conf + setup-2.0.5-1::/etc/passwd + sh-utils-2.0-1::/bin/basename + sh-utils-2.0-1::/bin/false + sh-utils-2.0-1::/bin/sleep + sh-utils-2.0-1::/bin/true + sh-utils-2.0-1::/usr/bin/expr + sh-utils-2.0-1::/usr/bin/id + texinfo-3.12h-2::/usr/bin/makeinfo + textutils-2.0-2::/bin/cat + textutils-2.0-2::/bin/sort + textutils-2.0-2::/usr/bin/cut + textutils-2.0-2::/usr/bin/tr + zlib-1.1.3-5::/usr/lib/libz.so.1 +\endverbatim + +The information can be used to generate build prerequisites. What is still +needed is a sensible approach on + +\verbatim + 1) eliminating obvious common dependencies (e.g. libtool, egcs). + 2) identifying (and removing for now) per-platform build dependencies. + 3) deciding on whether to add the build dependency on a file or on the + package that contains the file. + 4) if adding a dependency on a package, choosing version ranges as + appropriate. +\endverbatim + +but that's up to individual packagers. + +*/ diff --git a/doc/manual/buildroot b/doc/manual/buildroot new file mode 100644 index 0000000..3bf0b05 --- /dev/null +++ b/doc/manual/buildroot @@ -0,0 +1,122 @@ +/*! \page buildroot Using a build root + +The build root is very similar to Root: (which is now legacy). +By using Buildroot: in your spec file you are indicating +that your package can be built (installed into and packaged from) +a user-definable directory. This helps package building by normal +users. + +\section buildroot_specfile The Spec File + +Simply use +\verbatim + Buildroot: <dir> +\endverbatim + +in your spec file. The actual buildroot used by RPM during the +build will be available to you (and your %prep, %build, and %install +sections) as the environment variable RPM_BUILD_ROOT. You must +make sure that the files for the package are installed into the +proper buildroot. As with Root:, the files listed in the %files +section should *not* contain the buildroot. For example, the +following hypothetical spec file: + +\verbatim + Name: foo + ... + Root: /tmp + + %prep + ... + + %build + ... + + %install + install -m755 fooprog /tmp/usr/bin/fooprog + + %files + /usr/bin/fooprog +\endverbatim + +would be changed to: + +\verbatim + Name: foo + ... + BuildRoot: /tmp + + %prep + ... + + %build + ... + + %install + install -m755 fooprog $RPM_BUILD_ROOT/usr/bin/fooprog + + %files + /usr/bin/fooprog +\endverbatim + +\section buildroot_building Building With a Build Root + +RPM will use the buildroot listed in the spec file as the default +buildroot. There are two ways to override this. First, you can +have "buildroot: <dir>" in your rpmrc. Second, you can override +the default, and any entry in an rpmrc by using "--buildroot <dir>" +on the RPM command line. + +\section buildroot_caveats Caveats using Build Roots + +Care should be taken when using buildroots that the install directory +is owned by the correct package. For example the file + +\verbatim + /usr/lib/perl5/site_perl/MD5.pm +\endverbatim + +is installed by the package perl-MD5. If we were to use a buildroot +and specified + +\verbatim + %files + /usr/lib/perl5/site_perl +\endverbatim + +we would end up with the directory /usr/lib/perl5/site_perl being +owned by the library package. This directory is in fact used by ALL +perl libraries and should be owned by the package for perl not any of +its libraries. It is important that the %files command specifies all +the known directories explicitly. So this would be preferable: + +\verbatim + /usr/lib/perl5/site_perl/* +\endverbatim + +Since we only want the files and directories that the package perl-MD5 +installed into /usr/lib/perl5/site_perl/ to be owned by the package. +The directory /usr/lib/perl5/site_perl/ is created when perl is +installed. + +If we were to use the bad %files line shown above, then when the MD5 +package is removed, RPM will try to remove each of the perl-MD5 files and +then try to remove the dir itself. If there's still files in the +site_perl directory (e.g. from other packages) then the Unix rmdir(2) +will fail and you will get a non-zero return code from RPM. If the +rmdir succeeds then you will no longer have a site_perl directory on +your machine even though this directory was created when Perl was +installed. + +The other common problem is that two packages could install two files +with the the same name into the same directory. This would lead to +other collision problems when removing the file. Care should be taken +by the packager to ensure that all packages install unique files. +Explicit use of %files can help make the packager aware of potential +problems before they happen. When you try to install a package which +contains file names already used by other packages on the system then +RPM will warn you of the problem and give a fatal error. This error can +be overridden with --force and the installed file will be replaced by the +new file and when the new package is removed the file will be removed as well. + +*/ diff --git a/doc/manual/conditionalbuilds b/doc/manual/conditionalbuilds new file mode 100644 index 0000000..b7b5d2c --- /dev/null +++ b/doc/manual/conditionalbuilds @@ -0,0 +1,106 @@ +/*! \page conditionalbuilds Passing conditional parameters into a rpm build + +Source code is often built with optional features enabled or disabled. +When source code is packaged using rpm, the various features can be +chosen, added to a spec file, and a package will be produced with +binaries compiled with that feature set. This mechanism works fine +for packages with small feature sets, but does not work so well +for large, complicated, packages like the Linux kernel and/or +the Pine mailer which have a large number of features, as a given +feature set may not "work" for everyone. + +RPM now has a supported mechanism to pass information from the rpm +command line to enable/disable features during a build. Two options have +been added to pass feature names from the rpm command line: +\verbatim + --with <feature> Enable <feature> + --without <feature> Disable <feature> +\endverbatim +The new options are implemented using popt to add aliases to the existing rpm +options --define to specify macros from the command line. The magic necessary +to add the new options is (from the file /usr/lib/rpm/rpmpopt*) +\verbatim + rpmb alias --with --define "_with_!#:+ --with-!#:+" + rpmb alias --without --define "_without_!#:+ --without-!#:+" +\endverbatim +(Note: The obscure "!#:+" popt token above says "substitute the next command +line argument found here, and, additionally, mark the argument as used.") + +For example, when rpm is invoked as +\verbatim + rpm ... --with ldap ... +\endverbatim +then the popt aliases will cause the options to be rewritten as +\verbatim + rpm ... --define "_with_ldap --with-ldap" ... +\endverbatim +which causes a "%_with_ldap" macro to be defined with value "--with-ldap" +during a build. + +The macro defined on the rpm command line can be used to conditionalize +portions of the spec file for the package. For example, let's say you +are trying to build the pine package using "--with ldap" to enable the +LDAP support in the pine mailer (i.e. configuring with "--with-ldap"). +So the spec file should be written +\verbatim + ... + ./configure \ + %{?_with_ldap} \ + ... +\endverbatim +so that, if "--with ldap" was used as a build option, then configure +will be invoked (after macro expansion) as +\verbatim + ./configure --with-ldap ... +\endverbatim +(Note: The obscure "%{?_with_ldap: ...}" rpm macro syntax above says "if the +macro "_with_ldap" exists, then expand "...", else ignore.") + +The spec file should include a default value for the "_with_ldap" macro, +and should support "--without ldap" as well. Here's a more complete example +for pine: +\verbatim + # Default values are --without-ldap --with-ssl. + # + # Read: If neither macro exists, then add the default definition. + %{!?_with_ldap: %{!?_without_ldap: %define _without_ldap --without-ldap}} + %{!?_with_ssl: %{!?_without_ssl: %define _with_ssl --with-ssl}} + ... + + # You might want to make sure that one and only one of required and + # mutually exclusive options exists. + # + # Read: It's an error if both or neither required options exist. + %{?_with_ssl: %{?_without_ssl: %{error: both _with_ssl and _without_ssl}}} + %{!?_with_ssl: %{!?_without_ssl: %{error: neither _with_ssl nor _without_ssl}}} + + # Add build dependencies for ssl and ldap features if enabled. + # Note: Tag tokens must start at beginning-of-line. + # + # Read: If feature is enabled, then add the build dependency. + %{?_with_ssl:BuildRequires: openssl-devel} + %{?_with_ldap:BuildRequires: openldap-devel} + ... + + # Configure with desired features. + # + # Read: Add any defined feature values to the configure invocation. + %configure \ + %{?_with_ssl} \ + %{?_without_ssl} \ + %{?_with_ldap} \ + %{?_without_ldap} + ... + + # Conditional tests for desired features. + # + # Read: true if _with_ssl is defined, false if not defined. + %if %{?_with_ssl:1}%{!?_with_ssl:0} + ... + %endif + +\endverbatim + +See also the %bcond_with and %bcond_without helper macros and their +documentation in /usr/lib/rpm/macros. +*/ diff --git a/doc/manual/dependencies b/doc/manual/dependencies new file mode 100644 index 0000000..810e266 --- /dev/null +++ b/doc/manual/dependencies @@ -0,0 +1,370 @@ +/*! \page dependencies Dependencies + +Dependencies provide a way for a package builder to require other +packages or capabilities to be installed before or simultaneously +with one another. These can be used to require a python interpreter +for a python based application for example. RPM ensures dependencies +are satisfied whenever packages are installed, erased, or upgraded. + +\section dependencies_package Requiring Packages + +To require the packages python and perl, use: + +\verbatim + Requires: python perl +\endverbatim + +in the spec file. Note that "Requires python, perl" would work as well. If you +needed to have a very recent version of python but any version of perl, + +\verbatim + Requires: python >= 1.3, perl +\endverbatim + +would do the trick. Again, the ',' in the line is optional. Instead of +'>=', you may also use '<', '>', '<=', or '='. Spaces are required +around the numeric operator to separate the operator from the package name. + +The full syntax for specifying a dependency on an epoch, version and release +is +\verbatim + [epoch:]version[-release] +\endverbatim +where +\verbatim + epoch (optional) number, with assumed default of 0 if not supplied + version (required) can contain any character except '-' + release (optional) can contain any character except '-' +\endverbatim + +For example, + +\verbatim + Requires: perl >= 9:5.00502-3 +\endverbatim + +specifies + +\verbatim + epoch=9 + version=5.00502 + release=3 +\endverbatim + +The epoch (if present) is a monotonically increasing integer, neither the +version or the release can contain the '-' hyphen character, and the dependency +parser does not permit white space within a definition. Unspecified epoch +and releases are assumed to be zero, and are interpreted as "providing all" +or "requiring any" value. + +The release tag is usually incremented every time a package is rebuilt for +any reason, even if the source code does not change. For example, changes +to the specfile, compiler(s) used to build the package, and/or dependency +changes should all be tracked by incrementing the release. The version number, +on the other hand, is usually set by the developer or upstream maintainer, +and should not be casually modified by the packager. + +Version numbering should be kept simple so that it is easy to determine the +version ordering for any set of packages. If the packager needs to separate +a release from all other releases that came before it, then the epoch, the +most significant part of package ordering, can be changed. + +The algorithm that RPM uses to determine the version ordering of +packages is simple and developers are encouraged not to rely on the +details of its working. Developers should keep their numbering scheme +simple so any reasonable ordering algorithm would work. The version +comparison algorithm is in the routine rpmvercmp() and it is just a segmented +strcmp(3). First, the boundaries of the segments are found using +isdigit(3)/isalpha(3). Each segment is then compared in order with the +right most segment being the least significant. The alphabetical +portions are compared using a lexical graphical ascii ordering, the +digit segments strip leading zeroes and compare the strlen before +doing a strcmp. If both numerical strings are equal, the longer string +is larger. Notice that the algorithm has no knowledge of decimal fractions, +and perl-5.6 is "older" than perl-5.00503 because the number 6 is less than +the number 503. + +The concept of "newer" used by rpm to determine when a package should be +upgraded can be broken if version format changes oddly, such as when the +version segments cannot be meaningfully compared. + +Example of a bad format change: 2.1.7Ax to 19980531 +\verbatim + The date may be the older version, but it is numerically greater + 2 so it is considered newer :( +\endverbatim + +Example of a bad increment: 2.1.7a to 2.1.7A +\verbatim + The 'a' (ASCII 97) is compared against 'A' (ASCII 65), making 2.1.7a + the newer version. +\endverbatim + +Stick to major.minor.patchlevel using numbers for each if you can. +Keeps life simple :-) + +If a Requires: line needs to include an epoch in the comparison, then +the line should be written like + +\verbatim + Requires: somepackage = 23:version +\endverbatim + +You can't continue a "Requires: " line. If you have multiple +"Requires: " lines then the package requires all packages mentioned on +all of the lines to be installed. + +\section dependencies_prereqs Prereqs + +Prereqs are different from requires only in that a PreReq is guaranteed +to be installed before the package that contains the PreReq. PreReq's +are used only to order packages, otherwise PreReq's are exactly the same +as a Requires: dependency. + +\section dependencies_virtual Virtual Packages + +Sometimes you need to make sure the system your package is being installed +on has a package which provides a certain capability, even though you don't +care what specific package provides it. For example, sendmail won't work +properly unless a local delivery agent (lda) is present. You can ensure that +one is installed like this: + +\verbatim + Requires: lda +\endverbatim + +This will match either a package called lda (as mentioned above), or any +package which contains: + +\verbatim + Provides: lda +\endverbatim + +in its .spec file. No version numbers may be used with virtual packages. + +Virtual packages are often used to supply file dependencies such as /bin/sh +on machines that are only partly managed by rpm. A virtual package with +\verbatim + Provides: /bin/sh +\endverbatim +differs from a package that has /bin/sh in the %files list in that the +package can be safely removed without removing /bin/sh. + +\section dependencies_automatic Automatic Dependencies + +To reduce the amount of work required by the package builder, RPM scans +the file list of a package when it is being built. Any files in the file +list which require shared libraries to work (as determined by ldd) cause +that package to require the shared library. + +For example, if your package contains /bin/vi, RPM will add dependencies +for both libtermcap.so.2 and libc.so.5. These are treated as virtual +packages, so no version numbers are used. + +A similar process allows RPM to add Provides information automatically. Any +shared library in the file list is examined for its soname (the part of +the name which must match for two shared libraries to be considered +equivalent) and that soname is automatically provided by the package. For +example, the libc-5.3.12 package has provides information added for +libm.so.5 and libc.so.5. We expect this automatic dependency generation +to eliminate the need for most packages to use explicit Requires: lines. + +\section dependencies_custom Custom Automatic Dependency + +The automatic dependency programs are found via macro expansion. Thus +sites can very the amount of dependency processing that are performed +locally, by changing the executable/script which is run. Dependency +processing can even be changed on a per-package basis if the macros are +defined in the spec file. To allow for maximum configurability the +dependency programs are shell scripts which can be duplicated and edited +for site specific needs. + +The macros: %__find_provides, %__find_prereq, %__find_requires, +%__find_conflicts, %__find_obsoletes, if they exist, are expanded to +the name of a program to exec. For each package, the program receives +the glob'ed %files manifest on stdin and returns dependencies on stdout. The +discovered dependencies are parsed exactly as if they were found after + +\verbatim + Provides: + PreReq: + Requires: + Conflicts: + Obsoletes: +\endverbatim +tokens in a spec file (i.e. the same parser is used), so items look like +(comments added) +\verbatim + /bin/sh # file existence + libc.so.6 # soname existence + foo <= 1:2.3-4 # versioned package + perl5(Apache) <= 1.2 # versioned namespace +\endverbatim + +The default rpm configuration has only + %__find_provides /usr/lib/rpm/find-provides + %__find_requires /usr/lib/rpm/find-requires +which can be overridden (or even undefined) within a spec file. + +\section dependencies_interpreters Interpreters and Shells + +Modules for interpreted languages like perl and tcl impose additional +dependency requirements on packages. A script written for an interpreter +often requires language specific modules to be installed in order to execute +correctly. In order to automatically detect language specific modules, each +interpreter may have its own find-provides and find-requires. To prevent +module name collisions between interpreters, module names are enclosed within +parentheses and a conventional interpreter specific identifier is prepended: + + +\verbatim + Provides: perl(MIME-Base64), perl(Mail-Header)-1-09 + + Requires: perl(Carp), perl(IO-Wrap) = 4.5 +\endverbatim + + +The output of a per-interpreter find-requires (notice in this example the +first requirement is a package and the rest are language specific modules) + +\verbatim + Mail-Header >= 1.01 + perl(Carp) >= 3.2 + perl(IO-Wrap) == 4.5 or perl(IO-Wrap)-4.5 +\endverbatim + +the output from find-provides is +\verbatim + Foo-0.9 + perl(Widget)-0-1 +\endverbatim + +The per-interpreter automatic module detectors will normally be located in +\verbatim + /usr/lib/rpm/{perl,tcl}/find-{provides,requires} +with appropriate per-interpreter hooks into +\verbatim + /usr/lib/rpm/find-{provides,requires} +\endverbatim + +@todo per-interpreter dependency generators are not located in subdirectories. + +Notice that shell dependencies will require that all %post et al scriptlets +be processed by the find-requires. Since a shell script depends on all the +programs which it runs. + + +\section dependencies_installing Installing and Erasing Packages with Dependencies + +For the most part, dependencies should be transparent to the user. However, +a few things will change. + +First, when packages are added or upgraded, all of their dependencies +must be satisfied. If they are not, an error message like this appears: + +\verbatim + failed dependencies: + libICE.so.6 is needed by somepackage-2.11-1 + libSM.so.6 is needed by somepackage-2.11-1 + libc.so.5 is needed by somepackage-2.11-1 +\endverbatim + +Similarly, when packages are removed, a check is made to ensure that +no installed packages will have their dependency conditions break due to +the packages being removed. If you wish to turn off dependency checking for +a particular command, use the --nodeps flag. + +\section dependencies_conflicts Conflicts + +While conflicts were implemented in earlier versions of RPM they never +worked properly until RPM 2.3.4 (well, we hope they work properly now +anyway). + +Conflicts allow a package to say it won't work with another package (or +virtual package) installed on the system. For example, qmail doesn't work +(w/o custom setup) on machines with sendmail installed. The qmail spec file +may codify this with a line like: + +\verbatim + Conflicts: sendmail +\endverbatim + +The syntax of the "Conflicts" tag is identical to the syntax of the Requires +tag and conflict checking may be overridden by using the --nodeps flag. + +\section dependencies_querying Querying for Dependencies + +Two new query information selection options are now available. The first, +--provides, prints a list of all of the capabilities a package provides. +The second, --requires, shows the other packages that a package requires +to be installed, along with any version number checking. + +There are also two new ways to search for packages. Running a query with +--whatrequires \<item\> queries all of the packages that require \<item\>. +Similarly, running --whatprovides \<item\> queries all of the packages that +provide the \<item\> virtual package. Note that querying for package that +provides "python" will not return anything, as python is a package, not +a virtual package. + +\section dependencies_verifying Verifying Dependencies + +As of RPM 2.2.2, -V (aka --verify) verifies package dependencies +by default. You can tell rpm to ignore dependencies during system +verification with the --nodeps. If you want RPM to verify just dependencies +and not file attributes (including file existence), use the --nofiles +flag. Note that "rpm -Va --nofiles --nodeps" will not verify anything at +all, nor generate an error message. + +\section dependencies_branching Branching Version + +It is quite common to need to branch a set of sources in version +control. It is not so obvious how those branches should be represented +in the package version numbers. Here is one solution. + +You have a bag of features that are injected into a package in a +non-ordered fashion, and you want to have the package +name-version-release be able to: + +\verbatim + 1) identify the "root version" of the source code. + 2) identify the handful of features that are in that + branch of the package. + 3) preserve sufficient ordering so that packages upgrade + without the use of --oldpackage. +\endverbatim + +A simple (but possibly not adequate) scheme to achieve this is: + +\verbatim + Name: foo + Version: <the "root version" of the source code> + Release: <release instance>.<branch> +\endverbatim + +where the release instance is something like YYYMMMDD or some linear +record of the number of builds with the current tar file, it is used +to preserve ordering when necessary. + +Another alternative scheme might be: + +\verbatim + Name: foo + Epoch: <branch> + Version: <the branch specific version of the code> + Release: <release instance> +\endverbatim + +\section dependencies_build Build dependencies + +The following dependencies are available at build time. These are +similar to the install time version but these apply only during +package creation and are specified in the specfile not in the binary +package. + +\verbatim + BuildRequires: + BuildConflicts: + BuildPreReq: +\endverbatim + +*/ diff --git a/doc/manual/format b/doc/manual/format new file mode 100644 index 0000000..521387b --- /dev/null +++ b/doc/manual/format @@ -0,0 +1,273 @@ +/*! \page pkgformat Package format + +This document describes the RPM file format version 3.0, which is used +by RPM versions 2.1 and greater. The format is subject to change, and +you should not assume that this document is kept up to date with the +latest RPM code. That said, the 3.0 format should not change for +quite a while, and when it does, it will not be 3.0 anymore :-). + +\warning In any case, THE PROPER WAY TO ACCESS THESE STRUCTURES IS THROUGH +THE RPM LIBRARY!! + +The RPM file format covers both source and binary packages. An RPM +package file is divided in 4 logical sections: + +\verbatim +. Lead -- 96 bytes of "magic" and other info +. Signature -- collection of "digital signatures" +. Header -- holding area for all the package information (aka "metadata") +. Payload -- compressed archive of the file(s) in the package (aka "payload") +\endverbatim + +All 2 and 4 byte "integer" quantities (int16 and int32) are stored in +network byte order. When data is presented, the first number is the +byte number, or address, in hex, followed by the byte values in hex, +followed by character "translations" (where appropriate). + +\section pkgformat_lead Lead + +The Lead is basically for file(1). All the information contained in +the Lead is duplicated or superceded by information in the Header. +Much of the info in the Lead was used in old versions of RPM but is +now ignored. The Lead is stored as a C structure: + +\code +struct rpmlead { + unsigned char magic[4]; + unsigned char major, minor; + short type; + short archnum; + char name[66]; + short osnum; + short signature_type; + char reserved[16]; +}; +\endcode + +and is illustrated with one pulled from the rpm-2.1.2-1.i386.rpm +package: + +\verbatim +00000000: ed ab ee db 03 00 00 00 +\endverbatim + +The first 4 bytes (0-3) are "magic" used to uniquely identify an RPM +package. It is used by RPM and file(1). The next two bytes (4, 5) +are int8 quantities denoting the "major" and "minor" RPM file format +version. This package is in 3.0 format. The following 2 bytes (6-7) +form an int16 which indicates the package type. As of this writing +there are only two types: 0 == binary, 1 == source. + +\verbatim +00000008: 00 01 72 70 6d 2d 32 2e ..rpm-2. +\endverbatim + +The next two bytes (8-9) form an int16 that indicates the architecture +the package was built for. While this is used by file(1), the true +architecture is stored as a string in the Header. See, lib/misc.c for +a list of architecture->int16 translations. In this case, 1 == i386. +Starting with byte 10 and extending to byte 75, are 65 characters and +a null byte which contain the familiar "name-version-release" of the +package, padded with null (0) bytes. + +\verbatim +00000010: 31 2e 32 2d 31 00 00 00 1.2-1... +00000018: 00 00 00 00 00 00 00 00 ........ +00000020: 00 00 00 00 00 00 00 00 ........ +00000028: 00 00 00 00 00 00 00 00 ........ +00000030: 00 00 00 00 00 00 00 00 ........ +00000038: 00 00 00 00 00 00 00 00 ........ +00000040: 00 00 00 00 00 00 00 00 ........ +00000048: 00 00 00 00 00 01 00 05 ........ +\endverbatim + +Bytes 76-77 ("00 01" above) form an int16 that indicates the OS the +package was built for. In this case, 1 == Linux. The next 2 bytes +(78-79) form an int16 that indicates the signature type. This tells +RPM what to expect in the Signature. For version 3.0 packages, this +is 5, which indicates the new "Header-style" signatures. + +\verbatim +00000050: 04 00 00 00 68 e6 ff bf ........ +00000058: ab ad 00 08 3c eb ff bf ........ +\endverbatim + +The remaining 16 bytes (80-95) are currently unused and are reserved +for future expansion. + +\section pkgformat_signature Signature + +A 3.0 format signature (denoted by signature type 5 in the Lead), uses +the same structure as the Header. For historical reasons, this +structure is called a "header structure", which can be confusing since +it is used for both the Header and the Signature. The details of the +header structure are given below, and you'll want to read them so the +rest of this makes sense. The tags for the Signature are defined in +lib/signature.h. + +The Signature can contain multiple signatures, of different types. +There are currently only three types, each with its own tag in the +header structure: + +\verbatim + Name Tag Header Type + ---- ---- ----------- + SIZE 1000 INT_32 + MD5 1001 BIN + PGP 1002 BIN +\endverbatim + +The MD5 signature is 16 bytes, and the PGP signature varies with +the size of the PGP key used to sign the package. + +As of RPM 2.1, all packages carry at least SIZE and MD5 signatures, +and the Signature section is padded to a multiple of 8 bytes. + +\section pkgformat_header Header + +The Header contains all the information about a package: name, +version, file list, etc. It uses the same "header structure" as the +Signature, which is described in detail below. A complete list of the +tags for the Header would take too much space to list here, and the +list grows fairly frequently. For the complete list see lib/rpmlib.h +in the RPM sources. + +\section pkgformat_payload Payload + +The Payload is currently a gzipped cpio archive. The cpio +archive type used is SVR4 with a CRC checksum. + +\section pkgformat_header_structure The Header Structure + +The header structure is a little complicated, but actually performs a +very simple function. It acts almost like a small database in that it +allows you to store and retrieve arbitrary data with a key called a +"tag". When a header structure is written to disk, the data is +written in network byte order, and when it is read from disk, is is +converted to host byte order. + +Along with the tag and the data, a data "type" is stored, which indicates, +obviously, the type of the data associated with the tag. There are +currently 9 types: + +\verbatim + Type Number + ---- ------ + NULL 0 + CHAR 1 + INT8 2 + INT16 3 + INT32 4 + INT64 5 + STRING 6 + BIN 7 + STRING_ARRAY 8 + I18NSTRING_TYPE 9 +\endverbatim + +One final piece of information is a "count" which is stored with each +tag, and indicates the number of items of the associated type that are +stored. As a special case, the STRING type is not allowed to have a +count greater than 1. To store more than one string you must use a +STRING_ARRAY. + +Altogether, the tag, type, count, and data are called an "Entry" or +"Header Entry". + +\verbatim +00000000: 8e ad e8 01 00 00 00 00 ........ +\endverbatim + +A header begins with 3 bytes of magic "8e ad e8" and a single byte to +indicate the header version. The next four bytes (4-7) are reserved. + +\verbatim +00000008: 00 00 00 20 00 00 07 77 ........ +\endverbatim + +The next four bytes (8-11) form an int32 that is a count of the number +of entries stored (in this case, 32). Bytes 12-15 form an int32 that +is a count of the number of bytes of data stored (that is, the number +of bytes made up by the data portion of each entry). In this case it +is 1911 bytes. + +\verbatim +00000010: 00 00 03 e8 00 00 00 06 00 00 00 00 00 00 00 01 ................ +\endverbatim + +Following the first 16 bytes is the part of the header called the +"index". The index is made of up "index entries", one for each entry +in the header. Each index entry contains four int32 quantities. In +order, they are: tag, type, offset, count. In the above example, we +have tag=1000, type=6, offset=0, count=1. By looking up the the tag +in lib/rpmlib.h we can see that this entry is for the package name. +The type of the entry is a STRING. The offset is an offset from the +start of the data part of the header to the data associated with this +entry. The count indicates that there is only one string associated +with the entry (which we really already knew since STRING types are +not allowed to have a count greater than 1). + +In our example there would be 32 such 16-byte index entries, followed +by the data section: + +\verbatim +00000210: 72 70 6d 00 32 2e 31 2e 32 00 31 00 52 65 64 20 rpm.2.1.2.1.Red +00000220: 48 61 74 20 50 61 63 6b 61 67 65 20 4d 61 6e 61 Hat Package Mana +00000230: 67 65 72 00 31 e7 cb b4 73 63 68 72 6f 65 64 65 ger.1...schroede +00000240: 72 2e 72 65 64 68 61 74 2e 63 6f 6d 00 00 00 00 r.redhat.com.... +... +00000970: 6c 69 62 63 2e 73 6f 2e 35 00 6c 69 62 64 62 2e libc.so.5.libdb. +00000980: 73 6f 2e 32 00 00 so.2.. +\endverbatim + +The data section begins at byte 528 (4 magic, 4 reserved, 4 index +entry count, 4 data byte count, 16 * 32 index entries). At offset 0, +bytes 528-531 are "rpm" plus a null byte, which is the data for the +first index entry (the package name). Following is is the data for +each of the other entries. Each string is null terminated, the strings +in a STRING_ARRAY are also null terminated and are place one after +another. The integer types are aligned to appropriate byte boundaries, +so that the data of INT64 type starts on an 8 byte boundary, INT32 +type starts on a 4 byte boundary, and an INT16 type starts on a 2 byte +boundary. For example: + +\verbatim +00000060: 00 00 03 ef 00 00 00 06 00 00 00 28 00 00 00 01 ................ +00000070: 00 00 03 f1 00 00 00 04 00 00 00 40 00 00 00 01 ................ +... +00000240: 72 2e 72 65 64 68 61 74 2e 63 6f 6d 00 00 00 00 r.redhat.com.... +00000250: 00 09 9b 31 52 65 64 20 48 61 74 20 4c 69 6e 75 ....Red Hat Linu +\endverbatim + +Index entry number 6 is the BUILDHOST, of type STRING. Index entry +number 7 is the SIZE, of type INT32. The corresponding data for entry +6 end at byte 588 with "....redhat.com\0". The next piece of data +could start at byte 589, byte that is an improper boundary for an INT32. +As a result, 3 null bytes are inserted and the date for the SIZE actually +starts at byte 592: "00 09 9b 31", which is 629553). + +\section pkgformat_tools Tools + +The tools directory in the RPM sources contains a number of small +programs that use the RPM library to pick apart packages. These +tools are mostly used for debugging, but can also be used to help +you understand the internals of the RPM package format. + +\verbatim + rpmlead - extracts the Lead from a package + rpmsignature - extracts the Signature from a package + rpmheader - extracts the Header from a package + rpmarchive - extracts the Archive from a package + dump - displays a header structure in readable format +\endverbatim + +Given a package foo.rpm you might try: + +\verbatim + rpmlead foo.rpm | od -x + rpmsignature foo.rpm | dump + rpmheader foo.rpm | dump + rpmarchive foo.rpm | zcat | cpio --list +\endverbatim + +*/ diff --git a/doc/manual/hregions b/doc/manual/hregions new file mode 100644 index 0000000..1bdb4f1 --- /dev/null +++ b/doc/manual/hregions @@ -0,0 +1,89 @@ +/*! \page hregions Immutable header regions in rpm-4.0.1 and later + +The header data structure has changed in rpm-4.0.[12] to preserve the +original header from a package. The goal is to keep the original +header intact so that metadata can be verified separately from the +payload by the RHN up2date client and by the rpm command line verify +mode using signatures saved in the rpm database. I believe the change +is entirely forward and backward compatible, and will not require +any artifacts like changing the version number of packaging or +adding an "rpmlib(...)" tracking dependency. We'll see ... + +Here's a short description of the change. An rpm header has three sections: +\verbatim + 1) intro (# entries in index, # bytes of data) + 2) index 16 byte entries, one per tag, big endian + 3) data tag values, properly aligned, big endian +\endverbatim + +Representing sections in the header (ignoring the intro) with +\verbatim + A,B,C index entries sorted by tag number + a,b,c variable length entry data + | boundary between index/data +\endverbatim +a header with 3 tag/value pairs (A,a) can be represented something like +\verbatim + ABC|abc +\endverbatim + +The change is to introduce a new tag that keeps track of a contiguous +region (i.e. the original header). Representing the boundaries with +square/angle brackets, an "immutable region" in the header thus becomes +\verbatim + [ABC|abc] +\endverbatim +or more generally (spaces added for clarity) +\verbatim + [ABC> QRS | <abc] qrs +\endverbatim +or with concatenated regions (not implemented yet) +\verbatim + [ABC> [DEF> QRS | <abc] <def] qrs +\endverbatim +or with nested regions (not implemented yet) +\verbatim + [ABC [DEF>> QRS | <<abc] def] qrs +\endverbatim + +\todo Either concatenated/nested regions may be used to implement +a metarpm, aka a package of packages, dunno how, when, or even if, yet. + +What complicates the above is legacy issues, as various versions of rpm +have added/deleted/modified entries in the header freely. Thus, representing +altered tag entries/data with a '.', there is a need to preserve deleted +information something like + +\verbatim + [A.C> QRS XYZ | <a.c] qrs xyz +\endverbatim + +\note This is basically the change that replaces the filename with + a {dirname,basename,dirindex} triple between rpm-3.x and rpm-4.x. + +or + +\verbatim + [AB.> QRS D | <ab.] qrs d +\endverbatim + +\note The header is no longer sorted because of replacing Cc with Dd. + +and yet permit retrieval of the original + +\verbatim + [ABC|abc] +\endverbatim + +region. PITA, really. + +What made header regions trickier yet is the desire to have an implementation +that is both backward and forward compatible. I won't bore you with the +tedious details. + +However, even after doing regressions against supported Red Hat releases, +there's a Great Big Universe of rpm packages out there, and I'm *very* +interested in hearing (as bug reports against rpm at http://bugzilla.redhat.com) +about any and all problems with header regions in rpm-4.0.1. + +*/ diff --git a/doc/manual/macros b/doc/manual/macros new file mode 100644 index 0000000..fea9bf3 --- /dev/null +++ b/doc/manual/macros @@ -0,0 +1,258 @@ +/*! \page macros Macro syntax + +RPM has fully recursive spec file macros. Simple macros do straight text +substitution. Parameterized macros include an options field, and perform +argc/argv processing on white space separated tokens to the next newline. +During macro expansion, both flags and arguments are available as macros +which are deleted at the end of macro expansion. Macros can be used +(almost) anywhere in a spec file, and, in particular, in "included file +lists" (i.e. those read in using %files -f \<file\>). In addition, macros +can be nested, hiding the previous definition for the duration of the +expansion of the macro which contains nested macros. + +\section macros_defining Defining a Macro + +To define a macro use: + +\verbatim + %define <name>[(opts)] <body> +\endverbatim + +All whitespace surrounding \<body\> is removed. Name may be composed +of alphanumeric characters, and the character `_' and must be at least +3 characters in length. A macro without an (opts) field is "simple" in that +only recursive macro expansion is performed. A parameterized macro contains +an (opts) field. The opts (i.e. string between parentheses) is passed +exactly as is to getopt(3) for argc/argv processing at the beginning of +a macro invocation. While a parameterized macro is being expanded, the +following shell-like macros are available: + +\verbatim + %0 the name of the macro being invoked + %* all arguments (unlike shell, not including any processed flags) + %# the number of arguments + %{-f} if present at invocation, the flag f itself + %{-f*} if present at invocation, the argument to flag f + %1, %2 the arguments themselves (after getopt(3) processing) +\endverbatim + +At the end of invocation of a parameterized macro, the above macros are +(at the moment, silently) discarded. + +\section macros_writing Writing a Macro + +Within the body of a macro, there are several constructs that permit +testing for the presence of optional parameters. The simplest construct +is "%{-f}" which expands (literally) to "-f" if -f was mentioned when the +macro was invoked. There are also provisions for including text if flag +was present using "%{-f:X}". This macro expands to (the expansion of) X +if the flag was present. The negative form, "%{!-f:Y}", expanding to (the +expansion of) Y if -f was *not* present, is also supported. + +In addition to the "%{...}" form, shell expansion can be performed +using "%(shell command)". The expansion of "%(...)" is the output of +(the expansion of) ... fed to /bin/sh. For example, "%(date ++%%y%%m%%d)" expands to the string "YYMMDD" (final newline is +deleted). Note the 2nd % needed to escape the arguments to /bin/date. +There is currently an 8K limit on the size that this macro can expand +to. + +\section macros_builtin Builtin Macros + +There are several builtin macros (with reserved names) that are needed +to perform useful operations. The current list is + +\verbatim + %trace toggle print of debugging information before/after + expansion + %dump print the active (i.e. non-covered) macro table + + %{echo:...} print ... to stderr + %{warn:...} print ... to stderr + %{error:...} print ... to stderr and return BADSPEC + + %define ... define a macro + %undefine ... undefine a macro + %global ... define a macro whose body is available in global context + + %{uncompress:...} expand ... to <file> and test to see if <file> is + compressed. The expansion is + cat <file> # if not compressed + gzip -dc <file> # if gzip'ed + bzip2 -dc <file> # if bzip'ed + %{expand:...} like eval, expand ... to <body> and (re-)expand <body> + + %{S:...} expand ... to <source> file name + %{P:...} expand ... to <patch> file name + %{F:...} expand ... to <file> file name +\endverbatim + +Macros may also be automatically included from /usr/lib/rpm/macros. +In addition, rpm itself defines numerous macros. To display the current +set, add "%dump" to the beginning of any spec file, process with rpm, and +examine the output from stderr. + +\section macros_example Example of a Macro + +Here is an example %patch definition from /usr/lib/rpm/macros: + +\verbatim + %patch(b:p:P:REz:) \ + %define patch_file %{P:%{-P:%{-P*}}%{!-P:%%PATCH0}} \ + %define patch_suffix %{!-z:%{-b:--suffix %{-b*}}}%{!-b:%{-z:--suffix %{-z*}}}%{!-z:%{!-b: }}%{-z:%{-b:%{error:Can't specify both -z(%{-z*}) and -b(%{-b*})}}} \ + %{uncompress:%patch_file} | patch %{-p:-p%{-p*}} %patch_suffix %{-R} %{-E} \ + ... +\endverbatim + + +The first line defines %patch with its options. The body of %patch is + +\verbatim + %{uncompress:%patch_file} | patch %{-p:-p%{-p*}} %patch_suffix %{-R} %{-E} +\endverbatim + +The body contains 7 macros, which expand as follows + +\verbatim + %{uncompress:...} copy uncompressed patch to stdout + %patch_file ... the name of the patch file + %{-p:...} if "-p N" was present, (re-)generate "-pN" flag + -p%{-p*} ... note patch-2.1 insists on contiguous "-pN" + %patch_suffix override (default) ".orig" suffix if desired + %{-R} supply -R (reversed) flag if desired + %{-E} supply -E (delete empty?) flag if desired +\endverbatim + +There are two "private" helper macros: + +\verbatim + %patch_file the gory details of generating the patch file name + %patch_suffix the gory details of overriding the (default) ".orig" +\endverbatim + +\section macros_using Using a Macro + +To use a macro, write: + +\verbatim + %<name> ... +\endverbatim + +or + +\verbatim + %{<name>} +\endverbatim + +The %{...} form allows you to place the expansion adjacent to other text. +The %\<name\> form, if a parameterized macro, will do argc/argv processing +of the rest of the line as described above. Normally you will likely want +to invoke a parameterized macro by using the %\<name\> form so that +parameters are expanded properly. + +Example: +\verbatim + %define mymacro() (echo -n "My arg is %1" ; sleep %1 ; echo done.) +\endverbatim + +Usage: + +\verbatim + %mymacro 5 +\endverbatim + +This expands to: + +\verbatim + (echo -n "My arg is 5" ; sleep 5 ; echo done.) +\endverbatim + +This will cause all occurrences of %1 in the macro definition to be +replaced by the first argument to the macro, but only if the macro +is invoked as "%mymacro 5". Invoking as "%{mymacro} 5" will not work +as desired in this case. + +\section macros_commandline Command Line Options + +When the command line option "--define 'macroname value'" allows the +user to specify the value that a macro should have during the build. +Note lack of leading % for the macro name. We will try to support +users who accidentally type the leading % but this should not be +relied upon. + +Evaluating a macro can be difficult outside of an rpm execution context. If +you wish to see the expanded value of a macro, you may use the option +\verbatim + --eval '<macro expression>' +\endverbatim +that will read rpm config files and print the macro expansion on stdout. + +Note: This works only macros defined in rpm configuration files, not for +macros defined in specfiles. You can use %{echo: %{your_macro_here}} if +you wish to see the expansion of a macro defined in a spec file. + +\section macros_configuration Configuration using Macros + +Starting in rpm 3.0, macros rather than rpmrc lines are used to configure rpm. +In general, all the rpmrc configuration lines documented in "Maximum RPM" +have been converted to macros, usually with a leading underscore, and the +same name that was used in rpmrc files. In some cases, there is no leading +underscore. Those macros existed in rpm-2.5.x and the underscore is omitted +in order to preserve the meaning and usage of macros that are defined during +spec file parsing. + +Here's an example to illustrate configuration using macros: + +\verbatim + Old way: + In /etc/rpmrc and/or ~/.rpmrc you put + something: some_value + + New way: + In /etc/rpm/macros and/or ~/.rpmmacros + %_something some_value +\endverbatim + +Here are 2 common FAQ for experienced users of rpm: + +\verbatim + 1) --rcfile works differently. + Old way: rpm --rcfile whatever + New way: rpm --rcfile /usr/lib/rpm/rpmrc:whatever + + 2) topdir (and other rpmrc configurables) work differently. + + Old way: + ~/.rpmrc contains + topdir: whatever + + New way: + /usr/lib/rpm/rpmrc contains + macrofiles: /usr/lib/rpm/macros: ... :~/.rpmmacros + ~/.rpmmacros contains + %_topdir whatever +\endverbatim + +\section macros_autoconf Macro Analogues of Autoconf Variables + +Several macro definitions provided by the default rpm macro set have uses in +packaging similar to the autoconf variables that are used in building packages: + +\verbatim + %_prefix /usr + %_exec_prefix %{_prefix} + %_bindir %{_exec_prefix}/bin + %_sbindir %{_exec_prefix}/sbin + %_libexecdir %{_exec_prefix}/libexec + %_datadir %{_prefix}/share + %_sysconfdir %{_prefix}/etc + %_sharedstatedir %{_prefix}/com + %_localstatedir %{_prefix}/var + %_libdir %{_exec_prefix}/lib + %_includedir %{_prefix}/include + %_oldincludedir /usr/include + %_infodir %{_prefix}/info + %_mandir %{_prefix}/man +\endverbatim + +*/ diff --git a/doc/manual/multiplebuilds b/doc/manual/multiplebuilds new file mode 100644 index 0000000..3db75fb --- /dev/null +++ b/doc/manual/multiplebuilds @@ -0,0 +1,47 @@ +/*! \page multiplebuilds Multiple build areas + +It is possible to run several RPM builds on the same machine using +separate RPM databases. On my build machine I have several build +areas which all run builds at the same time. The builds do not +interfere with each other. Each build behaves as if it was running on +its own machine and no build area knows about the RPM database which +actually configures the machine. + +First, setup a "topdir" in a prefix other then where RPM is +installed. You will need to make the directories. They need to be +writable by the account which will do the building, typically they +are owned by the buildmaster account and set to permissions +755. + +\verbatim + BUILD RPMS SOURCES SPECS SRPMS +\endverbatim + +Next, you will need to decide where the database files live. I suggest +putting them in a separate directory under "topdir". I call my +directory DB and it has the same owner and permissions as the other +directories. + +Each separate build area needs a rpmrc and macro configuration file. This +will need to specify the new topdir and dbpath. If you will be building +the same packages in different work areas you will also need to specify a +tmppath into the topdir. I suggest either making tmppath be the same as +the BUILD directory or adding another directory called BUILDROOT for it +in the topdir. + +Keeping track of the correct rpmrc for each build area can be +difficult. To make my life easier I make a small shell script with the +topdir hard coded inside: + +\verbatim + #!/bin/sh + /bin/rpm --rcfile /topdir/rpmrc "$@" + exit $? +\endverbatim + +I call the shell script rpm and it lives in the topdir. Each time I +wish to use a particular build area I just ensure that the build area +is first in my path so that when I run "rpm" I get the regular rpm +binary but I am using the local build areas rpmrc. + +*/ diff --git a/doc/manual/queryformat b/doc/manual/queryformat new file mode 100644 index 0000000..9b2ce6c --- /dev/null +++ b/doc/manual/queryformat @@ -0,0 +1,173 @@ +/*! \page queryformat Query formats + +As it is impossible to please everyone with one style of query output, RPM +allows you to specify what information should be printed during a query +operation and how it should be formatted. + +\section queryformat_tags Tags + +All of the information a package contains, apart from signatures and the +actual files, is in a part of the package called the header. Each piece +of information in the header has a tag associated with it which allows +RPM to to tell the difference between the name and description of a +package. + +To get a list of all of the tags your version of RPM knows about, run the +command 'rpm --querytags'. It will print out a list like (but much longer +then) this: + +\verbatim + RPMTAG_NAME + RPMTAG_VERSION + RPMTAG_RELEASE + RPMTAG_SERIAL + RPMTAG_SUMMARY + RPMTAG_DESCRIPTION + RPMTAG_BUILDTIME + RPMTAG_BUILDHOST + RPMTAG_INSTALLTIME + RPMTAG_SIZE +\endverbatim + +As all of these tags begin with RPMTAG_, you may omit it from query format +specifiers and it will be omitted from the rest of this documentation for +the same reason. + +A tag can consist of one element or an array of elements. Each element can +be a string or number only. + +\section queryformat_format Query Formats + +A query format is passed to RPM after the --queryformat argument, and normally +should be enclosed in single quotes. This query format is then used to print +the information section of a query. This means that when both -i and +--queryformat are used in a command, the -i is essentially ignored. +Additionally, using --queryformat implies -q, so you may omit the -q as well. + +The query format is similar to a C style printf string, which the printf(2) +man page provides a good introduction to. However, as RPM already knows the +type of data that is being printed, you must omit the type specifier. In +its place put the tag name you wish to print enclosed in curly braces +({}). For example, the following RPM command prints the names and sizes +of all of the packages installed on a system: + +\verbatim + rpm -qa --queryformat "%{NAME} %{SIZE}\n" +\endverbatim + +If you want to use printf formatters, they go between the % and {. To +change the above command to print the NAME in the first 30 bytes and +right align the size to, use: + +\verbatim + rpm -qa --queryformat "%-30{NAME} %10{SIZE}\n" +\endverbatim + +\section queryformat_arrays Arrays + +RPM uses many parallel arrays internally. For example, file sizes and +file names are kept as an array of numbers and an array of strings +respectively, with the first element in the size array corresponding +to the first element in the name array. + +To iterate over a set of parallel arrays, enclose the format to be used +to print each item in the array within square brackets ([]). For example, +to print all of the files and their sizes in the slang-devel package +followed by their sizes, with one file per line, use this command: + +\verbatim + rpm -q --queryformat "[%-50{FILENAMES} %10{FILESIZES}\n]" slang-devel +\endverbatim + +Note that since the trailing newline is inside of the square brackets, one +newline is printed for each filename. + +A popular query format to try to construct is one that prints the +name of a package and the name of a file it contains on one line, +repeated for every file in the package. This query can be very useful +for passing information to any program that's line oriented (such as +grep or awk). If you try the obvious, + +\verbatim + rpm --queryformat "[%{NAME} %{FILENAMES}\n]" cdp +\endverbatim + +If you try this, you'll see RPM complain about a "parallel array size +mismatch". Internally, all items in RPM are actually arrays, so the NAME +is a string array containing one element. When you tell RPM to iterate +over the NAME and FILENAMES elements, RPM notices the two tags have +different numbers of elements and complains. + +To make this work properly, you need to tell RPM to always print the first +item in the NAME element. You do this by placing a '=' before the tag +name, like this: + +\verbatim + rpm --queryformat "[%{=NAME} %{FILENAMES}\n]" cdp +\endverbatim + +which will give you the expected output. + +\verbatim + cdp /usr/bin/cdp + cdp /usr/bin/cdplay + cdp /usr/man/man1/cdp.1 +\endverbatim + +\section queryformat_formatting Formatting Tags + +One of the weaknesses with query formats is that it doesn't recognize +that the INSTALLTIME tag (for example) should be printed as a date instead +of as a number. To compensate, you can specify one of a few different +formats to use when printing tags by placing a colon followed the formatting +name after the tag name. Here are some examples: + +\verbatim + rpm -q --queryformat "%{NAME} %{INSTALLTIME:date}\n" fileutils + rpm -q --queryformat "[%{FILEMODES:perms} %{FILENAMES}\n]" rpm + rpm -q --queryformat \ + "[%{REQUIRENAME} %{REQUIREFLAGS:depflags} %{REQUIREVERSION}\n]" \ + vlock +\endverbatim + +The :shescape may be used on plain strings to get a string which can pass +through a single level of shell and give the original string. + +\section queryformat_expressions Query Expressions + +Simple conditionals may be evaluated through query expressions. Expressions +are delimited by %|...|. The only type of expression currently supported +is a C-like ternary conditional, which provides simple if/then/else +conditions. For example, the following query format display "present" if +the SOMETAG tag is present, and "missing" otherwise: + +\verbatim + %|SOMETAG?{present}:{missing}| +\endverbatim + +Notice that the subformats "present" and "missing" must be inside of curly +braces. + +\section queryformat_example Example: Viewing the Verify Flags + +The following example query is run against dev because I know %verify +is used there. +\verbatim + rpm -q --qf '[%{filenames} %{fileverifyflags}\n]' dev +\endverbatim + +The flags are defined in rpmlib.h (check there for changes): +\verbatim + #define RPMVERIFY_MD5 (1 << 0) + #define RPMVERIFY_FILESIZE (1 << 1) + #define RPMVERIFY_LINKTO (1 << 2) + #define RPMVERIFY_USER (1 << 3) + #define RPMVERIFY_GROUP (1 << 4) + #define RPMVERIFY_MTIME (1 << 5) + #define RPMVERIFY_MODE (1 << 6) + #define RPMVERIFY_RDEV (1 << 7) +\endverbatim + +A 1 bit in the output of the query means the check is enabled. + +*/ diff --git a/doc/manual/relocatable b/doc/manual/relocatable new file mode 100644 index 0000000..d73d0ce --- /dev/null +++ b/doc/manual/relocatable @@ -0,0 +1,57 @@ +/*! \page relocatable Relocatable packages + +Relocatable packages are a way to give the user a little control +over the installation location of a package. For example, a vendor +may distribute their software to install in "/opt" but you'd like +it to install in "/usr/opt". If the vendor were distributing a +relocatable RPM package, it would be easy. + +\section relocatable_building Building a Relocatable Package + +Not all software can be "relocatable". Before continuing you should +think about how the program works, what files it accesses, what other +programs access *it* (and expect it to be in a certain place), etc. +If you determine that the location of the package doesn't matter, +then it can probably be built as "relocatable". + +All you need to do to build a relocatable package is put one or more: + +\verbatim + Prefix: <dir> +\endverbatim + +in your spec file. The "<dir>" will usually be something like "/usr", +"/usr/local", or "/opt". Every file in your %files list must start +with that prefix. For example, if you have "Prefix: /usr" and your +%files list contains "/etc/foo.conf", the build will fail. The fix for +this is to put + +\verbatim + Prefix: /usr + Prefix: /etc +\endverbatim + +into the spec file so that the /usr and /etc directories may be +relocated separately when this package is installed. + + +\section relocatable_installing Installing Relocatable Packages + +By default, RPM will install a relocatable package in the prefix +directory listed in the spec file. You can override this on the +RPM install command line with "--prefix <dir>". For example, if +the package in question were going to be installed in "/opt" but +you don't have enough disk space there (and it is a relocatable +package), you could install it "--prefix /usr/opt". + +If there is more then one Prefix you may relocate each prefix +separately by using syntax like: + +\verbatim + rpm ... --relocate /opt=/usr/opt --relocate /etc=/usr/etc ... +\endverbatim + +If any of the Prefixes is not being relocated they can be skipped on +the command line + +*/ diff --git a/doc/manual/signatures b/doc/manual/signatures new file mode 100644 index 0000000..fffb985 --- /dev/null +++ b/doc/manual/signatures @@ -0,0 +1,83 @@ +/*! \page signatures Signature header + +The 2.1 release of RPM had a few improvements in the area of +digital package signatures. The usage of PGP has been cleaned +up and extended, the signature section in the RPM file format +has been made easily extensible with new signature types, and +packages can have multiple signatures. + +\section signatures_pgp PGP + +Legacy usage of PGP in rpm-2.0 was cumbersome, and only supported +1024 bit keys. Both of these problems have been corrected in rpm-2.1. + +Whereas previously you needed many rpmrc entries to clue in +RPM about keyring locations and such, RPM now behaves as PGP +users would expect. The PGPPATH environment variable can be +used to specify keyring locations. You can also use a +"%_pgpbin" line in your macros file to specify a different value +for RPM to use for PGPPATH. If neither of these are used PGP +uses its default ($HOME/.pgp). + +If you just want to verify packages, you need to supply values +for the macros +\verbatim + %_pgpbin the path to the pgp executable + %_signature the type of signature to use +\endverbatim + +In order to be able to sign packages, you may also have to +supply values for +\verbatim + %_pgp_name the pgp signature to use for signing + %_pgp_path the path to the key ring +\endverbatim + +\section signatures_signing Signing Packages + +Signature creation is the same as previous releases: just add +a --sign to your build command line. You can sign a package +after the package is built with: + +\verbatim + rpm --resign <package> +\endverbatim + +Using --resign removes any previous signature in the package. +To *add* a signature to a package, leaving all existing +signatures use: + +\verbatim + rpm --addsign <package> +\endverbatim + +RPM always creates MD5 and SIZE signatures when it build +packages, which means that packages built without --sign can +be "verified" to some extent. The MD5 signature should catch +problems like corrupt packages, faulty downloads, etc. + +\section signatures_verifying Verifying Package Signatures + +Package signature verification is the same as previous releases: + +\verbatim + rpm -K <package> +\endverbatim + +RPM will verify every signature in the package, which may include +more than one PGP signature. The output indicates what types of +signatures are being checked. If any checks fail you'll see a +"NOT OK" message, and you should be worried. + +If you have a package with PGP signatures, but don't have PGP +installed, but still want to verify it as much as possible, you +can do: + +\verbatim + rpm -K --nopgp <package> +\endverbatim + +That will cause RPM to skip any PGP signatures, but still check +any others (currently only MD5 and SIZE). + +*/ diff --git a/doc/manual/spec b/doc/manual/spec new file mode 100644 index 0000000..d67c058 --- /dev/null +++ b/doc/manual/spec @@ -0,0 +1,217 @@ +/*! \page specfile Spec file tags + +A few additions have been made to the spec file format. + +Name + +The Name tag contains the proper name of the package. Names must not +include whitespace and may include a hyphen '-' (unlike version and release +tags). Names should not include any numeric operators ('<', '>','=') as +future versions of rpm may need to reserve characters other than '-'. + +By default subpackages are named by prepending `\<main package\>-' to +the subpackage name(s). If you wish to change the name of a +subpackage (most commonly this is to change the '-' to '.'), then you +must specify the full name with the -n argument in the %package +definition: + +\verbatim + %package -n newname +\endverbatim + +\section specfile_summary Summary: and Description: Tags + +The Summary: tag should be use to give a short (50 char or so) summary +of the package. Most package's Description: line should be changed to +a Summary: line. The Description: tag is still supported but should +be changed to a "%description" entry similar to %package and %files. +At some point in the future support will be removed for "Description:". +As an example, this spec file fragment: + +\verbatim + Description: Screen drawing library + Name: screenlib + Version: 1.0 + + %package devel + Description: Screen drawing library headers and static libs +\endverbatim + +might be changed to: + +\verbatim + Summary: Screen drawing library + Name: screenlib + Version: 1.0 + + %description + The screen drawing library + is a handy development tool + + %package devel + Summary: Screen drawing library headers and static libs + + %description devel + This package contains all of the + headers and the static libraries for + screenlib. + + You'll only need this package if you + are doing development. +\endverbatim + +The description is free form text, but there are two things to note. +The first regards reformatting. Lines that begin with white space +are considered "pre-formatted" and will be left alone. Adjacent +lines without leading whitespace are considered a single paragraph +and may be subject to formatting by glint or another RPM tool. + +\section specfile_url URL: and Packager: Tags + +Two new tags are "URL:" and "Packager:". "URL:" is a place to put a +URL for more information and/or documentation on the software +contained in the package. Some future RPM package tool may make use +of this. The Packager: tag is meant to contain the name and email +address of the person who "maintains" the RPM package (which may be +different from the person who actually maintains the program the +package contains). + +\section specfile_buildarchitectures BuildArchitectures: Tag + +This tag specifies the architecture which the resulting binary package +will run on. Typically this is a CPU architecture like sparc, +i386. The string 'noarch' is reserved for specifying that the +resulting binary package is platform independent. Typical platform +independent packages are html, perl, python, java, and ps packages. + +\section specfile_virtual Virtual File Attribute(s) in %files Section + +A %ghost tag on a file indicates that this file is not to be included +in the package. It is typically used when the attributes of the file +are important while the contents is not (e.g. a log file). + +The %config(missingok) indicates that the file need not exist on the +installed machine. The %config(missingok) is frequently used for files +like /etc/rc.d/rc2.d/S55named where the (non-)existence of the symlink +is part of the configuration in %post, and the file may need to be +removed when this package is removed. This file is not required to +exist at either install or uninstall time. + +The %config(noreplace) indicates that the file in the package should +be installed with extension .rpmnew if there is already a modified file +with the same name on the installed machine. + +The virtual file attribute token %verify tells `-V/--verify' to ignore +certain features on files which may be modified by (say) a postinstall +script so that false problems are not displayed during package verification. +\verbatim + %verify(not size filedigest mtime) %{prefix}/bin/javaswarm +\endverbatim + +\section specfile_globbing Shell Globbing of %files Section + +The usual rules for shell globbing apply. Most special characters can +be escaped by prefixing them with a '\'. Spaces are used to separate +file names and so must be escaped by enclosing the file name with quotes. +For example: + +\verbatim + /tmp/are\.you\|bob\? + /tmp/bob\'s\*htdocs\* + "/tmp/bob\'s htdocs" +\endverbatim + +Names containing "%%" will be rpm macro expanded into "%". When +trying to escape large number of file names, it is often best to +create a file with the complete list of escaped file names. This is +easiest to do with a shell script like this: + +\verbatim + rm -f $RPM_BUILD_DIR/filelist.rpm + echo '%defattr(-,root,root)' >> $RPM_BUILD_DIR/filelist.rpm + find $RPM_BUILD_ROOT/%{_prefix} -type f -print | \ + sed "s!$RPM_BUILD_ROOT!!" | perl -pe 's/([?|*.\'"])/\\$1/g' \ + >> $RPM_BUILD_DIR/filelist.rpm + + %files -f filelist.rpm +\endverbatim + +\section specfile_automatic Fine Adjustment of Automatic Dependencies + +Rpm currently supports separate "Autoreq:" and "Autoprov:" tags in a +spec file to independently control the running of find-requires and +find-provides. A common problem occurs when packaging a large third +party binary which has interfaces to other third party libraries you +do not own. RPM will require all the third party libraries be +installed on the target machine even though their intended use was +optional. To rectify the situation you may turn off requirements when +building the package by putting + +\verbatim + Autoreq: 0 +\endverbatim + +in your spec file. Any and all requirements should be added manually using the + +\verbatim + Requires: depend1, ..., dependN +\endverbatim + +in this case. + +Similarly there is an Autoprov tag to turn off the automatic provision +generation and a Autoreqprov to turn off both the automatic provides and +the automatic requires generation. + +\section specfile_nosrc NoSource: Tag + +Files ending in .nosrc.rpm are generally source RPM packages whose spec +files have one or more NoSource: or NoPatch: directives in them. Both +directives use the named source or patch file to build the resulting +binary RPM package as usual, but they are not included in the source +RPM package. + +The original intent of this ability of RPM was to allow proprietary or +non-distributable software to be built using RPM, but to keep the +proprietary or non-distributable parts out of the resulting source RPM +package, so that they would not get distributed. + +They also have utility if you are building RPM packages for software +which is archived at a well-known location and does not require that +you distribute the source with the binary, for example, for an +organization's internal use, where storing large quantities of source +is not as meaningful. + +The end result of all this, though, is that you can't rebuild +``no-source'' RPM packages using `rpm --rebuild' unless you also have +the sources or patches which are not included in the .nosrc.rpm. + +\section specfile_buildrequires BuildRequires: Tag + +Build dependencies are identical to install dependencies except: + +\verbatim + 1) they are prefixed with build (e.g. BuildRequires: rather than Requires:) + 2) they are resolved before building rather than before installing. +\endverbatim + +So, if you were to write a specfile for a package that requires egcs to build, +you would add +\verbatim + BuildRequires: egcs +\endverbatim +to your spec file. + +If your package was like dump and could not be built w/o a specific version of +the libraries to access an ext2 file system, you could express this as +\verbatim + BuildRequires: e2fsprofs-devel = 1.17-1 +\endverbatim + +Finally, if your package used C++ and could not be built with gcc-2.7.2.1, you +can express this as +\verbatim + BuildConflicts: gcc <= 2.7.2.1 +\endverbatim + +*/ diff --git a/doc/manual/triggers b/doc/manual/triggers new file mode 100644 index 0000000..64973f2 --- /dev/null +++ b/doc/manual/triggers @@ -0,0 +1,165 @@ +/*! \page triggers Trigger scriptlets + +Triggers provide a well-defined method for packages to interact with one +another at package install and uninstall time. They are an extension +of the normal installation scripts (i.e. %pre) which allows one package +(the "source" of the trigger package [which I often think of as the +"triggered package"]) to execute an action when the installation status +of another package (the "target" of the trigger) changes. + +\section triggers_example A Simple Example + +Say the package "mymailer" needs an /etc/mymailer/mailer symlink which points +to the mail transport agent to use. If sendmail is installed, the link should +point to /usr/bin/sendmail, but it vmail is installed, the link should +instead point to /usr/bin/vmail. If both packages are present, we don't care +where the link points (realistically, sendmail and vmail should conflict +with one another), while if neither package is installed the link should +not exist at all. + +This can be accomplished by mymailer providing trigger scripts which +move the symlink when any of the following occurs: + +\verbatim + 1) sendmail is installed + 2) vmail is installed + 3) sendmail is removed + 4) vmail is removed +\endverbatim + +The first two of these scripts would look like this: + +\verbatim + %triggerin -- sendmail + ln -sf /usr/bin/sendmail /etc/mymailer/mailer + + %triggerin -- vmail + ln -sf /usr/bin/vmail /etc/mymailer/mailer +\endverbatim + +These are two installation triggers, triggered by one of sendmail or vmail. +They are run when: + +\verbatim + 1) mymailer is already installed, and sendmail is installed or + upgraded + 2) mymailer is already installed, and vmail is installed or + upgraded + 3) sendmail is already installed, and mymailer is installed or + upgraded + 4) vmail is already installed, and mymailer is installed or + upgraded +\endverbatim + +For the upgrading, the strategy is a little different. Rather then +setting the link to point to the trigger, the link is set to point to +the *other* mailer (if it exists), as follows: + +\verbatim + %triggerun -- sendmail + [ $2 = 0 ] || exit 0 + if [ -f /usr/bin/vmail ]; then + ln -sf /usr/bin/vmail /etc/mymailer/mailer + else + rm -f /etc/mymailer/mailer + + fi + + %triggerun -- vmail + [ $2 = 0 ] || exit 0 + if [ -f /usr/bin/sendmail ]; then + ln -sf /usr/bin/sendmail /etc/mymailer/mailer + else + rm -f /etc/mymailer/mailer + + fi + + %postun + [ $1 = 0 ] && rm -f /etc/mymailer/mailer +\endverbatim + +These trigger scripts get run when: + +\verbatim + 1) sendmail is installed, and mymailer is removed + 2) vmail is installed, and mymailer is removed + 3) mymailer is installed, and sendmail gets removed + 4) mymailer is installed, and vmail gets removed +\endverbatim + +The %postun insures that /etc/mymailer/mailer is removed when mymailer +is removed (triggers get run at the same time as %preun scripts, so +doing this in the %postun is safe). Note that the triggers are testing +$2 to see if any action should occur. Recall that the $1 passed to regular +scripts contains the number of instances of the package which will be +installed when the operation has completed. $1 for triggers is exactly +the same -- it is the number of instances of the source (or triggered) +package which will remain when the trigger has completed. Similarly, $2 +is the number of instances of the target package which will remain. In +this case, if any of the targets will remain after the uninstall, the +trigger doesn't do anything (as it's probably being triggered by an +upgrade). + +\section triggers_syntax Trigger Syntax + +Trigger specifications are of the form: + +\verbatim + %trigger{un|in|postun} [[-n] <subpackage>] [-p <program>] -- <trigger> +\endverbatim + +The -n and -p arguments are the same as for %post scripts. The +\<trigger\> portion is syntactically equivalent to a "Requires" +specification (version numbers may be used). If multiple items are +given (comma separated), the trigger is run when *any* of those +conditions becomes true (the , can be read as "or"). For example: + +\verbatim + %triggerin -n package -p /usr/bin/perl -- fileutils > 3.0, perl < 1.2 + print "I'm in my trigger!\n"; +\endverbatim + +Will put a trigger in package 'package' which runs when the installation +status of either fileutils > 3.0 or perl < 1.2 is changed. The script will +be run through /usr/bin/perl rather then /bin/sh (which is the default). + +\section triggers_unusual An Unusual Case + +There is one other type of trigger available -- %triggerpostun. These are +triggers that are run after their target package has been removed; they will +never be run when the package containing the trigger is removed. + +While this type of trigger is almost never useful, they allow a package to +fix errors introduced by the %postun of another package (or by an earlier +version of that package). + +\section triggers_order Order of Script Execution + +For reference, here's the order in which scripts are executed on a single +package upgrade: + +\verbatim + all-%pretrans + ... + any-%triggerprein (%triggerprein from other packages set off by new install) + new-%triggerprein + new-%pre for new version of package being installed + ... (all new files are installed) + new-%post for new version of package being installed + + any-%triggerin (%triggerin from other packages set off by new install) + new-%triggerin + old-%triggerun + any-%triggerun (%triggerun from other packages set off by old uninstall) + + old-%preun for old version of package being removed + ... (all old files are removed) + old-%postun for old version of package being removed + + old-%triggerpostun + any-%triggerpostun (%triggerpostun from other packages set off by old un + install) + ... + all-%posttrans +\endverbatim +*/ diff --git a/doc/manual/tsort b/doc/manual/tsort new file mode 100644 index 0000000..e2f634f --- /dev/null +++ b/doc/manual/tsort @@ -0,0 +1,159 @@ +/*! \page tsort Package ordering in rpm-4.0.1 and later + +The package ordering algorithm in rpm-4.0.1 has changed. + +\section tsort_problem The Problem + +Here's a simple test to illustrate the need for the change (from +bugzilla #12327): + +Assume the minimal 7.0 package manifest in /tmp/list +\verbatim + /mnt/redhat/comps/dist/7.0/sparc/bash-2.04-11.sparc.rpm + /mnt/redhat/comps/dist/7.0.2/sparc/glibc-2.1.94-1.sparc.rpm + /mnt/redhat/comps/dist/7.0/sparc/mktemp-1.5-5.sparc.rpm + /mnt/redhat/comps/dist/7.0/noarch/basesystem-7.0-2.noarch.rpm + /mnt/redhat/comps/dist/7.0/noarch/setup-2.3.4-1.noarch.rpm + /mnt/redhat/comps/dist/7.0/noarch/filesystem-2.0.7-1.noarch.rpm + /mnt/redhat/comps/dist/7.0/sparc/libtermcap-2.0.8-25.sparc.rpm + /mnt/redhat/comps/dist/7.0/noarch/termcap-11.0.1-3.noarch.rpm +\endverbatim + +with database initialization as +\verbatim + mkdir -p /tmp/ROOT/var/lib/rpm + rpm --initdb /tmp/ROOT/var/lib/rpm +\endverbatim + +This command "works" +\verbatim + rpm -Uvh -r /tmp/ROOT `cat /tmp/list` +\endverbatim +while this command +\verbatim + rpm -Uvh -r /tmp/ROOT `tac /tmp/list` +\endverbatim +fails with +\verbatim + loop in prerequisite chain: libtermcap bash libtermcap +\endverbatim + +\note The 2nd upgrade reverse orders the packages in the manifest. + +The problem is that the previous ordering algorithm, basically a very clever +implementation of tsort, was sensitive to initial conditions, and the first +command "happens" to snip a loop, while the second does not. + +\section tsort_solution The Solution + +The current ordering algorithm is exactly tsort from Knuth V1, with one further +twist. Since the only way out of a dependency loop is to snip the loop +somewhere, rpm uses hints from Requires: dependencies to distinguish +co-requisite (these are not needed to install, only to use, a package) from +pre-requisite (these are guaranteed to be installed before the package that +includes the dependency) relations. + +There is now syntax in spec files to explicitly specify the source of a +Requires: dependency. If, for example, you use grep in %post, then you +as a packager would normally add +\verbatim + PreReq: grep +\endverbatim +in order to insure that grep was installed before attempted use by the +%postun scriptlet. + +Now the same dependency can be expressed more precisely as +\verbatim + Requires(post): grep +\endverbatim + +For completeness, here's the complete set of tokens that may be +added to Requires: as in the example above: +\verbatim + "interp", RPMSENSE_INTERP + "prereq", RPMSENSE_PREREQ + "preun", RPMSENSE_SCRIPT_PREUN + "pre", RPMSENSE_SCRIPT_PRE + "postun", RPMSENSE_SCRIPT_POSTUN + "post", RPMSENSE_SCRIPT_POST + "rpmlib", RPMSENSE_RPMLIB + "verify", RPMSENSE_SCRIPT_VERIFY +\endverbatim + +Ditto BuildRequires: +\verbatim + "prep", RPMSENSE_SCRIPT_PREP + "build", RPMSENSE_SCRIPT_BUILD + "install", RPMSENSE_SCRIPT_INSTALL + "clean", RPMSENSE_SCRIPT_CLEAN +\endverbatim +but let's not go there (yet). + +For giggles, you can also do stuff like +\verbatim + Requires(pre,post): /bin/sh +\endverbatim + +By marking dependencies more precisely, rpm can distinguish between +an upgrade context (like the use of grep in %post above) and an installed +context (like the autogenerated Requires: in a package that includes a +script with #!/bin/sh), and that permits rpm to differentiate pre-requisites +from co-requisites while doing package ordering. + +Here's what cures the libtermcap <-> bash loop: +\verbatim + Requires(postun): /bin/sh +\endverbatim +which, since the dependency is clearly not useful or necessary in determining +install ordering, is safely ignored. + +\section tsort_sideeffects Side Effects + +One of the side effects of changing the package install ordering, is that +there are a handful of new loops that are detected. Here's what I found +looking at supported Red Hat releases: + +\verbatim + ghostscript-fonts ghostscript + /* 7.0 only */ + pango-gtkbeta-devel pango-gtkbeta + XFree86 Mesa + compat-glibc db2 + compat-glibc db1 + pam initscripts + kernel initscripts + initscripts sysklogd + /* 6.2 */ + egcs-c++ libstdc++ + /* 6.1 */ + pilot-link-devel pilot-link + /* 5.2 */ + pam pamconfig +\endverbatim + +Why are there new loops? Because tsort is trying to use all of the +dependency relations for ordering, while the previous tsort ignored all +Requires: from added packages. + +Except for the "well known" libtermcap <-> bash loop (which is just wrong), +all of the other dependencies are simply not needed in an upgrade context +to perform package ordering. Please note that all of the known to cause +loop dependencies listed above are, for now, explicitly ignored when +determining package install ordering. + +\section tsort_summary Summary + +So what does this all mean? Basically not much, unless you find yourself +trying to specify dependencies amongst a set of packages correctly and +happen to create a dependency loop. + +And, before you start adding the new-fangled syntax to packages, please +remember that rpm will almost certainly be auto-generating fine-grained +dependencies for %post et al scriptlets pretty soon. Truly, rpm needs to +make packaging easier, not provide Yet More Complicated Syntax in spec files. + +With thanks to Ken Estes for doing the implementation in bash2 that makes +it possible to auto-generate scriptlet dependencies, blame me for the long, +slow deployment. + +*/ |