Ersetzen eines Symlinks durch ein Verzeichnis oder ein Verzeichnis durch eine Datei beliebigen Typs

Aufgrund einer bekannten Einschränkung von RPM ist es nicht möglich, ein Verzeichnis durch eine beliebige Datei oder einen symbolischen Link zu ersetzen. Ebenso wenig ist es möglich, einen symbolischen Link zu einem Verzeichnis durch ein Verzeichnis zu ersetzen, ohne dass RPM beim Installationsversuch des Pakets Dateikonflikte ausgibt. Weitere Informationen zu den Problemen finden Sie unter Bug 447156 und Bug 646523.

Versuchen, das Problem von vornherein zu vermeiden

Es ist zwar nicht möglich, alle Fälle vorherzusehen, in denen dies erforderlich sein könnte, aber wenn der Bedarf vorhersehbar ist, wie beispielsweise bei gebündelten Bibliotheken, ist es besser, von Anfang an einen symbolischen Link zu verwenden, da sich das Ziel des symbolischen Links leichter ändern lässt. Wenn Sie beispielsweise eine gebündelte libfoo-Bibliothek innerhalb der Verzeichnisstruktur des Pakets haben, platzieren Sie diese beispielsweise in einem Verzeichnis libfoo.bundled und erstellen Sie einen symbolischen Link von libfoo zu diesem Verzeichnis. Wenn die Bündelung schließlich entfernt wird, müssen Sie lediglich das Verzeichnis löschen und den symbolischen Link so ändern, dass er auf das entsprechende Systembibliotheksverzeichnis verweist, ohne auf die unten beschriebenen Skripte zurückgreifen zu müssen.

Umgehung des Problems mit Scriptlets

Um dieses Problem zu umgehen, müssen Sie ein %pretrans-Scriptlet einfügen, das die Konvertierung manuell durchführt, bevor RPM versucht, das Paket zu installieren.

Beachten Sie, dass die '%pretrans'-Scriptlets in Lua geschrieben sein MÜSSEN und daher -p <lua> verwenden, um in der frühen Phase der Systeminstallation zu funktionieren, wenn noch keine Shell installiert ist.

Bitte verwenden Sie in Paketen, die diese Umstellung benötigen, den jeweils erforderlichen der beiden folgenden Code-Schnipsel und ersetzen Sie /Pfad/zum/Verzeichnis durch den Pfad zu dem Verzeichnis, das konvertiert werden soll.

Scriptlet zum Ersetzen eines Verzeichnisses

RPM kann ein Verzeichnis nicht einfach löschen, wenn es durch eine Datei oder einen symbolischen Link ersetzt wird, da Benutzer möglicherweise Dateien in diesem Verzeichnis hinzugefügt oder geändert haben. Um versehentlichen Datenverlust zu vermeiden, MÜSSEN Sie das folgende Skript verwenden, das das Verzeichnis mit der Endung .rpmmoved umbenennt, so dass Benutzer das gesicherte Verzeichnis nach der Paketaktualisierung bei Bedarf wiederfinden können. (Es wird außerdem eine Ganzzahl an die Endung angehängt, falls dieses Verzeichnis in seltenen Fällen bereits existiert.)

%pretrans -p <lua>
-- Define the path to directory being replaced below.
-- DO NOT add a trailing slash at the end.
path = "/path/to/dir"
st = posix.stat(path)
if st and st.type == "directory" then
  status = os.rename(path, path .. ".rpmmoved")
  if not status then
    suffix = 0
    while not status do
      suffix = suffix + 1
      status = os.rename(path .. ".rpmmoved", path .. ".rpmmoved." .. suffix)
    end
    os.rename(path, path .. ".rpmmoved")
  end
end

Darüber hinaus sollten Sie das Verzeichnis /path/to/dir.rpmmoved als einen %ghost-Eintrag in der %files-Liste in der Spec-Datei des Pakets definieren, damit das Verzeichnis nicht völlig verwaist ist und gelöscht werden kann, falls das Paket jemals deinstalliert wird und das Verzeichnis leer ist.

Das Ersetzen eines symbolischen Links durch ein reguläres Verzeichnis ist wesentlich einfacher, da so keine Gefahr besteht, versehentlich extern hinzugefügte Dateien zu löschen. Das folgende Skript prüft auf den symbolischen Link und entfernt ihn. Das Verzeichnis muss hier nicht erstellt werden, da RPM dies später bei der Paketinstallation erledigt.

%pretrans -p <lua>
-- Define the path to the symlink being replaced below.
path = "/path/to/dir"
st = posix.stat(path)
if st and st.type == "link" then
  os.remove(path)
end