Page suivante Page précédente Table des matières

5. Introduction à l'utilisation de patch.

5.1 Introduction

Cet article a pour but de présenter aux nouveaux utilisateurs de Linux le programme patch, de Larry Wall, une ressource inestimable s'il en est. Patch est une interface pour le programme GNU diff, qui sert à trouver des différences entre des fichiers. Diff dispose de nombreuses options, mais il est utilisé le plus souvent pour créer un fichier qui recense les lignes qui ont changé, en indiquant uniquement les lignes qui diffèrent, et leurs originaux. Patch sert habituellement à mettre à jour un repertoire contenant des sources, ce qui évite de télécharger l'intégralité d'un programme. Télécharger un patch revient à récupérer uniquement les lignes modifiées.

Patch est né à l'époque de l'émergence de l'Internet, il y a une dizaine d'année, à une époque ou la bande passante était une ressource très limitée. Comme nombre d'outils Unix de cette époque, il est encore très utilisé de nos jours. Dans le numéro de Février de Dr Dobb's Journal, Larry Wall a fait ces remarques au sujet de patch :

DDJ : Quel a été le premier programme, patch ou diff ?

LW : Diff, et de beaucoup. Avec le recul, je suis tout à fait étonné que personne n'y ait pensé plus tôt, car diff, je pense, est sorti une dizaine d'année avant patch. Je pense que c'est pour des raisons psychologiques. Quand diff a été écrit, on y a mis l'option -e, qui fabriquait un script ed, et les gens se disaient : « Si je veux automatiser l'application d'un patch, je m'en servirai. ». Mais en fait, personne n'a pensé à écrire un programme qui puisse prendre plusieurs formats et les appliquer. À moins qu'il n'y ait eu une raison particulière d'utiliser le context diff, plus facile à appliquer à une source déjà modifiée. L'idée ne m'est pas venue d'un coup, dans un éclair de génie : il s'agissait plutôt de me faciliter la vie. J'ai publié la première version de rn, puis j'ai commencé à sortir des patches, et ce fut la pagaille. Les gens ne voulaient pas appliquer des patches à la main, donc ils sautaient ceux qui ne leur semblaient pas nécessaires, et ils étaient coincés par la suite, au moment d'appliquer d'autres patches plus récents. J'ai écrit patch pour qu'ils n'aient pas l'excuse de la difficulté. Je ne sais pas si c'est toujours le cas, mais j'ai pu dire pendant des années que je pensais que patch avait plus révolutionné la culture informatique que rn ou Perl. L'Internet de nos jours est plus rapide, et il est plus facile de distribuer des paquetages complets. Les patches ne sont plus échangés qu'entre programmeurs, et patch est donc devenu moins important, mais il continue d'être un bon moyen d'échanger des idées.

La constatation de Larry Wall sur l'importance déclinante de patch est probablement vraie, mais dans le monde du logiciel libre, c'est un outil essentiel. L'omniprésence de patch permet aux utilisateurs de participer facilement aux tests des pré-versions des logiciels, ce qui profite à toute la communauté.

J'ai eu l'idée d'écrire cet article en remarquant une discussion récurrente sur la liste de diffusion linux-kernel. Tous les trois mois environ, quelqu'un demande que les sources de Linux soient séparées, de sorte que quelqu'un qui aurait seulement besoin, par exemple, du code i386 et d'un pilote pour disque dur IDE ne soit pas obligé de télécharger les fichiers pour Alpha, Sparc... et les nombreux pilotes SCSI à chaque nouvelle version du kernel. Il s'ensuit une série de réponses conseillant l'utilisation des patches pour se mettre à jour. Linus Torvalds répond alors que le travail nécessaire pour couper en morceaux les sources du noyau ne l'intéresse pas, mais que chacun est libre de le faire s'il le souhaite. Jusqu'à présent, personne ne s'est porté volontaire. On ne peut pas en vouloir aux programmeurs du noyau de ne pas vouloir se compliquer la vie : j'imagine qu'il est plus passionnant de travailler sur le noyau lui-même plutôt que de penser à réorganiser tout le système de distribution. Télécharger un fichier de 11 Mo prend du temps, et de l'argent pour ceux qui payent leur connexion à la durée, mais les patches du noyau ne prennent que quelques dizaines de Ko en général, et très rarement plus qu'un Mo. J'ai mis à jour petit à petit mes sources du noyau de la version 2.1.99 à la version 2.1.119, et je n'aurais probablement pas suivi le développement d'aussi près si j'avais eu à récupérer la totalité de chaque version.

