TD 5: arborescence des répertoires

Tristan Crolard - François Pottier

Résumé:

opendir, readdir, closedir, stat, IS_DIR (POSIX.1); perror, strlen, strcpy, strcat, strcmp (ANSI C, POSIX.1).

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.

Les systèmes conformes au standard POSIX.1 fournissent les fonctions suivantes pour déterminer le contenu des répertoires:

        #include <sys/types.h>
        #include <dirent.h>

        DIR* opendir (const char* name);
        struct dirent* readdir (DIR* dir);
        int closedir (DIR* dir);
On passe à opendir le nom d'un répertoire. Elle renvoie alors un descripteur, de type DIR*. En cas d'erreur, le descripteur renvoyé est NULL et la variable globale errno est mise à jour. Dans le cas contraire, on peut passer ce descripteur à readdir.

Chaque appel successif à readdir renvoie un pointeur sur une structure de type struct dirent, qui décrit l'un des fichiers ou répertoires contenus dans le répertoire parcouru. readdir renvoie NULL lorsque le dernier fichier a été lu. Les champs de la structure dirent ne sont pas spécifiés par le standard POSIX; on sait seulement qu'elle contient au moins un champ char d_name[], qui contient le nom du fichier ou sous-répertoire considéré. Ce nom contient au plus NAME_MAX caractères.

Enfin, closedir ferme le descripteur de répertoire fourni.

Affichage du contenu du répertoire courant

On souhaite réécrire une version simplifiée de la commande ls, qui affiche le contenu d'un répertoire donné. Écrire une fonction

        int Liste (const char* dirname);
qui consulte le répertoire dirname et en affiche le contenu. Le nom de chaque élément du répertoire sera affiché, à raison d'un nom par ligne. Si l'ouverture au répertoire échoue, on affichera un message d'erreur à l'aide de la fonction perror, et la fonction Liste terminera.

Les entrées . et .., qui correspondent au répertoire courant et à son père, ne seront pas affichées. On utilisera la fonction standard strcmp pour effectuer la comparaison entre chaînes de caractères. Cette fonction renvoie 0 en cas d'égalité.

La fonction Liste renverra 1 en cas de succès et 0 en cas d'erreur.

Affichage récursif

On souhaite à présent passer à l'échelle supérieure, en écrivant une fonction capable d'afficher le contenu d'un répertoire et de tous ses sous-répertoires (ce qui correspond à la commande ls -R). Écrire une fonction

        void ListeRecursive (const char* dirname);
qui effectue cette tâche. Plus précisément: Notons que pour construire le nom complet du sous-répertoire, il faudra d'abord allouer une place suffisante en mémoire à l'aide de malloc. Les fonctions standard strlen, strcpy et strcat seront utiles.

Enfin, pour déterminer si un élément est ou non un répertoire, on utilise la fonction POSIX suivante:

        #include <sys/stat.h>
        #include <unistd.h>

        int stat(const char *file_name, struct stat *buf);
Cette fonction demande un nom de fichier, et renvoie une quantité d'informations à son propos, qu'elle stocke dans une structure de type struct stat, qui doit avoir été allouée par vous (le plus simple est d'en faire une variable locale). Elle renvoie 0 en cas de succès et -1 en cas d'échec.

Parmi les champs de la structure stat, on trouve un champ st_mode, de type mode_t, qui contient diverses informations à propos du fichier. Entre autres, on peut passer ce mode à un macro IS_DIR (lui aussi défini par POSIX), qui indique si le fichier est un répertoire.



Jean-Baptiste Yunes
1999-02-05