RPM-Bau für Anfänger

(5396 Worte insgesamt im Text)
(17073 mal aufgerufen)  Druckerfreundliche Ansicht [1]

Letzte Änderung: 13.12.2005

Inhalt


Für wen ist dieses HowTo?

Für alle, die eigene RPM-Pakete erstellen möchten.

Dabei soll hier bewußt keine Anleitung zur Erstellung von Software herauskommen - das ist in einem solch kleinen HowTo nicht möglich. Sie sollten also schon über ein wenig Erfahrung im Umgang mit den Befehlen make, make install verfügen und auch mal einen Blick in den Sourcecode werfen können ohne dabei nur böhmische Dörfer zu sehen.

Was ist RPM?

RPM ist der "Red Hat Package Manager". Obwohl der Name die Bezeichnung Red Hat enthält, ist er dennoch als ein vollständig offenes System angelegt, welches jeder - und damit auch andere Distributionen wie SUSE [28] oder Mandrake - benutzen kann.

Er gibt dem Benutzer die Möglichkeit, aus dem Quellcode für eine neue Software Pakete mit Quell- und Binärcode zu erstellen, mit denen es möglich ist, Binaries einfach zu installieren und zu verwalten sowie Quellcode einfach zu übersetzen. Er besitzt auch eine eigene Datenbank mit Informationen über alle Pakete und deren zugehörige Dateien, die zum Testen von Paketen und zum Abfragen von Informationen bezüglich Dateien und/oder Paketen benutzt werden kann.

Die Philosophie von RPM

Eines der Ziele von RPM war die Möglichkeit die ursprünglichen Quellen auf verschiedenen Systemen zu verwenden. Die Quellen sollten dabei im Original erhalten bleiben und Änderungen, die die Distributoren hatten vornehmen müssen um es zum Laufen zu bringen, sollten klar erkennbar sein.

Mit RPM hat man sowohl die Originalquellen als auch den Patch, mit dem die Quellen kompiliert wurden. Das hat verschiedene Vorteile: Wenn z.B. eine neue Version eines Programmes herauskommt, ist es nicht mehr nötig, noch einmal komplett von vorne anzufangen, um es unter der jeweiligen Distribution zu kompilieren. Man kann sich einfach den Patch anschauen, um zu sehen, was eventuell zu ändern ist. Alle einzukompilierenden Defaults usw. sind so einfach herauszufinden.

Zusätzlich bietet RPM die Möglichkeit, vor und nach der Installation des eigentlichen Programmpakets Skripte auszuführen. Dies ermöglicht eine sehr feine Steuerung der Installation neuer Software. So können diese Skripte durchaus vorhandene Konfigurationsdateien anpassen (Konfigurationsdateien werden, soweit vorhanden, normalerweise nicht überschrieben) oder die Installationsumgebung an die Sofware anpassen. Allerdings herrscht hier zwischen den Paketmaintainern auch Uneinigkeit, in wie weit diese "post"- oder "pre"-Skripte in die Installation eingreifen dürfen. Schließlich laufen diese Skripte i.A. mit root-Rechten und können damit auch viel Schaden auf dem System des Anwenders hervorrufen.

RPM hat ebenfalls einen leistungsfähigen Abfragemechanismus. Man kann die gesamte Paketdatenbank nach bestimmten Paketen oder einzelnen Dateien durchsuchen und so einfach feststellen, zu welchem Paket eine Datei gehört und wo sie herkommt. Die RPM-Dateien selbst sind komprimierte Archive, die einzelnen Pakete können jedoch einfach und schnell nach bestimmten Informationen durchsucht werden, da ein sog. Header an die Dateien angefügt wird alle wichtigen Informationen zu diesem Paket enthält. Das ermöglicht das schnelle Durchsuchen von Paketen.

Eine andere nützliche Funktion ist die Möglichkeit, Pakete zu überprüfen. Falls man vermutet, daß man ein für ein Paket wichtiges File gelöscht haben könnte, kann man dieses damit einfach kontrollieren. Man wird dann über Probleme mit der gegenwärtigen Konfiguration informiert und kann -- falls notwendig -- das Paket neu installieren.

Ebenso kann man bei einzelnen Dateien im System einfach feststellen, zu welchem Paket diese gehören. Damit lassen sich manchmal Probleme bei einem Update vermeiden oder es kann auch noch nachträglich festgestellt werden, welches Paket die entsprechende Datei installiert hat, die evtl. Probleme verursacht.

RPM bietet also nicht nur eine einfache Möglichkeit zur Verwaltung der installierten Software-Pakete. Inzwischen gehen die Anwendungsmöglichkeiten von RPM weit darüber hinaus. Programmautoren bzw. Pakethersteller können mit RPM die Installation und auch das Update eine Software feinfühlig steuern, und Anwender können sich jederzeit einen detailierten Überblick über die auf Ihrem System installierte Software verschaffen.


Installation der Workstation

In diesem Kapitel wird beschrieben, wie man seinen PC installieren sollte, um RPM-Pakete professionel bauen zu können. Dabei soll dies nur als Empfehlung dienen. Es gibt sicherlich hunderte von Varianten, wie man einen PC installieren kann...

Hintergrund ist hierbei allerdings das Sicherstellen einer gewissen Qualität - denn wenn man die erzeugten Pakete später einmal veröffentlichen will und andere Nutzer in den Genuss seiner Arbeit bringen möchte, dann sollten die veröffentlichten Pakete auch funktionieren.


Sprachauswahl

Neben der eigenen Sprache sollten immer auch die englischen Sprachpakete installiert werden. Dies dient als "Fallback-Lösung": falls einmal jmd. eine völlig andere Spracheinstellung nutzt, kann er ggf. trotzdem noch mit der englischen Sprachvariante arbeiten. Dies sollte aber auch funktionieren und getestet sein!

Natürlich sollten auch andere Sprachvarianten getestet werden - aber die eigene und zusätzlich noch die englische Sprache sollte zunächst ausreichend sein.


Partitionierung

Hier zunächst ein Vorschlag für die Größe der einzelnen Partitionen:

GrößeInhalt
5-8 GBpro Distribution bzw. Betriebssystem
0,5-2 GBfür Swap
3-8 GBfür temporäre Dateien, die während des Build-Vorgangs anfallen können
6-15 GBfür eigene Dateien
30-50 MBfür die Boot-Partition

