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.
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-nud, 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.
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.
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