Fontion récursive =>Segmentation fault

Fontion récursive =>Segmentation fault - C - Programmation

Marsh Posté le 16-03-2006 à 19:23:00    

Bonjour, j'ai absolument besoin de votre aide !!
 
Lorque j'utilise ma fonction avec pour option -R pour afficher le contenu du dossier, et si celui-ci en contient d’autre, cette option affiche aussi leurs contenu (d'où la récursivité).
 
1er problème : elle affiche les fichiers ou dossiers en DOUBLE.
2ème prblème : elle retourne "segmentation fault". La fontion ne fait pas la récursivité.
 
Pourquoi ?
 
Voici le code :
 
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
 
typedef struct options_s{
  int recursive, longdisplay, numeric, all, displaydirnames ;
} options_t ;
options_t _options = { 0, 0, 0, 0, 0 } ;
 
/* renvoie la dernière composante d'un chemin
   (ce qui suit le dernier slash, s'il y en a un) */
char * afterslash (const char * name) {
  char * path = strrchr (name, '/') ;
 
  if (path == name) return path ;
  if (!path)        return strchr(name, name[0]) ;
  else              return path + 1 ;
}
 
/* une fonction qui indique si le nom commence par un point */
int allbutdotfiles (const struct dirent* d) {
  char* realname = afterslash(d->d_name) ;
  return realname[0]!='.' ;
}
 
/* une fonction qui indique si le nom est . ou .. */
int allbutdotand2dots (const struct dirent* d) {
  char* realname = afterslash(d->d_name) ;
 
  if (realname[0]!='.')    return 1 ;
  if (realname[1]=='\0')   return 0 ;
  if (realname[1]!='.')    return 1 ;
  if (realname[2]=='\0')   return 0 ;
  return 1 ;
}
 
/* affichage d'un fichier */
void printfile (char * name, options_t * options) {
  struct stat s;
  char access_chars [] = "rwxrwxrwx";
  int  access_masks [] = { 0400, 0200, 0100, 040, 020, 010, 4, 2, 1 };
  char type_chars   [] = "-dbcl";
  int  type_masks   [] = { S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK };
  struct passwd * p;
  struct group  * g;
  int i ;
  char date[12] ;
 
/* (avec option "-l" ) */
  if ( ! options->longdisplay )
    puts(afterslash(name));
  else {
    if ( lstat(name,&s) == -1) {
      perror("lstat" );
      exit(-1);
    }
 
    for (i=0; i<strlen(type_chars); i++)
      if (s.st_mode & type_masks[i]) {
    putchar(type_chars[i]);
    break;
      }
   
    if (i==strlen(type_chars))      putchar('?');
 
    for (i=0; i<strlen(access_chars); i++) {
      if (s.st_mode & access_masks[i]) putchar(access_chars[i]) ;
      else putchar('-') ;
    }
 
    printf (" %4d ", s.st_nlink) ;
 
    if (options->numeric)
      printf("%-8d %-8d ",s.st_uid,s.st_gid) ;
    else {
      p = getpwuid (s.st_uid) ;
      g = getgrgid (s.st_gid) ;
 
      if (p)    printf ("%-8s ",p->pw_name);
      else    printf ("%-8d ",s.st_uid);
 
      if (g)    printf ("%-8s ",g->gr_name);
      else    printf ("%-8d ",s.st_gid);
    }
    printf ("%8d ", s.st_size) ;
 
    strftime (date,13,"%b %d %H:%M",gmtime(&s.st_mtime)) ;
    printf ("%12s ",date) ;
  }
  name = afterslash (name) ;
  puts(name) ;
}
 
/* affichage d'un fichier ou répertoire.
   pour un fichier, on l'affiche simplement.
   pour un répertoire, on fait une descente récursive
   (si l'option -R est spécifiée) */
void printdirectory (char* name, options_t* options){
  struct stat s;
  struct dirent ** files;
  int n, i;
  char * fullname;
 
  /* d'abord, si "name" ne correspond pas à un répertoire,
     on l'affiche directement */
  if ( stat(name,&s) == -1 ) {
    perror("stat" );
    exit(-1);
  }
 
  if (!S_ISDIR(s.st_mode))
    printfile (name,options) ;
  /* sinon, c'est un répertoire, donc on va le parcourir */
  else {
    /* est-ce qu'on affiche tout (sauf . et ..), ou bien
       est-ce qu'on cache les fichiers commençant par un point ? */
    int(*selectfun)(const struct dirent*) =
      options->all ? allbutdotand2dots : allbutdotfiles ;
 
    n = scandir (name, &files, selectfun, alphasort) ;
 
    if (n == -1) {
      perror("scandir" );
      exit(-1);
    }
 
    if (options->displaydirnames || options->recursive)
      printf("%s:\n",afterslash(name));
 
    for (i=0; i<n; i++) {
      fullname = (char *)malloc(strlen(name)+1+strlen(files[i]->d_name)+1);
      if ( fullname == NULL ) {
    perror("malloc" );
    exit(-1);
      }
 
      sprintf (fullname, "%s/%s", name, files[i]->d_name) ;
      printfile (fullname,options) ;
      free(fullname);
    }
    free(files);
 
    /* maintenant, on fait l'éventuelle descente récursive */
    if (options->recursive) {
      for (i=0; i<n; i++) {
    fullname = (char *)malloc(strlen(name)+1+strlen(files[i]->d_name)+1);
    if ( fullname == NULL ) {
      perror("malloc" );
      exit(-1);
    }
 
    sprintf (fullname, "%s/%s", name, files[i]->d_name) ;
    if ( stat(fullname,&s) == -1 ) {
      perror("stat" );
      exit(-1);
    }
 
    if (S_ISDIR(s.st_mode)) {
      puts("" ); /* pour séparer l'affichage des répertoires */
      printdirectory (fullname, options) ;
    }
    free(fullname);
      }
      free(files);
    }
  }
}
 
 
int main (int c, char**v) {
  options_t options = _options ;
  int option ;
  int i;
 
  while (-1!=(option=getopt(c,v,"Rlna" )))
    switch (option) {
    case 'R': options.recursive = 1;    break;
    case 'l': options.longdisplay = 1;    break;
    case 'n': options.numeric = 1;        break;
    case 'a': options.all = 1;          break;
    }
 
  if (c == optind)
    printdirectory(".",&options);
  else {
    if (optind < c-1)
      options.displaydirnames++ ;
 
    for (i=optind; i<c; i++) {
      printdirectory(v[i],&options) ;
 
      if (i+1!=c)
    puts("" ); /* pour séparer les différents répertoires */
    }
  }
  return 0;
}

Reply

Marsh Posté le 16-03-2006 à 19:23:00   

Reply

Marsh Posté le 16-03-2006 à 21:34:44    

Quel est l'intérêt de ceci :
 
   for (i=0; i<n; i++) {  
      fullname = (char *)malloc(strlen(name)+1+strlen(files[i]->d_name)+1);  
      if ( fullname == NULL ) {  
    perror("malloc" );  
    exit(-1);  
      }  
 
 
 Tu fais une boucle d'allocation mémoire, tu conserves simplement la dernière et tu as une belle fuite mémoire pour les premières !!

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed