[C]fonction recursive pour supprimer un dossier - [resolu]

hello à tous,

voila je dois creer une fonction recursive afin de pouvoir supprimer un dossier meme si ce dernier n’est pas vide.

je dois utiliser uniquement rmdir, chdir, unlink, stat, opendir, readdir, scandir

je elaborer une source mais ca marche po :


void scann_dossier(char* g_dossier_a_scann,char* g_tableau_nom_donnee_scann[100], char* g_tableau_type_donnee_scann[100],char** g_message_erreur, struct stat *buf2)
{

  struct dirent **namelist;
  int n,cnt=0;
  int x=0;

  n=scandir(g_dossier_a_scann, &namelist, 0 , alphasort);
  if (n<0)
    {
      printf("%s\n",strerror(errno));
      printf("%d\n",errno);
      traiter_erreur(errno,g_message_erreur); 
    }
  else
    {
      errno=0;
      traiter_erreur(errno,g_message_erreur);
      while(cnt<n)
	{
   g_tableau_nom_donnee_scann[cnt]=(namelist[cnt]->d_name);
   cnt++;
	}
      g_tableau_nom_donnee_scann[n]="fin";
    }
  while(g_tableau_nom_donnee_scann[x]!="fin")
    {
      stat(g_tableau_nom_donnee_scann[x],buf2);
      
      if(S_ISDIR(buf2->st_mode)) {g_tableau_type_donnee_scann[x]="Repertoire";}
      if(S_ISCHR(buf2->st_mode)) {g_tableau_type_donnee_scann[x]="Character Special File";}
      if(S_ISBLK(buf2->st_mode)) {g_tableau_type_donnee_scann[x]="Block Special File";}
      if(S_ISREG(buf2->st_mode)) {g_tableau_type_donnee_scann[x]="Fichier regulier";}
      if(S_ISFIFO(buf2->st_mode)){g_tableau_type_donnee_scann[x]="FIFO Special File";}
      if(S_ISLNK(buf2->st_mode)) {g_tableau_type_donnee_scann[x]="Lien Symbolique";}
      if(S_ISSOCK(buf2->st_mode)){g_tableau_type_donnee_scann[x]="Socket";}
      x++;
    }
}

void detruire_dossier(char c_nom_dossier_a_supp[4096])
{
  char** g_message_erreur;
  char* c_temp_nom[100];
  char* c_temp_type[100];
  char c_dossier_supp[1024];
  int x;
  int y;
  struct stat *temp=(struct stat *)malloc(sizeof(struct stat));

  chdir(c_nom_dossier_a_supp);
  scann_dossier(".", c_temp_nom , c_temp_type , g_message_erreur , temp);

  x=0;
  while(c_temp_nom[x]!="fin")
    {
      if(c_temp_type[x]=="Fichier regulier"){strcpy(c_dossier_supp,c_temp_nom[x]);unlink(c_dossier_supp);}
      x++;
    }

  y=0;
  while(c_temp_nom[y]!="fin")
    {
      if(c_temp_type[y]=="Repertoire")
	{
   strcpy(c_dossier_supp,c_temp_nom[y]);
   printf("%s\n",c_dossier_supp);
   chdir(c_dossier_supp);
	}
      y++;
    }
}

dslé le code est trié d’un ancienne version, il n’est donc pas totalement a joru dans ce que j’ai fait

vous avez une idée ??

merci

  1. tu peux corriger ton titre de sujet histoire qu’on sache de quoi il retourne? (je veux dire si tout le monde écrivait “aide pour un prog en C”, on s’y retrouverait pas)

  2. utilise la balise [!code] et [/code] (sans le ‘!’) pour encadrer ton code.

Sinon à priori, la suppression de dossier ça doit donner ça :

int rmdir_recursive(const char* directoryPath) {
  char buffer[1024];
  char* file = NULL;
  struct ??? dir = opendir(directoryPath);
  // gna gna gna gna (à corriger, je connais pas en C)
  // pour chaque fichier
  while (NULL != (file = readdir(dir))) {
    // si file n'est pas un chemin complet
    snprintf(buffer, 1024, "%s/%s", directoryPath, file);
    if (IS_DIR(file)) {
      rmdir_recursive(file); // on le rend suppressible
    }
    unlink(file); // on supprime
    free(file); // si nextdirentry renvoie un truc alloué.
  }
}

Etc. C’est normalement pas plus compliqué que ça.

merci bcp de ton aide, je vais tester ça.

Hé bien c’est simple : je suis coutumier d’opendir & readdir en PHP, mais pas en C :slight_smile: (j’ai certes fait du C, mais bref).

Donc à toi de corriger en fonction du man.

voial ce que j’ai fait :


int rmdir_recursive(const char* directoryPath) {

 DIR* dp;
 struct dirent *ep;
 char* buffer;
 struct stat *st;

dp = opendir(directoryPath);

if (dp != NULL){

 while ( ep = readdir(dp)) {
          buffer=ep->d_name;
          stat(buffer,st);
          if(!S_ISDIR(st->st_mode)) { unlink (buffer);}
          else {rmdir_recursive(buffer);}
}
}
rmdir(directoryPath);
}

