Forum Programmation.c Récursivité qui ne marche pas avec "stat()"

Posté par  (site web personnel) .
Étiquettes : aucune
0
7
juil.
2006
Bonjour!

Je suis en train d'ecrire une fonction qui doit parcourir recursivement des repertoires, puis effectuer des manipulations sur les fichiers (en fait, une suppression).

J'ai le code suivant:


int list_files(char directory[2048]) {
DIR *d;
struct dirent *de;
struct stat sb;

char dir_path[2048];

d = opendir(directory);

while((de = readdir(d)) != NULL)
{
stat(de->d_name, &sb);
if(S_ISREG(sb.st_mode)) {
printf("%s - ISDIR=%d\n", de->d_name, S_ISDIR(sb.st_mode));
}

if(S_ISDIR(sb.st_mode) && (strcmp(de->d_name,".") !=0) && (strcmp(de->d_name,"..") !=0)) {
sprintf(dir_path,"%s/%s",directory,de->d_name);
list_files(dir_path);
printf("%s: done\n", dir_path);
}
}
closedir(d);
return(0);
}

int main(void)
{
list_files(".");
return 0;
}


Le probleme, c'est que lors de l'execution, j'ai l'erreure suivante:

./stat_test
Opening directory . in cwd=/home/mbavay/tmp/test
test - ISDIR=0
Opening directory ./test2 in cwd=/home/mbavay/tmp/test
Opening directory ./test2/file.txt in cwd=/home/mbavay/tmp/test
Segmentation fault (core dumped)

alors que "file.txt" dans "test2" est bien un fichier, il est vu par "stat" comme un repertoire...

Des idees?

Mathias
PS: certains proposent de faire un chdir(...) avant la recursion, suivit d'un chdir(...) pour revenir au repertoire initial, ca marche, mais ca me semble un peu gros que stat() ne soit pas capable de gerer correctement une bete situation comme cela...
PPS: et je ne veux pas utiliser lstat(), car je souhaite traiter les liens symboliques comme des simples fichiers
  • # Verifier les retours d'erreur

    Posté par  . Évalué à 3.

    Il faut deja que tu testes les retours d'erreur des fonctions opendir() et stat(). En effet, en cas d'erreur, ce qu'elles sont censées renvoyer ne sera pas initialisé.
    Tu vas donc te retrouver avec un pointeur NULL pour opendir() (d'où coredump), ou une structure aléatoire pour stat() (d'où récursion là où il faut pas.)

    Donc, rajoute par exemple ces includes
    #include <error.h>
    #include <errno.h>

    Et modifie ton code:

    d = opendir(directory);
    if (d == NULL){
    error(0, errno, "opendir %s", directory);
    return 1;
    }
    [...]



    while((de = readdir(d)) != NULL)
    {
    int s_err;
    s_err = stat(de->d_name, &sb);
    if (s_err){
    error(0, errno, "stat %s", de->d_name);
    continue;
    }
    [...]


    A ce moment là, en lançant ton test, tu verras mieux ce qu'il se passe, et il se terminera sans planter (et sans rien faire, aussi).

    L'erreur de base de stat() c'est : "no such file or directory"

    Alors apparemment, l'erreur c'est que tu appeles stat() avec comme paramètre le nom du fichier pris directement dans le résultat de readdir(), et c'est un nom local au répertoire, stat() va donc le chercher dans le repertoire courant (et non pas dans le sous-repertoire). Il faut que tu construises le chemin complet, au moins relatif (en collant "directory/" avant)
    • [^] # Re: Verifier les retours d'erreur

      Posté par  (site web personnel) . Évalué à 2.

      Effectivement... je passais a stat() un argument qui n'etait pas valide (le nom local d'un repertoire au lieu d'un chemin ne serait-ce que relatif)... Je viens de corriger cela (ie: construire un vrai chemin relatif pour l'argument de "stat"), et ca marche...

      Merci beaucoup!

      Mathias
      PS: et en plus, je m'en veux monstrueusement de m'etre fait avoir et de ne meme pas avoir eut l'idee de tester les retours d'erreur...
  • # Nom complet

    Posté par  (site web personnel) . Évalué à 2.

    Il faur que tu passe directory a stat et non pas de->d_name

    Sinon la version que tu donne ne correspond pas a celle qui a retourné ton erreur car il manque un print de "Opening directory"

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.