Tristan Crolard - François Pottier
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.
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.
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:
:
et d'un passage à la ligne.
Liste
. Si Liste
signale un échec, la fonction s'arrêtera là.
.
et ..
). Si
l'élément en question est lui-même un répertoire, alors on construira son nom complet (formé du nom de son
père, d'un caractère /
, puis de son nom propre), et on effectuera un appel récursif pour afficher
le contenu de ce sous-répertoire.
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.