Nach oben hin ist natürlich immer ein wenig Platz - aber die Mindestgrößen sollten schon eingehalen werden, wenn es nicht plötzlich allzu knapp werden sollte. Bei den heutigen Festplattengrößen dürfte dies aber kein großes Problem mehr darstellen.

Folgende Betriebssysteme sollten eingespielt werden:

Einige Entwickler haben auch zwei oder mehr Computer an der Hand oder nutzen virtuelle Maschinen.

Wichtig ist in jedem Fall die Trennung zwischen der "Entwicklermaschine" und "Testmaschinen", welche nur mit einer "Endbenutzerkonfiguration" installiert sind. Oft wird hier der Fehler gemacht auf den Testmaschinen Compiler oder andere Entwicklertools zu installieren die später nicht verfügbar sind und damit ist das Programm dann oft nicht mehr lauffähig.


Backups

Rechnen Sie rechtzeitig damit, dass Sie Ihr System während der Entwicklungsphase unbrauchbar machen und legen Sie Backups an.

Auch während der laufenden Entwicklung sollten zum Feierabend immer noch 5 Minuten Zeit sein, um ein Backupskript anzustoßen, welches den aktuellen Arbeitsstand sichert. Wer weiß: evtl. stürzt Ihnen der Rechner durch einen kleinen Fehler am nächsten Morgen ab und Ihre Arbeit verschwindet im Nirvana...


Software installieren

Am einfachsten machen Sie sich die Sache, wenn Sie für die ersten Tests erst einmal alle verfügbaren Pakete installieren. Insbesondere die Entwicklertools und Bibliotheken sind wichtig, um überhaupt erst einmal Software kompilieren zu können.

Auf den Testmaschinen sollte nur die Standardauswahl an Software installiert sein - mehr auf keinen Fall.


Das SPEC-File

Das SPEC-File steuert später den gesammten Build-Prozess Ihres Programms und gibt dem Paketmanager die nötigen Informationen, welche Dateien später in das eigentliche RPM gehören und welche zusätzlichen Skripte oder Aktionen vor oder nach der Installation oder auch bei einem Update eines Paketes auszuführen sind.

Das SPEC-File ist also sozusagen das Herzstück für den RPM-Bau.

Aus diesem Grund sollten Sie anfangs (und auch später) lieber nicht damit anfangen, dieses SPEC-File von Hand komplett neu erzeugen zu wollen. Suchen Sie sich lieber ein Source-RPM, welches ein Programm enthält, welches den Ihrem ähnlich ist und passen Sie das darin enthaltene SPEC-File an.


SPEC-File Vorlage

Wenn Sie es dennoch einmal "from scratch" versuchen möchten und um Ihnen einen kleinen Überblick zu geben, finden Sie hier eine Vorlage.

#
# spec file for package PackageName (Version x.y)
#
# Copyright (c) 2005 myhometown.
# This file and all modifications and
# additions to the pristine
# package are under the same license as the package itself.
#
# Please submit bugfixes or comments
# to Mr.x <my@example.com>.
#
# norootforbuild
# neededforbuild
# usedforbuild
Name: PackageName
License: LicenseName
Group: PackageRPMGroup
Autoreqprov: on
Version: PackageVersion
Release: 0
Summary: PackageSummary
Url: http://
Source: %{name}-%{version}.tar.bz2
Packager: YourName
Patch: %{Pname}-%{version}.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-build
#BuildArchitectures: noarch
#ExclusiveArch: %ix86
%description PackageDescription
%package SubPackageNameSuffix
Summary: SubPackageSummary
Group: SubPackageRPMGroup
Requires: PackageName = %{version}
%description SubPackageSuffix
%prep
%setup
%patch
%build
%install
rm -rf $RPM_BUILD_ROOT
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)

Die einzelnen Sektionen des SPEC-Files

Wir wollen uns nun einmal die einzelnen Sektionen des SPEC-Files etwas genauer ansehen. Dabei ist der Kopf des SPEC-Files noch leicht zu erklären:

Präambel: Im Kopfteil des Pakets sollten leicht lesbare Informationen über das Paket, den Paketautor (und seine Email) sowie weitere Informationen stehen, welche für einen anderen Paketbauer evtl. wichtige Informationen liefern können. Bei vielen Distributoren erstellt diese Informationen ein Skript, weshalb hier meist nur generelle Informationen zu finden sind. Wichtig ist hier eigentlich nur, dass sämtliche Informationen durch das Voranstellen einer # als Kommentar gekennzeichnet werden.

Sollten Sie später innerhalb des SPEC-Files einen Kommentar einfügen, tragen Sie bitte auch in der darüber stehenden Zeile eine # ein, damit der Kommentar später leichter zu finden ist und die "Leerzeile" über dem Kommentar später nicht durch Skripte herausgelöscht wird.

[...]
%install
rm -rf $RPM_BUILD_ROOT
make DESTDIR=$RPM_BUILD_ROOT
install
#
# Emacs support
install -d $RPM_BUILD_ROOT/usr/share/emacs/site-lisp
install contrib/emacs/t-mouse.el* \
$RPM_BUILD_ROOT/usr/share/emacs/site-lisp
#
# start script and sysconfig template
install -m 755
[...]