5.2 L'utilisation de patch.

Patch est accompagné d'une documentation de bonne qualité qui recense ses multiples options, mais dans 99% des cas, seules deux d'entre elles sont utiles :

  • patch -p1 < [fichier_de_patch]
    
  • patch -R < [fichier_de_patch]
    
    (pour enlever un patch)
  • L'option -p1 supprime le premier niveau de l'arborescence dans les noms de fichier contenus dans le fichier de patch, ce qui est utile puisque le premier niveau change souvent d'une machine à l'autre. Pour utiliser cette option, mettez le patch dans le répertoires à modifier, et exécutez patch -p1 < [fichier_de_patch] dans ce répertoire. Voici un exemple :

    diff -u --recursive --new-file v2.1.118/linux/mm/swapfile.c linux/mm/swapfile.c
    --- v2.1.118/linux/mm/swapfile.c        Wed Aug 26 11:37:45 1998
    +++ linux/mm/swapfile.c Wed Aug 26 16:01:57 1998
    @@ -489,7 +489,7 @@
            int swap_header_version;
            int lock_map_size = PAGE_SIZE;
            int nr_good_pages = 0;
    -       char tmp_lock_map = 0;
    +       unsigned long tmp_lock_map = 0;
    

    L'option -p1 va couper le chemin d'accès. Patch va chercher un sous-répertoire appelé /mm, et y trouver le fichier swapfile.c. La ligne commençant par un moins sera remplacée par la ligne commenceant par un plus. Un patch contient en général des mises à jours pour plusieurs fichiers. Il est divisé en section formées par le résultat d'un diff -u entre les deux versions d'un fichier.

    Patch affiche ses commentaires à l'écran, mais ils défilent en général trop vite pour être lus. Les fichiers de départ sont rebaptisées en *.orig, tandis que les nouvelles versions prennent le nom des anciennes.

    5.3 Problemes avec patch.

    Certains problèmes avec patch proviennent des différences entre les versions disponibles sur Internet d'un même programme. Larry Wall n'a pas fait grand chose pour améliorer patch ces dernières années, principalement parce que la dernière version fonctionne bien dans la plupart des cas. Les programmeurs de la FSF chargés du projet GNU ont fait de nouvelles versions. Leur premier essai avait quelques problèmes, mais j'utilise la version 2.5 (distribuée avec la Debian 2.0) sans problème. La version 2.1 fonctionnait tout aussi bien chez moi. Les sources de la version GNU actuelle sont disponibles sur leur site FTP, mais dans la plupart des cas vous pouvez utiliser celle qui est fournie avec votre distribution de linux.

    Si vous mettez à jour un répertoire, et que tout ne se passe pas comme prévu, patch affichera un message d'erreur contenant le nom du fichier et le numéro de ligne. Parfois l'erreur est évidente, quand il manque un ; par exemple, et on peut la corriger sans difficulté. On peut aussi supprimer la partie du fichier de patch qui pose problème. Cela peut marcher ou pas, selon la nature du patch.

    Un scénario courant : après avoir décompressé les sources du noyau de Linux, vous avez exploré l'arborescence, et vous avez remarqué les sous-repertoires consacrés aux différentes architectures : Sparc, Alpha... Comme vous utilisez une architecture Intel, vous avez effacé ces répertoires, qui ne vous servent à rien, pour gagner de l'espace disque. Et quand vient l'heure de mettre les sources à jour, patch bloque car il n'arrive pas à trouver des fichiers pour Alpha ou PPC. Heureusement, patch permet à l'utilisateur d'intervenir, et il pose la question « Skip this patch ? ». Il suffit de répondre y et tout ira bien. Il vous faudra probablement répondre à cette question à de nombreuses reprises, ce qui incite, tout compte fait, à laisser ces répertoires inutiles sur le disque dur.

    5.4 Astuces pour mettre le noyau à jour.

    La plupart des linuxiens se servent de patch uniquement pour le noyau. Voici donc quelques astuces. La méthode la plus simple consiste à utiliser le script shell « patch-kernel », situé dans le répertoire /script des sources du noyau. Ce script pratique et bien écrit a été conçu en 1995 par Nick Holloway. Quelques années plus tard, Adam Sulmicki y ajouta la gestion de plusieurs algorithmes de compression, dont bz, bz2, compress, gzip, et du texte brut. Le script suppose que les sources sont placées dans /usr/src/linux, et que le patch est situé dans le répertoire courant. Ces deux choix par défaut peuvent être modifiés par des options sur la ligne de commande :

    patch-kernel [répertoire des sources] [répertoire du patch]
    

    Patch-kernel s'arrêtera si les modifications échouent, mais si tout va bien il utilisera find pour trouver les fichier *.orig et les détruire.

    Si vous préferez voir le résultat des commandes, ou si vous voulez conserver les fichiers *.orig jusqu'à ce que vous soyez certain que les sources modifiées se compilent correctement, lancez directement patch après avoir placé le patch dans les répertoire des sources, comme indiqué plus haut. C'est très fiable. Si vous ne voulez pas décompresser d'abord, utilisez un pipe :

    gzip -cd patchXX.gz | patch -p1
    

    ou

    bzip2 -dc patchXX.bz2 | patch -p1
    

    Après avoir modifié les sources, faites appel à

    find . -name \*.rej
    

    pour trouver les erreurs. La syntaxe de cette commande paraît compliquée au début.

    • Le point indique que find doit chercher dans le répertoire courant et dans tous ses sous-répertoires. N'oubliez pas l'espace avant et après ;
    • la barre oblique inverse avant le caractère * évite qu'il soit interprété par le shell.

    Si find trouve des fichiers correspondant à *.rej, il affichera leur nom à l'ecran. Si find n'affiche rien, la mise à jour s'est probablement déroulée sans erreur.

    On peut aussi se servir de find pour supprimer les fichiers *.orig :

     
    find . -name \*.orig -print0 | xargs -0r rm -f 
    

    Cette commande, pratique mais encombrante, peut faire l'objet d'un alias : en bash, ajouter

    alias findorig 'find . -name \*.orig -print0 | xargs -0r rm -f'
    

    dans votre fichier  /.bashrc vous permettra de faire appel à cette commande en tapant simplement findorig. Les apostrophes sont nécessaires car la commande contient des espaces. Pour utiliser votre nouvel alias sans se delogguer et se logguer à nouveau, tapez au prompt :

    source ~/.bashrc
    

    5.5 Commentaires et conclusion.

    Tout en écrivant cet article, je suis passé de la version 2.1 à la version 2.5 de patch. Ces deux versions proviennent des mainteneurs de la FSF et du projet GNU. J'ai tout de suite remarqué que la sortie à l'écran avait changé, et qu'il s'affichait moins d'informations. On ne lis plus les « ...hmm » de Larry Wall lorsque patch tente de déterminer les lignes à modifier. La version 2.5 affiche simplement des messages comme « patching file [nom_du_fichier]nbsp;», au lieu des informations plus complètes des versions précédantes. Certes, elles défilaient trop vite pour être lues, mais il était toujours possible de les rediriger vers un fichier. Ce changement ne diminue pas les fonctionnalités du programme, mais il lui fait perdre un peu de son âme. Des détails comme les messages affichés ou les commentaires dans les sources rappellent à l'utilisateur qu'un programme est le fruit du travail d'un homme, et pas une simple suite de 0 et de 1. On peut retrouver cet affichage avec l'option --verbose mais la plupart des utilisateurs ne la connaîtront pas ou ne se fatigueront pas à la taper. Autre différence : dans la nouvelle version, les fichiers *.orig ne sont pas créés si l'on n'utilise pas l'option -b.

    Patch n'est pas absolument nécessaire pour l'utilisateur final qui ne veut pas essayer et tester les logiciels en version beta et les noyaux de développement, mais c'est souvent durant ces tests que se passent les choses les plus intéressantes. L'effort, minime, pour apprendre à utiliser patch sera vite largement compensé.


    Publié dans le Numéro 32 de la Linux Gazette -- Septembre 1998

    Vincent Stemen

    Adaptation française : Marc Simon.


    Page suivante Page précédente Table des matières