Créer un paquetage Manux : l'exemple de fblog

En petit bonus, voici la façon dont on procède pour créer un paquetage pour Manux. Comme exemple, nous allons utiliser fblog, un moteur de blog en fortran écrit par un utilisateur de Manux.

Avertissement

Manux est conçu, non seulement pour encaisser les exploits jour zéro, mais aussi pour permettre l'installation de paquetages délibérément hostiles sans dommage pour la sécurité du système. Ceci explique que les opérations de création d'un paquetage soient relativement complexes. De plus, le système est encore très récent, ce qui explique que les outils disponibles pour cette création soient assez peu conviviaux.

Premières opérations

Fortran n'est plus un langage très courant, dans le logiciel libre; en fait, c'est même la première fois de ma vie que j'en voyais. Mais c'est sans importance, puisque, pour le noyau, tant que l'exécutable est un binaire ELF ou un script interprété, il se moque de la façon dont celui-ci a été généré.

Cela dit, évidemment, Manux n'est actuellement pas livré avec un compilateur Fortran. Mais comme il y a des compilateurs Fortran pour Linux, et que Manux est binairement compatible avec Linux, il suffit de le compiler sous Linux.

Cela fait, on se crée un petit répertoire où construire notre paquetage :

mkdir fblog

Puis, créons-lui les répertoires de base qu'il doit contenir :

cd fblog/
mkdir root root/bin meta meta/crypto
mkdir lncb

Le répertoire meta/crypto est obligatoire, mais comme je n'ai pas encore fait le travail de cryptographie correspondant, il est pour l'instant vide. Quant au répertoire lncb, il n'est utile que pour les paquetages contenant des exécutables, ce qui est notre cas.

A présent, commençons à remplir ces répertoires. Plaçons-y le programme en question :

cp XXX/fblog ./root/bin/fblog 

Le fichier d'identité

Puis, remplissons le fichier d'identité du paquetage :

echo -n "contrib/0.0.1/fblog/0.5.1/fblog" > ./meta/identity
chmod 440 ./meta/identity

Explications : ce paquetage ne fait clairement pas partie du coeur du système (core), ni même des éléments standards habituels (std). Je n'en suis pas l'auteur, je ne vais donc pas inscrire "deber" (le surnom de l'auteur) comme distribution. Je le place donc dans "contrib".

La version actuelle de "contrib" est la même que celle de std, à savoir 0.0.1. Le logiciel s'appelle fblog, il est en version 0.5.1, et la portion du logiciel que j'empaquète est fblog (ç'auraient pu être les pages de manuel, que j'aurais alors nommées "contrib/0.0.1/fblog/0.5.1/man"). Pour finir, le logiciel s'appelle "fblog", pas "fblog\n", donc je fais bien un "echo -n".

Quant au mode 440, il s'agit d'une sécurité visant à distinguer les paquetages en cours d'installation des autres. Cela n'a pas grande importance pour nous, si ce n'est que le créateur de paquetages refusera de le créer si le fichier est dans un mode différent.

Les dépendances

À présent, je passe aux dépendances. Celles-ci doivent être listées dans le fichier meta/deps du paquetage.

Il se trouve par hasard que fblog ne dépend d'aucune bibliothèque :

$ file root/bin/fblog
root/bin/fblog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), statically linked, for GNU/Linux 2.6.26, BuildID[sha1]=0x021dfe13caebd228b7601e0d7deacefb7dc42251, stripped

C'est assez rare; habituellement, il y a au moins une dépendance sur la glibc. Cependant, il y a des dépendances sur des programmes externes, à savoir cp, rm, mkdir, stty, ls, et vi (j'ai tout simplement obtenu cette liste par l'auteur), ainsi que sur addr2line, /proc (repérés par strace) et vraisemblablement /dev/null. Cependant, il ne se sert de /proc que pour lire /proc/self/exe (sans doute pour addr2line); sur ce point, on peut se permettre de le lui indiquer en dur, ce sera plus simple. Ceci me donne le fichier de dépendance suivant :

2012:0^@std/0.0.1/coreutils/8.19/cp/L///std/0.0.1/coreutils/8.19/mkdir/L///std/0.0.1/coreutils/8.19/ls/L///std/0.0.1/coreutils/8.19/rm/L///std/0.0.1/coreutils/8.19/stty/L///std/0.0.1/vim/7.3/vim/L////std/0.0.1/vim/7.3/alias/E///std/0.0.1/binutils/2.22/addr2line/L///core/0.0.1/dev/1.0/std/E

