TD 8: recherche multi-critères

Tristan Crolard - François Pottier

Rappelons que les sujets et corrigés de chaque TD sont accessibles sur les machines des élèves, dans ~pottier/TD-Systems-98-99/. Essayez les programmes, modifiez-les, exécutez-les pas-à-pas, etc. pour mieux comprendre leur fonctionnement.

Définition d'un critère de recherche

On souhaite réécrire une version simplifiée de la commande find, qui recherche, dans une arborescence de fichiers, tous ceux qui satisfont certains critères. Les critères que nous utiliserons sont la recherche par nom, par numéro d'i-n\oeud, par taille minimum et par taille maximum. Nous avons donc quatre sortes de critères, et nous souhaitons pouvoir combiner des critères de sortes différentes. Une combinaison de critères sera représentée par les variables globales suivantes:

    #define BY_NAME (1<<0)
    #define BY_INUM (1<<1)
    #define BY_LE   (1<<2)
    #define BY_GE   (1<<3)

    static int              gOptions;
    static char*            gName;
    static int /* ino_t */  gInode;
    static int /* off_t */  gLowLimit, gHighLimit;
La variable gOptions est un champ de bits qui indique quelles sortes de critères sont superposées ici. Quatre masques sont définis, à l'aide de macros, pour faciliter l'accès à chacun des quatre bits de ce champ. Lorsque le bit BY_NAME du champ gOptions vaut 1, alors (et alors seulement) la variable gName contient le nom souhaité. Les variables gInode, gLowLimit et gHighLimit sont utilisées de façon similaire.

On demande, en première question, d'écrire une fonction

    int satisfaction (const char *inName, const struct stat* inStat);
dont les arguments sont un nom de fichier ou de répertoire inName et une structure inStat que l'on suppose obtenue par un appel à stat; la fonction renverra un booléen indiquant si le critère défini ci-dessus est ou non satisfait par ce fichier.

Recherche récursive

On écrira ensuite une fonction

    void recherche (const char *inDirectoryName);
Cette fonction devra parcourir le répertoire dont le nom complet est donné en argument. Pour chaque entrée du répertoire (exceptées les entrées . et ..), elle construira le nom complet de l'entrée, puis vérifiera que cette entrée satisfait les critères définis plus haut, à l'aide de la fonction satisfaction. En cas de succès, elle affichera son nom complet sur la sortie standard. S'il s'agit d'un sous-répertoire, il sera lui-même parcouru, récursivement.

myfind

On passera enfin au programme principal, qui devra reconnaître les options suivantes:

    Usage: myfind <dir> [-name <name>] [-inum <inum>]
                        [-le <size>] [-ge <size>]
On vérifiera d'abord que le nombre d'arguments est bien un nombre pair strictement supérieur à 2 (pourquoi?), puis on lira les options les unes après les autres pour initialiser les variables globales qui définissent le critère de recherche. Pour convertir une chaîne de caractères en un entier, on utilisera la fonction sscanf. Enfin, une fois le critère de recherche reconnu, on effectuera la recherche.

Voici un exemple d'utilisation du programme complet:

    $ myfind . -ge 3000 
    ./myfind.c
    ./myfind.o
    ./myfind



Jean-Baptiste Yunes
1999-02-05