mais ca marche tjrs pas, g une belle segmentaion fault.

je craque !!!!! ca fé 4 jours que chui dessus et je dois la finir pour mardi soir

ouais. Et t’apprendras à utiliser gdb et tu verras où est ton erreur hein. Car bon, c’est bien de se baser sur le code des autres, mais faut le faire jusqu’au bout : ta segfault est tout ce qu’il y a de plus normale.

C’est pas char* buffer mais char buffer[1024] : la différence est notable, dans un cas c’est un pointeur vers n’importe quoi, dans l’autre un tableau de char.

je sais que c’est tjrs mieu de se faire son propre code, mais le c’est une partie pour un gestionnaire de fichier (que je doit faire comme mivroprojet), ca fait 1 mois que je suis sur el projet et cette fonction est une des dernieres que je dois faire et ca fait 4 jours que je rame comme un ouf a essayer nombre de code qui fonctionne pas.
devant rendre mon projet mardi soir, je commence a flippe run peu.

voila, mais en tout cas merci pour ton aide

On ne flippe pas :slight_smile: on fait un coup de gdb & on relance le programme :slight_smile: résultats garantis.

Et encore une fois tu t’es gourré : buffer=ep->d_name;

Y a bien une bonne raison pour que j’ai mis :

snprintf(buffer, 1024, "%s/%s", directoryPath, file);

Là, dans ton cas tu positionnes buffer à ep->d_name, donc le dossier dans le contexte de lancement du programme…

Sinon sans chercher plus loin : stat(buffer, &st);

Je vois mal dans quoi tape la fonction stat si tu as struct stat *st.

Je connaissais pas gdb, j’ai lu un tuto, ça a l’air vraiment génial.
Donc merci Sans-Nom. :slight_smile:

hé bé…

gbd, valgrind, strace sont tes amies quand tu bosses en C (surtout strace pour le système).

yooo, ben grace a toi, g finalement reussi :

voila le code final et fonctionnel :


  DIR* dp;
  struct dirent *ep;
  char buffer[1024];
  struct stat st;
  char* temp;

  dp = opendir(directoryPath);
  
  if (dp != NULL)
    {
      while( (ep = readdir(dp) ) != NULL)
	{
   sprintf(buffer, "%s/%s", directoryPath,ep->d_name);
   lstat(buffer,&st);

   if(S_ISDIR(st.st_mode))
     {
       if(strcmp(".",(ep->d_name))==-1 && strcmp("..",(ep->d_name))==-1)
  {
    rmdir_recursive(buffer);
  }
     }

   else
     {
       unlink (buffer);
     }
   
	}
    }
  rmdir(directoryPath);
}




enfin, apres 6 jours d’effort !!!!

if(strcmp(".",(ep->d_name))==-1 && strcmp("…",(ep->d_name))==-1)

Marchera jamais. C’est :

if(strcmp(".", ep->d_name) != 0 && strcmp("…", ep->d_name) !=0)

ben aussi bizare que ca paraisse, en testan avec 0 ca marche pas, avec 1 ca marche.

le test est formel, j’ai essaye de supprimer 5-6 dossiers bien plein, et tous ont été supprimés .

lol, comem quoi l’info, on fait plein truc ca marche pas, et d’un coups ca marche, alors on fait juste un grand sourire idiot et on est content

Tu te rends compte de la remarque stupide que tu dis là ?

Bref. Non, strcmp(a, b) == vérifie que deux chaînes à zéro terminal sont égales. Renvoie 0 si a vaut b, -1 si a avant b, et 1 si a après b?.

Fait des affichages pour voir ce que tu supprimes réellement/ce que tu lis, mais je t’assure que tel quel ton algorithme est faux : tu supprimes tout les fichiers tels que ‘.’ et ‘…’ soient avant le nom du fichier.

Essaye en créant un dossier nommé “,a” car strcmp(’.’, ‘,a’) = 1, de même strcmp(’…’, ‘,a’) = 1. Donc :

if(strcmp(".",(ep->d_name))==-1 && strcmp("…",(ep->d_name))==-1)
->
if(strcmp(".",",a")==-1 && strcmp("…",",a")==-1)
->
if(1==-1 && 1==-1)
->
if(false && false)
->
if (false)
->
rien.

ben ecoute, comme je l’ai dit plus haut avec if(strcmp(".",(ep->d_name))==-1 && strcmp("…",(ep->d_name))==-1) sur fedora, ca fonctionne, quelque soit les noms des fichiers ou dossiers, le dossier en argument de la fonction est supprimé.

Par contre, des que je suis passer sur le linux de mon iut (slackware) la ca marche pu et c’est effectivement !=0 qui faut mettre.

bref ca marche, c le principal.

encore merci de ton aide