(Plutôt que de m'embêter à l'écrire de zéro, j'ai recopié le fichier de dépendance d'un autre paquetage, et je l'ai adapté.) Décrivons la première dépendance : il s'agit d'une dépendance sur un paquetage de la distribution "std", version de la distribution "0.0.1", logiciel "coreutils", version "8.19 OU SUPÉRIEURE" (si j'avais voulu une dépendance précisément sur la version 8.19, j'aurais dû écrire 8.19^@8.19, où ^@ représente un caractère nul), portion du logiciel "cp", type de la dépendance L (lanceur seulement). La dernière, en revanche, est une dépendance de type E (entière), c'est-à-dire que tous les fichiers qui s'y trouvent doivent être exportés à destination de mon paquetage.

(Pour ceux qui ont repéré la bizarrerie, oui, il y a bien deux paquetages vim dans cette liste. L'un fournit l'exécutable /usr/bin/vim, l'autre le lien symbolique /usr/bin/vi -> vim.)

Ce fichier ne comporte pas de retour-chariot, pas même à la fin, c'est parfaitement normal ("\n" est un caractère acceptable dans un nom de fichier, y compris dans un nom de paquetage).

Ah, n'oublions pas que j'avais dit qu'il fallait lui mentir sur /proc/self/exe :

$ mkdir root/proc root/proc/self
$ ln -s /bin/fblog root/proc/self/exe 

Cela évite de lui donner un accès complet à /proc pour obtenir une information que nous pouvons lui indiquer en dur.

Le script d'installation

Une fois les dépendances faites, je crée le script d'installation. Il s'agit du fichier meta/install, dont le contenu, dans notre cas, doit être :

#!/bin/sh
# $1 contains the root of the package, $2 the identity file.
/bin/pupresdeps $2
if [ $? -ne 0 ] ; then
        exit 1
fi

/bin/pupmktmp $2
if [ $? -ne 0 ] ; then
        exit 1
fi

/bin/pupmklnc $2 lncb/fblog.lncb
if [ $? -ne 0 ] ; then
        exit 1
fi

Le premier appel demande la résolution des dépendances du paquetage (ah oui, ça peut être utile, ça), le second lui crée un répertoire /tmp (je ne suis pas certain que cela serve, mais pour ce que cela coûte...), le troisième crée son lanceur à partir de son lanceur binaire.

On ne peut pas simplement mettre un répertoire nommé /tmp dans le paquetage : si on le faisait, non seulement il y aurait des problèmes de droits, mais surtout, celui-ci ne serait jamais nettoyé. Pour que son contenu soit effacé, il faut créer un lien matériel vers ce répertoire dans l'arborescence du programme chargé de ce nettoyage; c'est ce que fait pupmktmp.

Le fichier binaire du lanceur

En ce qui concerne pupmklnc, on remarque qu'on lui a indiqué un fichier qui n'existe pas encore : le fichier binaire lncb/fblog.lncb. Pour le créer, je pourrais me référer à la spécification de ces fichiers, et utiliser un éditeur hexadécimal, mais je pense que mon lecteur me pardonnera si j'emploie des méthodes plus compréhensibles. Cependant, dans la mesure où les explications seraient un peu longues, je ne détaillerai pas ces opérations.

$ tools/mklncp --prg /bin/fblog --caps GLIBC+OPEN_R+OPEN_W+CREAT+UNLINK+UMASK+STAT+RENAME+CLONE+EXEC --with-path
VER:2012:0
PRG:/bin/fblog
PRT:00101d8b00000006
PTM:1
PTNF

Hmm... Oui, cela ressemble bien à ce que j'attendais : fblog ne prend aucun fichier sur sa ligne de commande (PTNF), il reçoit toujours son chemin courant (PTM:1), il s'appelle /bin/fblog, et il utilise diverses capabilités que je ne détaillerai pas ici.

Donc...

$ tools/mklncp --prg /bin/fblog --caps GLIBC+OPEN_R+OPEN_W+CREAT+UNLINK+UMASK+STAT+RENAME+CLONE+EXEC --with-path | ./manux/usr/launcher/parse_lnc > fblog/lncb/fblog.lncb

La liste des fichiers

Ça y est, le fichier lncb est créé. Il ne reste plus qu'une seule chose à faire, créer la liste des fichiers (meta/files). Heureusement, il y a un programme conçu pour :

./manux/usr/pup/pupmkpkgfileslist ./fblog

Cela dit, ce programme omet délibérément /proc; il faut donc rajouter /proc/self/exe manuellement à la liste des fichiers du paquetage. Je sais, ce n'est pas très beau... Mais c'est actuellement nécessaire.

La création du paquetage

Parfait! Maintenant, demandons à pupmk d'en faire un paquetage :

./manux/usr/pup/pupmk fblog fblog.pup

C'est fait! Le paquetage est créé, nous pouvons détruire tous les éléments intermédiaires (notamment le répertoire fblog).

L'installation

Installons-le, à présent. C'est facile, il suffit d'utiliser pupinstall :

pupinstall fblog.pup

La mise à disposition du programme

Cela dit, sous Manux, un logiciel installé n'en est pas pour autant utilisable par tous les utilisateurs; c'est l'administrateur de la machine qui décide quel utilisateur a accès à quel programme. Heureusement, nous sommes l'administrateur. Nous pouvons donc nous le rajouter dans la liste des logiciels auxquels nous avons accès; laquelle est implémentée comme un simple fichier de dépendance :

$ echo -n "///contrib/0.0.1/fblog/0.5.1/fblog/L" >> /packages/core/0.0.1/rootfs/1.0/roots/root/roots/ecolbus/meta/deps

Puis demander une nouvelle résolution de nos propres dépendances :

$ chmod 440 /packages/core/0.0.1/rootfs/1.0/roots/root/roots/ecolbus/meta/identity
$ pupresdeps /packages/core/0.0.1/rootfs/1.0/roots/root/roots/ecolbus/meta/identity

Cela fait, fblog apparaîtra dans notre répertoire /bin.

Conclusion

Ceci illustre les opérations à réaliser pour créer et installer un paquetage sous Manux. Comme je le disais au début, ce n'est pas très intuitif, et parfois assez laborieux, et surtout, les sécurités imposent d'effectuer des opérations qui n'ont pas d'équivalent sous les autres systèmes d'exploitation. Le second point est le prix à payer pour disposer de sa sécurité, tandis que le premier traduit la grande jeunesse du logiciel.

Si vous souhaitez tester ce paquetage sans le construire vous-même, il est disponible à cette adresse.

Page principale