norootforbuildDiese Funktion ist derzeit nur bei SUSE-RPMs implementiert, die automatisch über das build-Skript gebaut werden. Damit wird ein Paket als normaler Benutzer und nicht als root gebaut, was viele Sicherheitsvorteile bringt.
neededforbuildDiese Zeile hat derzeit nur eine Funktion innerhalb der Autobuild-Umgebung von SUSE und ist ausserhalb der Firma daher ohne Funktion. Sinn und Zweck ist (mal wieder) die Faulheit der Entwickler: wenn diese z.B. eine KDE-Anwendung distributieren, dann können Sie hier einfach kde3-packages angeben und die Autobuild-Umgebung fällt dann "BuildRequires" automatisch mit den richtigen Paketen, die für das erstellen eines KDE-Programms nötig sind.
BuildRequiresHier werden Pakete angegeben, die zum erstellen des neuen RPMs benötigt werden. Wenn Sie also eine C++ Anwendung als PRM zur Verfügung stellen wollen, werden Sie hier sicherlich als Paket den Kompiler gcc angeben müssen.
Oft mag es vorkommen, dass ein Paket bestimmte Bibliotheken benötigt. Dies erkennt man oft während des configure-Skripts, da hier bestimmte *.la-Dateien nicht gefunden werden. Eine Suche bei Google nach der entsprechenden Datei kann einen hier oft auf die richtige Fährte bringen und liefert dann das fehlende Paket. Ggf. befragen Sie einfach RPM selbst, zu welchem Paket eine Datei gehört: (rpm -qf /usr/lib/libgpm.a) und tragen dann dieses Paket unter BuildRequires ein.
usedforbuildDiese Zeile ist seit SUSE 9.1 obsolet und wurde durch BuildRequires abgelöst.
Name:Der Name des Paketes. Hier kann man den ASCII-Zeichensatz, Binde- und Unterstrich verwenden (a-z, A-Z, 0-9, -, _).
Licence:Die Lizenz, unter der das Paket verteilt wird. Notfalls nachfragen! Wenn nichts im Quelltext steht ist es NICHT GPL [29]! Verwendet ein Paket mehrere Lizenzen, dann werden diese durch Kommata voneinander getrennt.
Group:Stelle, an welcher das Paket nachher z.B. mit YaST2 zu finden ist, wenn man die "Paketgruppenansicht" einschaltet. Eine Übersicht über die bei SUSE verfügbaren Gruppen findet man auf dem Novell- FTP- Server [30].
Autoreqprov:on = mit dieser Einstellung überprüft RPM selbstständig, welche zusätzlichen Pakete zum "Betrieb" des Paketes benötigt werden und trägt diese in der Zeile Requires ein.
Vorübergehend kann man diese Option hier mit "off" deaktivieren. Dies sollte jedoch nicht die Standardeinstellung sein.
Version:Versionsnummer des Quelltextes. Diese Versionsnummer sollte hier angegeben werden. Aber Achtung: RPM entscheidet anhand dieser Versionnummer welches Paket älter oder neuer ist. Dabei kann RPM leider nicht richtig mit Buchstaben umgehen. Deshalb sollte man - wenn irgendwie möglich - auf Buchstaben in Versionsnummern verzichten und statt dessen lieber eine weitere Ziffernspalte beginnen. Aus "1.0rc1" würde dann z.B. "1.0.1".
Release:Versionsnummer des späteren RPMs - diese Versionsnummer wird zusammen mit der Versionsnummer des Quellcodes bei einem Update des Pakets überprüft. Sind die Nummern des installierten RPMs höher als die des zum Update ausgewählten, wird ein Update abgelehnt. Sie sollten also jedesmal, wenn Sie ein RPM neu bauen, auch diese Releasenummer erhöhen. Bei einem Update des Quelltextes hingegen wird die Versionsnummer erhöht und die Releasenummer wieder auf 0 heruntergesetzt.
Es hat sich inzwischen eingebürgert bei Tests die Releasenummer "0" zu vergeben und erst wenn alles funktioniert die Releasenummer auf "1" zu setzen und das Paket zu veröffentlichen.
Bitte verwenden Sie auch für die Releasenummer keine Buchstaben oder andere Sonderzeichen. RPM kann damit oft nicht vernünftig umgehen und ein einmal installiertes RPM-Paket läßt sich nur noch Updaten, wenn sich die Versionsnummer ändert.
SUSE verwendet in letzter Zeit häufig zweistellige Release-Nummern der Pakete. Hier will man auf die marginalen Unterschiede zwischen verschiedenen Produktversionen aufmerksam machen (SLES <> SL).
Summary:Kurze, knackige Zusammenfassung, die dem Benutzer sagt, was das Paket enthält. Diese Zusammenfassung wird bei Abfragen über den Paketmanager angezeigt und auch die Tools der einzelnen Distributionen zeigen die hier enthaltene Kurzinformation an. Deshalb sollte man hier keine kompletten Sätze sondern wirklich nur ein kurzes Statement formulieren, das dem Anwender die Bedeutung dieses Pakets klar macht.
Description:Ausführliche Beschreibung des Pakets. Diese wird bei einem rpm -qpi *.rpm angezeigt und sollte das Paket so gut wie möglich beschreiben.
Standardsprache ist Englisch - sowohl für die "Summary" als auch für die "Description".
Wenn Sie ein Paket in mehrere Subpakete (diese werden mit dem Namen des Hauptpakets, einem "-" und dem Namen des Subpakets benannt) aufsplitten möchten, müssen Sie auch für jedes dieser Subpakete eine eigene "Summary" und eine eigene "Description" verfassen. Beispiel:
%package devel
Summary: Development package for ...
Summary(de): Entwicklungspakete für ...
%description devel
Development package for ...
%description devel -l de
Entwicklungspakete für ...

