Fontion récursive =>Segmentation fault - C - Programmation
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 !!
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 dautre, 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;
}