Weitere Sprachen sollten Sie nur ins SPEC-File aufnehmen, wenn dies unbedingt nötig ist. Denken sie daran, dass die hier gemachten Angaben in die RPM-eigene Datenbank aufgenommen werden und diese Datenbank mit zunehmender Größe immer langsamere Zugriffszeiten hat.
URL:Die URL soll angeben, wo man die Quelltexte des Pakets beziehen kann. Wenn möglich kann hier die genaue URL zum Quelltext angegeben werden. Falls sich diese nicht eindeutig feststellen läßt ist aber auch die Homepage des Projektes zulässig.
Autors:Die eigentlichen Autoren des Programms. Diese sollten aus dem Quelltexten ersichtlich sein oder auf der Projekt-Homepage stehen. Notfalls sollte man per Email nachfragen. Da die hier gemachten Angaben durchaus von RPM-Datenbanken indiziert und auch im Internet angezeigt werden, ist die Angabe von Email-Adressen inzwischen leider unüblich geworden, da die Autoren ansonsten oft mit SPAM überschwemmt werden.
Source:Name des eigentlichen Paketes - also meist des Tarballs. Mehrere Dateien werden einfach durchnummeriert und können später über das Macro %SOURCE0 bzw. %SOURCE1 aufgerufen werden. Gewöhnen Sie sich ruhig schon so früh wie möglich daran, Macros zu benutzen und tragen Sie hier einfach %{name}-%{version}.tar.bz2 ein, sofern der Quelltext diese Struktur aufweist. (Denken Sie daran: "zippen" Sie die Dateien so klein wie möglich!)
Packager:Hier wird der Name des Paketbauers eingetragen - in der Regel also Ihr Name. Denken Sie bei der Angabe Ihrer Email-Adresse an den Hinweis unter "Authors" bezgl. SPAM.
NoSource:Für Dateien, die zwar zum Erzeugen eines RPMs genutzt werden, die aber aus lizenzrechtlichen Gründen nicht mit in das Source-RPM kommen dürfen. Dies kann bei kommerziellen Paketen, die die Quelltexte nicht freigeben, durchaus der Fall sein. Haben Sie mehrere solcher Quelltexte, werden diese ähnlich wie unter "Source" beschrieben durchnummeriert.
Patch:Name einer Patchdatei. Auch hier sind mehrere Dateien möglich, die dann wieder durchnummeriert werden. (Patch1, Patch2, Patch3, ...)
PreReq:Weist RPM an, die hier gelisteten Pakete (sofern vorhanden) zuerst zu installieren. Wichtig bei RPM-Aufrufen über die Kommandozeile oder bei Erstinstallationen. Sind die hier aufgeführten Pakete nicht vorhanden, wird die Installation abgebrochen.
Provides:Bietet zusätzlich zum eigentlichen Paketnamen andere Namen oder Funktionen mit an. z.B. "mailreader" oder "browser".
Damit kann RPM anderen Paketen dieses Paket anbieten, wenn diese eine solche Funktion über "Requires" anfordern.
Requires:Weist RPM an, zu überprüfen, ob die hier gelisteten Pakete im laufenden System installiert sind. Ansonsten wird die Installation abgebrochen. Achtung: hier nur diejenigen Pakete einfügen, die von "AutoReqProv" nicht erkannt werden.
Obsoletes:Wenn das Paket ältere Pakete ersetzt oder umbenannt worden ist, dann kann hier der alte Name angegeben werden, damit RPM wieder Abhängigkeiten auflösen kann.
BuildRoot:Hier sollte der Pfad zu einer "Build- Root- Umgebung angegeben werden (meist %{_tmppath}/%{name}-%{version}-build).
In diese Umgebung hinein werden später die fertig kompilierten Binaries und alle das neue Paket betreffenden Dateien gepackt. Dabei wird hier dann das normale Dateisystem nachgebildet, d.h. wenn Sie z.B. eine Datei später unter /usr/sbin ablegen möchten, legen Sie im %install-Abschnitt später das Verzeichnis innerhalb der BuildRoot-Umgebung mit install -d -m 700 %buildroot/usr/sbin an und installieren bzw. kopieren dort hinein dann die entsprechenden Dateien.
Damit können Sie später dann auch ganz einfach kontrollieren, ob Sie in Ihrem fertigen Paket etwas vergessen haben: vergleichen Sie einfach die Dateien im $RPM_BUILD_DIR-Verzeichnis (/usr/src/packages/BUILD/) mit denen im %buildroot-Verzeichnis.

Macros

Interessanter wird es nun in den nachfolgenden Sektionen des SPEC-Files. Hier kommen zunächst sogenannte "Macros" zum Einsatz, bei welchen es sich meist um kleine Skripte handelt, die dem Paketbauer die Arbeit abnehmen sollen. Macros werden dabei oft vom jeweiligen Distributor selbst geschrieben und auch bei der Installation von RPM installiert. Auf einige dieser Macros werden wir im weiteren Verlauf noch näher eingehen.

Aber auch Sie selbst können Macros schreiben und benutzen. Legen Sie sich dazu einfach eine Datei .rpmmacros im Homeverzeichnis ihres Benutzers an, mit welchem Sie RPMs bauen. (Wir werden im weiteren Verlauf noch eine "Rohform" solch einer Macro-Datei kennen lernen.)


Macros definieren

Ein Macro wird im einfachsten Fall folgendermaßen definiert:

%define <macroname> <wert></wert></macroname>
also z.B.
%define hello echo "hello world"

Sie können dieses Macro dann später im SPEC-File im einfachsten Fall wie folgt aufrufen:
%hello

Denken Sie daran, dass Macros nur aus einem zusammengesetzten Wort bestehen können. Leerzeichnen sind nicht zulässig.

Macros benutzen

Ein einfaches Macro läßt sich so benutzen:
%<macroname></macroname>

also z.B.
%hello

Kommt ans Ende des Macros noch irgendein weiterer Name und ist damit der eigentliche Macroname nicht mehr erkennbar, muss das Macro in geschweifte Klammern gesetzt werden. Das ist z.B. oft bei Verzeichnisnamen der Fall.


Weitere Informationen über Macros

Genauere Informationen über Macros und auch über schon vordefinierte Macros gibt es hier:

/usr/lib/rpm/macros
/usr/lib/rpm/noarch-linux/macros

und speziell für SUSE-Macros auch hier:
/usr/lib/rpm/suse_macros

Weitere Macros befinden sich hier:
/usr/lib/rpm/<arch>-linux/macros</arch>

wobei <arch> durch die jeweilige Architektur zu ersetzen ist.

Paketbau vorbereiten: prep

Das Macro %prep bereitet die Umgebung für den eigentlichen Paketbau vor. Hierzu gehört das Anlegen von temporären Verzeichnissen das Auspacken der Tarballs und das Patchen von Dateien.

%setup packt die unter SOURCE angegebenen Dateien aus. Egal, wie sie komprimiert sind (ein Macro halt... ...genau dieses Macro ist allerdings im rpm-Binary definiert icon_wink .

%setup enhält - genauso wie viele andere vordefinierten Macros verschiedene Optionen parat. Z.B. die Option -q lässt %setup die Datei leise auspacken.

%patch patcht eine Originaldatei mit der hier angegebenen Datei. Wichtigste Option ist hier die Option -p, welche dafür sorgt, dass eine bestimmte Anzahl von im Patchfile angegebenen Pfadelementen weggelassen wird. Also z.B. %patch -p1 sorgt dafür, dass der Patch nicht auf Dateien unter /usr/local/bin angewendet wird, sondern auf Dateien unter local/bin. Insbesondere in der BUILD-Umgebung macht das viel Sinn...

diff und patch
diff -u <originaldatei> <neudatei> > patchfile</neudatei></originaldatei> erzeugt eine neue Datei namens "patchfile", welche die Änderungen zwischen den Dateien <originaldatei> und <neudatei> enhält. Bitte beachten (besonders bei Kernelentwicklern icon_smile das Patches normalerweise mit patch -p1 eingespielt werden sollten (d.h. der Patch wird ausserhalb des Ursprungsverzeichnisses erstellt).
Eine Patchdatei sollte auch einen Header enthalten, welcher in kurzen Worten den Patch erläutert damit spätere Entwickler den Patch leicht nachvollziehen können.
patch -p1 < patchfile Patcht dann die im patchfile angegebene <originaldatei> mit den Änderungen in <neudatei>.</neudatei></originaldatei></neudatei></originaldatei>

Programm bauen: build

Hier passiert nun genau das, was man normalerweise an der Konsole mit dem Tarball machen würde. ./configure und make dürfte eigentlich bekannt sein. Aber weil das so langweilig ist, haben sich die Paketebauer gleich noch ein paar "Nettigkeiten" ausgedacht.


AutoConf

AutoConf steuert die Angleichung der Pfade und Umgebungsvariablen für verschiedene Architekturen, da diese dort oft unterschiedlich sind. Das normale AutoConf hinkt manchmal der Entwicklung (insbesondere der bei SUSE) hinterher - daher gibt es ein spezielles SUSE-Autoconf, welches mit %?suse_update_config aufgerufen wird.

Beispiel:
%build
%?suse_update_config
autoconf

Für den configure-Aufruf stellt SUSE wieder spezielle Distributionsmacros bereit, da nomalerweise die Programme sich nach /usr/local installieren würden. Für eine Distri-Standardkonfiguration mit dem Prefix /usr genügt heute: %configure -- Zusütze können einfach mit --Zusatz angefügt werden.

Wenn jetzt endlich alles soweit klar und (vielleicht noch mit speziellen Compilerflags wie z.B. %rpmoptflags) voreingestellt ist, sollte ein make und/ oder make install auch funktionieren und die Programme in die dafür vorgesehenen Verzeichnisse im "%buildroot" Verzeichnis installieren. Dieses liegt i.A. unter /var/tmp/<paketname>-<version>-build.


De-/Installation vorbereiten: pre und post

Manchmal müssen noch bestimmte Dinge erledigt werden, bevor ein RPM de-/installiert werden kann. Dafür gibt es dann noch die Abschnitte "pre" und "post" bzw. "preinst" und "postinst", welche meist kurze Scripte enthalten. Allerdings muss beachtet werden, dass bei einer Neuinstallation das eigentliche System noch in "/mnt" sein root-Verzeichnis hat. Hierzu bitte das Package-HowTo beachten!


Dateien einpacken: files

Jetzt muss man eigentlich dem RPM nur noch sagen, welche Dateien nun ins endgültige RPM-Paket kommen sollen. Dafür dient der "%files"-Abschnitt.

Jetzt hilft leider kein Skript und auch kein RPM mehr weiter: hier ist echte "Handarbeit" angesagt, weil ausser dem Paketbauer niemand wissen kann, welche Datei nun wirklich für das Paket gebraucht wird. Insofern ist das "nicht"-löschen des Build-Root-Verzeichnisses im Spec-File zunächst eine wertvolle Hilfe, da dort eigentlich alle Dateien enthalten sein müßten. (Kleine im Sourcecode schon fertige Skripte, Hilfedateien und Readme's fehlen aber oft trotzdem und liegen dann weiterhin unter /usr/src/packages/BUILD/<packetname></packetname>, wo sie von einem liebevollen Maintainer ins Build-Root-Verzeichnis kopiert werden möchten.)

Um den Dateien später unterschiedliche Rechte und Eigentümer zuzuweisen gibt es die Anweisungen %defattr für ganze Abschnitte und %attr für einzelne Dateien. Beispiel gefällig?

%defattr(-,root,root) behält die Dateirechte bei, ordnet aber alle Dateien und Verzeichnisse, die unter diesem Eintrag im Spec-File folgen, dem Nutzer root zu.

%attr(0644,hugo,hirsch) /var/lib/meinedatei ordnet <meinedatei> mit den Dateirechten 0644 dem Eigentümer hugo und der Gruppe hirsch zu.


Manuelles Paketebauen

Gebaut wird normalerweise als root auf dem lokalen System. Unter /usr/src/packages/SOURCES liegen die Source-Pakete (Tarballs) und unter /usr/src/packages/SPECS liegen die entsprechenden Spec-Files. Angestoßen wird der komplette Build-Prozess mit dem Befehl:

rpmbuild -ba <paketname>.spec</paketname>

im Verzeichnis /usr/src/packages/SPECS. Damit werden der Reihe nach alle Prozesse durchlaufen.

Wenn man nur einzelne Abschnitte des Spec-Files ablaufen lassen möchte, hilft ein Blick in man rpmbuild -- dort werden die einzelnen Optionen gelistet.<

Unter /var/tmp findet man normalerweise sowohl die "Changed Root Umgebung" als auch (besonders bei Fehlern) die temporären Files von RPM. Dort kann man (neben der Konsole) die Meldungen beim Paketbau nachlesen.


Wie fange ich an?

Am besten, man "übt" sich zunächst einmal im Neukompilieren von vorhandenen Paketen -- evtl. kann man diese auch gleich mal auf einen aktuelleren Stand bringen. Dafür müssen (über YaST2 oder über ein rpm -i <paketname>.src.rpm</paketname> oder <paketname>.spm) zunächst einmal die Source-RPMs installiert werden. Nach der Installation eines solchen Source-RPMs findet man unter /usr/src/packages im Verzeichnis SOURCES die Sourcen und in SPECS das Spec-File -- welch Wunder icon_wink </paketname>

Jetzt reicht es zum üben sicherlich aus, einfach mal in SPECS zu wechseln und den Befehl rpmbuild -ba <paketname>.spec</paketname> einzugeben.

Wer wissen will, was dann da so alles passiert, sollte u.a. die "rm"-Einträge im Spec-File entfernen, welche normalerweise ein aufgeräumtes System hinterlassen sollten. (Das ist zur späteren Fehlersuche und für die "%files"-Sektion auch sehr hilfreich!) Aber bitte nachher nicht vergessen, diese Einträge wieder zu setzen! Sonst gibts Haue von den Anwendern.

RPM-Inhalt
Wer ein fertiges RPM auf die in ihm enthaltenen Dateien untersuchen möchte, kann das an der Konsole mit rpm -qlp <paketname>.rpm</paketname> oder dem mc machen oder z.B. den Konqueror oder ark oder ... dazu nutzen.

Wer Informationen über ein RPM bekommen möchte nutzt
rpm -qpi <paketname>.rpm</paketname>

Das zugehörende Paket zu einer Datei findet man mit
rpm -qf <dateiname></dateiname>

Im nächsten Schritt empfiehlt sich einfach mal ein Update der im Paket enthaltenen Sourcen über die entsrechend angegebene Webseite. Die neuen Sourcen kommen also ins Verzeichnis SOURCES und nun wird das Spec-File angepasst. Wenn der Paket-Maintainer pfiffig ist, hat er Macros benutzt und man braucht im günstigsten Fall nur das Macro %version anzupassen -- wenn der Maintainer nicht pfiffig ist... ...hat man spätestens jetzt viel Spass!

Noch einmal der Hinweis: Für ein absolut neues Paket lohnt sich immer der Blick auf Spec-Files, die ähnliche Programme kompilieren.


Das erste RPM erstellen

Als erstes wollen wir uns mal ein eigenes RPM erstellen, welches es bestimmt noch nicht gibt: ein RPM mit unserem eigenen rpmkey.

Was ist das?

Wie ja von den vielen Windows-Würmern und Trojanern bekannt ist, kann man mit Binärpaketen jede Menge Unfug treiben. Weil auch unter Linux nicht jeder in den Quellcode der installierten Programme schaut (dazu müsste man dann ja die Source-RPMs installieren), kann man RPM-Pakete signieren und steht damit sozusagen "mit seinem guten Namen" für die Qualität des Pakets. Änderungen durch andere am Paket fallen nach der Signierung sofort auf und der Paketmanager weist ein verändertes Paket zurück anstatt es zu installieren. Damit das klappt, müssen wir zunächst einmal einen Schlüssel erzeugen, mit welchem wir später unser Paket signieren können.


GPG-Schlüssel erstellen

Um später nicht durcheinander zu kommen und auch, um den RPM-Schlüssel evtl. besser zu schützen als den "privaten" Schlüssel, lohnt es sich im allgemeinen, einen eigenen GPG-Schlüssel für die eigenen RPMs zu erzeugen.

Mit diesem Schlüssel werden dann die eigenen RPM-Pakete signiert - und natürlich stellt man den Nutzern seinen eigenen Schlüssel auch als RPM zur Verfügung, damit diese ihn "wie gewohnt" installieren können.

Zunächst erstellen wir nun einen Schlüssel, speziell für RPMs. Um nicht versehentlich den Schlüssel für die eigenen Emails und Dateien zu überschreiben, fertigen Sie bitte vorher ein Backup des Verzeichnisses ~/.gnupg an. Sollte das Verzeichnis sowieso noch nicht in ihrem Homeverzeichnis existieren, dann erzeugen Sie es spätestens jetzt mit dem Befehl:

mkdir ~/.gnupg

Nun erzeugen Sie einen GPG-Schlüssel mit dem Befehl:

gpg --gen-key

Hier ein Beispiel für den weiteren Ablauf:

GPG-Keyabfrage
/home/myuser> gpg --gen-key
Bitte wählen Sie, welche Art von Schlüssel Sie möchten:
(1) DSA und ElGamal (voreingestellt)
(2) DSA (nur signieren/beglaubigen)
(4) RSA (nur signieren/beglaubigen)
Ihre Auswahl? 1
Das DSA-Schlüsselpaar wird 1024 Bit haben.
Es wird ein neues ELG-E Schlüsselpaar erzeugt.
kleinste Schlüssellänge ist 768 Bit
standard Schlüssellänge ist 1024 Bit
größte sinnvolle Schlüssellänge ist 2048 Bit
Welche Schlüssellänge wünschen Sie? (1024) 2048
Die verlangte Schlüssellänge beträgt 2048 Bit
Bitte wählen Sie, wie lange der Schlüssel gültig bleiben soll.
0 = Schlüssel verfällt nie
<n> = Schlüssel verfällt nach n Tagen
<n>w = Schlüssel verfällt nach n Wochen
<n>m = Schlüssel verfällt nach n Monaten
<n>y = Schlüssel verfällt nach n Jahren
Wie lange bleibt der Schlüssel gültig? (0) 0
Key verfüllt nie.
Ist dies richtig? (j/n) j

Sie benötigen eine User-ID, um Ihren Schlüssel eindeutig zu machen; das
Programm baut diese User-ID aus Ihrem echten Namen, einem Kommentar und
Ihrer E-Mail-Adresse in dieser Form auf:
"Heinrich Heine (Der Dichter) <heinrichh@duesseldorf.de>"

Ihr Name ("Vorname Nachname"): Lars Rupp
E-Mail-Adresse: L.Rupp@web.de
Kommentar: RPM Key
Sie haben diese User-ID gewählt:
"Lars Rupp (RPM Key) <l.rupp@web.de>"

Ändern: (N)ame, (K)ommentar, (E)-Mail oder (F)ertig/(B)eenden?f
Sie benötigen eine Passphrase, um den geheimen Schlüssel zu schützen.
[...]
Öffentlichen und geheimen Schlüssel erzeugt und signiert.
Schlüssel ist als uneingeschränkt vertrauenswürdig gekennzeichnet.

pub 1024D/72496AA8 2005-04-18 Lars Rupp (RPM Key) <l.rupp@web.de>
Schl.-Fingerabdruck = 5565 536C 6FAE EA1F 70FC 7479 EAFF C76B 7249 6AA8
sub 2048g/DDB4A434 2005-04-18
</n></n></n></n>

Damit ist der neue Schlüssel erstellt. Nun sollten Sie zunächst feststellen, ob der Schlüssel auch richtig erstellt und in ihren persönlichen Schlüsselbund importiert wurde. Dafür lassen Sie sich nun einmal die Schlüssel in ihrem persönlichen Schlüsselbund ausgeben:

gpg --list-keys

Hier sollte nun auch ihr neu erzeugter Schlüssel auftauchen. Dieser Schlüssel sollte sich mindestens im Kommentar (RPM Key) von ihrem anderen Schlüssel unterscheiden (schlau, was? icon_wink .

Im nächsten Schritt exportieren Sie den öffentlichen Schlüssel, um ihn anschließend als root in die Paketdatenbank einzupflegen. Beim Export geben wir dem Schlüssel gleich einen "sprechenden" Namen und einen "geschütztes" ASCII-Aussehen, wie es die RPM-Regeln verlangen:

gpg --output linux-schulserver-lrupp.asc --armor --export 72496AA8

Durch output schreibt gpg direkt in eine Datei und diese Datei ist nach dem Schema <organisation>-<packager>.asc</packager></organisation> aufgebaut. Hinter export geben wir einfach die Schlüsselnummer des öffentlichen Schlüssels an.

Nun importieren wir diesen Key zunächst als root in die eigene RPM-Datenbank.

rpm --import linux-schulserver-lrupp.asc

Nun wirds ein wenig kniffelig: um später ein RPM mit unserem öffentlichen Schlüssel verteilen zu können, brauchen wir den RPM_DB_KEY unseres eigenen Schlüssels. Dazu müssen wir in der Paketdatenbank erst einmal unseren eigenen Schlüssel suchen. Erst einmal lassen wir uns alle vorhandenen Schlüssel in der Datenbank anzeigen:

rpm -q gpg-pubkey-*

Das gibt jetzt eine mehr oder weniger lange Liste mit:
gpg-pubkey-9c800aca-40d8063
gpg-pubkey-72496aa8-42640352
...

Jetzt müssen wir herausfinden, welcher der angegebenen Schlüssel in der Datenbank "unser" Schlüssel ist. Dazu fragen wir einfach für jeden gefundenen Schlüssel die Werte aus der Datenbank ab:

for i in `rpm -q gpg-pubkey-*`; do rpm -qi $i; done

Die Ausgabe sollte uns dann in der Summary irgendwann auch "unseren" Schlüssel liefern. Jetzt haben wir den RPM_DB_NAMEn unseres Schlüssels: gpg-pubkey-72496aa8-42640352

Diesen Namen stellen wir nun an den Begin unserer Export-Datei, damit man später leichter den Schlüssel in der Datenbank findet - und umgekehrt. Die resultierende Datei linux-schulserver-lrupp.asc sieht dann ungefähr so aus:

Schlüsseldatei für die RPM-Datenbank
RPMDB_NAME = gpg-pubkey-72496aa8-42640352

-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.2.5 (GNU/Linux)

mQGiBEJkA1IRBACT0edBxZbcANt0M1S/M0vDqV2Grq3fYquIxUZ3thZKRFQnMANm
z1m+IeFdSeaGkhezUO8JbjbWaunXPmMPZmiEi1DBxi5ho6Zuhr8yeRAR0n9Erwk7
uzSBhUNxBcCjaVpRt9hHzlOpPPdBnEU51c1E+D4Smf0ukJD48atGvI3qkwCg+jwG
//afL+DpMzUBgIoMkh7g5Q8D/0F+bDYoDynEZfJ/pMDSnp6hdIziZCjdCyK6ITMk
Uls+f++qvZTDi3MYzHMOB+90lvvPcEa+pBOZHrTT1LC2fCU/O3YPiZSq+AeWDhZp
uwWNbof9IXhonNGTl2EFrYZkauiWqSURtWwCErGjpNa5wEJUN83cj1L3nreq0XF4
iZnEA/98YrUFWZVQDsVpgWPMElqmYd3To512BP4llxVgQr1ZSisatl9Is8l3vJSq
LePkA73oLrqVW9FSnbFqLZ3gZoOR8FRSc69nzJqBAe2A/EUndJezljnHsBW73aNP
kTptwKSxLauqTAZWBJ9IoUpj+JSFVo7PzZwTEkHrCNTpdjma4bQjTGFycyBSdXBw
IChSUE0gS2V5KSA8TC5SdXBwQHdlYi5kZT6IXgQTEQIAHgUCQmQDUgIbAwYLCQgH
AwIDFQIDAxYCAQIeAQIXgAAKCRDq/8drcklqqPC/AJ9sLHleBjfrtyA6tU5VOwWO
PmG+LwCeNr0zh5b5ar/o/Vw4IKm1uuhl3RK5Ag0EQmQDhhAIANx5zVL3XJcJOyIN
K1KTPnBBYnfc1UfaEu+ngNIqAs6vR+C6qAGEPtm/dhZbjNGc5CJsLDd/YngQKLxu
hgxW4Gde6jE6OPczvKW2KCO7EWCIFBalqZxcOlBxNl27QdqiAcqm5bMsASCYU8wf
UisYTB7hYT0uW3gI39OuqOOUMBmcszApdpfvFpmDWpQSFWLheRuRdF8dLu+Yc/Hj
P+Akt3Ap/26vaMwxACgjGz3JBNHFvLHhKPbt5LvLL1AgTZ8bfbVQ8x6lz0Ei/OpH
fKfYV2mKKJkPtddExGmDZxlopRHvovWM6dXPkbt34fXzKW2PawTRLcgkGWD46C3A
AgfZvzMAAwYH/2hwF9tgz+Z+3vmbKJhthAP7geLW6jgFURNcoO7YXNfbwcWfIRDf
H1VmSAf17jMTs0g/Ya6+RoLsoUNVuddHDWyZVKUIF6vwclM0K4y+biM75CQYtWRa
LVTEowxhgEACa5hcQ9blN9v/TXoDMD5KP4NKeEENJhjTgJ+Fn+yyOa2f6IGJLPpC
dbkoD23guIArh+60T48jCWeX7ey9AZu/7iEdqTEEYHmtey0L3gUaxmdxeA0Sy81q
RzUTy/Uo4FW5yxijaNKvoZ76fzxRBlIk112iPbHqIoCNFKD6guuMnyLI3/6Nntnj
ha55vz7164yic7Fi1QGH370fEyJ9VvfmUc+ISQQYEQIACQUCQmQDhgIbDAAKCRDq
/8drcklqqOF/AKCESokOCQz9DE2H/eDsdf9+hJxkegCg5RMMTFt2eDzTbT4ZMsiG
aHsKpC4=
=Bdf5
-----END PGP PUBLIC KEY BLOCK-----

Jetzt haben wir eigentlich alles, um unsere eigenen RPM-Pakete zu signieren und um ein erstes, eigenes RPM herstellen zu können!


Das erste RPM

Um unseren RPM-Schlüssel zu verbreiten, erstellen wir nun ein RPM, welches nichts anderes macht, als unseren GPG-Schlüssel an die richtige Stelle im System zu "installieren", damit der Paketmanager später unsere Pakete verifizieren kann.

Das dafür nötige SPEC-File ist fast schon beschämend einfach - aber wir wollen ja auch einfach beginnen icon_wink

#
# Specfile for RPMDB_NAME = gpg-pubkey-f266f190-42af0345
# Lars Rupp (RPM Key) <l.rupp@web.de>
# Fingerprint: E56C 50AB B128 5E90 9CA0 AD3E DF11 30BA F266 F190
#
#
%define pubkeyname linux-schulserver-lrupp

# The public key file, should be named %{pubkeyname}.asc
# E.g. linux-schulserver-lrupp.asc

Summary: The %{pubkeyname} rpm public key
Name: rpmkey-%{pubkeyname}
Version: 0.1
Release: 1
Copyright: GPL
Group: System/Packages
Source: %{pubkeyname}.asc
Packager: Lars Rupp <l.rupp@web.de>
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-build

%description
The %{pubkeyname} rpm public key

%prep
%setup -c -T a1
%build
%install
mkdir -p %{buildroot}%{_libdir}/rpm/gnupg
cp -a %{SOURCE0} %{buildroot}%{_libdir}/rpm/gnupg

%files
%defattr(-, root, root)
/usr/lib/rpm/gnupg/%{pubkeyname}.asc

Dieses SPEC-File legen Sie mit dem Dateinamen rpmkey.spec im Verzeichnis /usr/src/packages/SPECS (oder /usr/src/rpms bei RedHat) ab und passen die Werte entsprechend an.

Jetzt fehlt nur noch die GPG-Datei linux-schulserver-lrupp.asc aus ~/.gnupg, welche ins Verzeichnis /usr/src/packages/SOURCES kopiert wird. Anschließend kann das RPM mit dem Befehl:

rpmbuild -ba /usr/src/packages/SPECS/rpmkey.spec

erzeugt werden.

Voila! Unser erstes RPM - und dann auch noch so ein nützliches...!

RPMs signieren

Jetzt können Sie das eben erzeugte (und natürlich auch alle weiteren) RPM mit ihrem eigenen Schlüssel signieren - und anhand des öffentlichen Schlüssels in der Paketdatenbank auch gleich überprüfen.

Zunächst sollten Sie dafür ihre eigene RPM-Macro-Datei (~/.rpmmacros) ein wenig erweitern (oder Sie neu anlegen). Dort sollten folgede Einträge enthalten sein:

%_signature gpg
%_gpg_name L.Rupp@web.de

Zum Signieren eines vorhandenen Pakets geben Sie nun einfach den Befehl:

rpm --addsign /usr/src/packages/RPMS/noarch/rpmkey-linux-schulserver-lrupp-0.1-1.noarch.rpm

ein. Sie werden dann nach der Passphrase gefragt und bei erfolgreicher Eingabe derselben wird das Paket signiert. Sie und jeder andere kann nun das Paket per Hand überprüfen:

rpm -qpi /usr/src/packages/RPMS/noarch/rpmkey-linux-schulserver-lrupp-0.1-1.noarch.rpm

Achten Sie hier auf die Zeile "Signature:" - hier finden Sie nun die Angaben zu ihrem Schlüssel.

Sie können das Paket nun auch jederzeit überprüfen:
rpm -vK rpmkey-linux-schulserver-lrupp-0.1-1.noarch.rpm

Erzeugt hier die folgende Ausgabe:
rpmkey-linux-schulserver-lrupp-0.1-1.noarch.rpm:
Header V3 DSA signature: OK, key ID 72496aa8
Header SHA1 digest: OK (d70d54dbbed78d790e3e728e6aa95e126a27e5d7)
MD5 digest: OK (8c2312ca651e0a1f43b37f9e180ae955)
V3 DSA signature: OK, key ID 72496aa8

...sieht alles in Ordnung aus. Der Paketmanager überprüft Pakete, die eine Signatur haben, übrigens automatisch und bemängelt sowohl falsche Prüfsummen als auch fehlende Schlüssel und installiert das Paket dann nicht.

</arch>


  

[ zurück zu Linux allgemein [31] | Index [32] ]

Kommentare

Einen Kommentar hinzufügen


Links
  [1] http://www.linux-schulserver.de/index.php?name=Sections&req=viewarticle&artid=32&allpages=1&theme=Printer
  [2] http://www.linux-schulserver.de/Sections-article32-p2.phtml
  [3] http://www.linux-schulserver.de/Sections-article32-p3.phtml
  [4] http://www.linux-schulserver.de/Sections-article32-p4.phtml
  [5] http://www.linux-schulserver.de/Sections-article32-p5.phtml
  [6] http://www.linux-schulserver.de/Sections-article32-p6.phtml
  [7] http://www.linux-schulserver.de/Sections-article32-p7.phtml
  [8] http://www.linux-schulserver.de/Sections-article32-p8.phtml
  [9] http://www.linux-schulserver.de/Sections-article32-p9.phtml
  [10] http://www.linux-schulserver.de/Sections-article32-p10.phtml
  [11] http://www.linux-schulserver.de/Sections-article32-p11.phtml
  [12] http://www.linux-schulserver.de/Sections-article32-p12.phtml
  [13] http://www.linux-schulserver.de/Sections-article32-p13.phtml
  [14] http://www.linux-schulserver.de/Sections-article32-p14.phtml
  [15] http://www.linux-schulserver.de/Sections-article32-p15.phtml
  [16] http://www.linux-schulserver.de/Sections-article32-p16.phtml
  [17] http://www.linux-schulserver.de/Sections-article32-p17.phtml
  [18] http://www.linux-schulserver.de/Sections-article32-p18.phtml
  [19] http://www.linux-schulserver.de/Sections-article32-p19.phtml
  [20] http://www.linux-schulserver.de/Sections-article32-p20.phtml
  [21] http://www.linux-schulserver.de/Sections-article32-p21.phtml
  [22] http://www.linux-schulserver.de/Sections-article32-p22.phtml
  [23] http://www.linux-schulserver.de/Sections-article32-p23.phtml
  [24] http://www.linux-schulserver.de/Sections-article32-p24.phtml
  [25] http://www.linux-schulserver.de/Sections-article32-p25.phtml
  [26] http://www.linux-schulserver.de/Sections-article32-p26.phtml
  [27] http://www.linux-schulserver.de/Sections-article32-p27.phtml
  [28] http://www.novell.com/linux/suse/
  [29] http://www.gnu.org/licenses/gpl.html
  [30] http://ftp.novell.com/pub/forge/library/SUSE%20Package%20Conventions/spc_rpm_groups.html
  [31] http://www.linux-schulserver.de/index.php?name=Sections&req=listarticles&secid=5
  [32] http://www.linux-schulserver.de/index.php?name=Sections