IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Recursibe Directory Listing (un ls -R en gros)


Sujet :

C

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 48
    Par défaut Recursibe Directory Listing (un ls -R en gros)
    Bonjour

    Mon but est d'ecrire un programme de listing qui list aussi les repertoire , les sous repertoire , les sous sous repertoire et ainsi de suite (un ls -R en gros).
    Mais j'ai un segfault lorsque le deuxieme repertoire est lister .

    Je trouve pas l'erreur et je vais devenir cingler

    Please help me :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <errno.h>
     
    char path[512];
    void listDirectory(DIR * directory ,  struct dirent *dir , char  chemin[512]);
    void savePath(char chemin[512]);
    void restaurPath(char chemin[512]);
     
    int main(int argc, char *argv[])
    {
        struct dirent *dir;
        DIR * directory;
        int i;
        char chemin[512];
        bzero(chemin,512);
        strcpy(chemin,"./");
        if(argc == 1)
        {
            printf("Listage du repertoire courant :\n");
            listDirectory(directory ,  dir , chemin);
        }
        else
        {
            for(i = 1;i < argc;i++)
            {
                if(!strcmp(argv[i],"-h"))
                {
                    printf("\n-h\t\tAfiche cette aide\n");
                    printf("%s rep\t\tListe les repertoire et les sous repertoire de rep\n",argv[0]);
                }
                else
                {
                    if (opendir(argv[i]))
                    {
                        strcpy(chemin , argv[i]);
                        listDirectory(directory ,  dir , chemin);
                    }
                    else
                    {
                        printf("L'argument est inconu ou le repertoire donner n'existe pas\n");
                    }
                }
            }
        }
        return 0;
    }
     
     
     
    void listDirectory(DIR * directory ,  struct dirent *dir , char chemin[512])
    {
        directory = opendir(chemin);
        while((dir = readdir(directory)))
        {
            bzero(chemin , strlen(chemin));
            if(!(!(strcmp(dir->d_name,".")) || !(strcmp(dir->d_name,".."))))
            {
                restaurPath(chemin);
     
                if(opendir(dir->d_name) != NULL)
                {
                    if(strcmp(chemin,dir->d_name) != 0)
                        strncat(chemin, dir->d_name, 512);
                    printf("(D)\t%s\n" , dir->d_name);
                    savePath(chemin);
                    listDirectory(directory, dir, chemin);
                }
                else
                {
                    printf("(F)\t%s/%s\n",chemin,dir->d_name);
                }
            }
        }
        closedir(directory);
    }
     
    void savePath(char chemin[512])
    {
        strcpy(path , chemin);
    }
     
    void restaurPath(char chemin[512])
    {
                strcpy(chemin , path);
    }

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Par défaut
    Moi j'aurais plutot opté pour la fonction POSIX nftw qui permet justement le parcours récursif de répertoires. Il n'en s'agit pas moins d'une fonction qui s'appelle récursivement en appelant une fonction dont tu passe le pointeur en argument pour faire une action que tu aura définie par toi meme... vois le man page: http://man.developpez.com/man3/ftw.3.php
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Un algo. possible : http://www.developpez.net/forums/vie...318745#2318745

    CSoldier : c'est vrai que la fonction ftw() peut aider mais ça ne résoud que partiellement le problème. Ca lui permettra de parcourir des répertoires, mais le jour où il devra parcourir un autre type d'arbre (ex. : le contenu de la base de registre sous Windows), il ne saura toujours pas le faire et attendra qu'on lui donne une fonction qui le fait pour lui.
    Mais bon...chacun sa vision des choses : avoir tout et tout de suite ou capitaliser ?

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 48
    Par défaut
    me suis debrouiller voila la source pour ceux que ca interesse :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    /*
    Recursive Directory Listing coded by FireMax
    mail : firemax666@gmail.com
    source modifiable et tous ce que vous voulez ;)
    Coder pour le concour 13 de securityhack.net
     
    Vous pouvez appeler le programme avec le repertoire que vous voulez lister 
    Par exemple :
    listeur /home/fire 
    Par default le programme listera le repertoire courant .
    */
     
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
     
    void listDirectory(char chemin[256]);
     
    int main(int argc, char *argv[])
    {
    	int i;
    	char chemin[256];
    	strncpy(chemin , "./",2);
    	if(argc == 1)
    	{
    		printf("Listage du repertoire courant :\n");
    		listDirectory(chemin);
    	}
    	else
    	{
    		for(i = 1;i < argc;i++)
    		{
    			if(!strcmp(argv[i],"-h"))
    			{
    				printf("\n-h\t\tAfiche cette aide\n");
    				printf("%s rep\t\tListe les repertoire et les sous repertoire de rep\n",argv[0]);
    			}
    			else
    			{
    				if (opendir(argv[i]))
    				{
    					strcat(chemin, argv[i]);
    					strcat(chemin,"/");
    					listDirectory(chemin);
    				}
    				else
    				{
    					printf("L'argument est inconu ou le repertoire donner n'existe pas\n");
    				}
    			}
    		}
    	}
    	return 0;
    }
     
    void listDirectory(char chemin[256])
    {
    	DIR * directory = opendir(chemin);
    	struct dirent * dir;
    	struct stat sta;
    	char temp[256];
    	bzero(temp,sizeof(temp));
     
    	while ((dir = readdir(directory)))
    	{
    		strcpy(temp,chemin);
    		if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, ".."))
    		{
    			strncpy(temp, chemin,strlen(chemin));
    			strcat(temp, dir->d_name);
     
    			if ((stat(temp, &sta) != -1) && (S_ISDIR(sta.st_mode)))
    			{
    				strcat(temp , "/");
    				printf("\n(D)\t%s\n", temp);
    				listDirectory(temp);
    			}
    			else
    			{
    				printf("(F)\t%s\n", temp);
    			}
    		}
    		strncpy(temp,chemin,strlen(chemin));
    	}
    	closedir(directory);
    	printf("\n");
    }

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Septembre 2005
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2005
    Messages : 7
    Par défaut
    Salut,

    Firemax: Jolie comme code, parcontre un :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
      memset(chemin,0,sizeof(chemin));
    devant strncpy(chemin , "./",2);
    Sinon sa segfault mechant

  6. #6
    Membre émérite

    Profil pro
    Inscrit en
    Août 2003
    Messages
    878
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2003
    Messages : 878
    Par défaut
    Mais non...pas de memset à mettre...
    Il peut remplacer le "2" par un "3" ou, mieux, utiliser strcpy() (je ne vois vraiment pas l'utilité de strncpy() ici [1]).

    D'ailleurs, le "bzero(temp,sizeof(temp));" (dans listDirectory()) pourrait être remplacé par un "temp[0]='\0';". Que les autres caractères soient à 0 ou pas, on s'en fiche un peu...

    Concernant le "strncpy(temp, chemin,strlen(chemin));"...à quoi sert-il ? Il y a déjà un "strcpy(temp,chemin);" en début de boucle, non ? Et pourquoi en mettre un deuxième juste avant la fin de la boucle ?
    Et puis, en général, le troisième paramètre de strncpy() est la longueur maximale à écrire à l'emplacement pointé par le premier paramètre, pas la longueur de la chaîne pointée par le deuxième... Le jour où tu fais ça avec "strlen(chemin)>sizeof(temp)" : dépassement de buffer.

    Pourquoi faire le test de "." et ".." dans tous les cas ? Est-ce utile de le faire aussi pour les fichiers réguliers (et tout ce qui n'est pas un répertoire) ?

    Aussi, plutôt que de dimensionner les buffers en spécifiant "256", il serait plus joli, plus lisible et plus portable d'utiliser une constante (MAXPATHLEN dans <sys/param.h> si ma mémoire est bonne).

    Bon, je m'arrête là [2] : sinon, c'est bien .

    PS : évite de mettre ton adresse mail telle quelle sur un site public (à moins que tu aimes le spam).

    [1] : et surtout, ne me dites pas "passkeu c'est plus sécurisé"...
    [2] : oui, il y avait (d')autre(s) chose(s)

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Avril 2005
    Messages
    48
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2005
    Messages : 48
    Par défaut
    Ok je vais modifier deux trois truc alors

    Pour les puriste ^^*

    J'ai quand meme laisser les strcpy mais j'ai modifier car les miens servait a rien ^^

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    /*
    Recursive Directory Listing coded by FireMax
    mail : firemax666@gmail.com
    source modifiable et tous ce que vous voulez ;)
    Coder pour le concour 13 de securityhack.net
     
    Vous pouvez appeler le programme avec le repertoire que vous voulez lister 
    Par exemple :
    listeur /home/fire 
    Par default le programme listera le repertoire courant .
    */
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <dirent.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <unistd.h>
     
    #define MAX_PATH 512
     
    void listDirectory(char chemin[MAX_PATH]);
     
    int main(int argc, char *argv[])
    {
    	int i;
    	char chemin[MAX_PATH];
    	bzero(chemin,MAX_PATH);
    	strncpy(chemin , "./",2);
    	if(argc == 1)
    	{
    		printf("Listage du repertoire courant :\n");
    		listDirectory(chemin);
    	}
    	else
    	{
    		for(i = 1;i < argc;i++)
    		{
    			if(!strcmp(argv[i],"-h"))
    			{
    				printf("\n-h\t\tAfiche cette aide\n");
    				printf("%s rep\t\tListe les repertoire et les sous repertoire de rep\n",argv[0]);
    			}
    			else
    			{
    				if (opendir(argv[i]))
    				{
    					strncat(chemin, argv[i],(MAX_PATH-strlen(chemin)));
    					strncat(chemin,"/",1);
    					listDirectory(chemin);
    				}
    				else
    				{
    					printf("L'argument est inconu ou le repertoire donner n'existe pas\n");
    				}
    			}
    		}
    	}
    	return 0;
    }
     
    void listDirectory(char chemin[MAX_PATH])
    {
    	DIR * directory = opendir(chemin);
    	struct dirent * dir;
    	struct stat sta;
    	char temp[MAX_PATH];
    	bzero(temp,MAX_PATH);
     
    	while ((dir = readdir(directory)))
    	{
    		strcpy(temp,chemin);
    		if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, ".."))
    		{
    			strncpy(temp, chemin,MAX_PATH);
    			strncat(temp, dir->d_name, (MAX_PATH-strlen(temp)));
     
    			if ((stat(temp, &sta) != -1) && (S_ISDIR(sta.st_mode)))
    			{
    				strncat(temp , "/", 1);
    				printf("\n(D)\t%s\n", temp);
    				listDirectory(temp);
    			}
    			else
    			{
    				printf("(F)\t%s\n", temp);
    			}
    		}
    		strncpy(temp,chemin,(MAX_PATH-strlen(temp)));
    	}
    	closedir(directory);
    	printf("\n");
    }

  8. #8
    Membre confirmé
    Profil pro
    Conseil - Consultant en systèmes d'information
    Inscrit en
    Juillet 2004
    Messages
    89
    Détails du profil
    Informations personnelles :
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Conseil - Consultant en systèmes d'information

    Informations forums :
    Inscription : Juillet 2004
    Messages : 89
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void listDirectory(char chemin[MAX_PATH]);
    Un tableau de 512octets passé à une fonction, n'est-ce pas un cas ou un pointeur serait de mise?

  9. #9
    Expert éminent
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 392
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 392
    Par défaut
    c'est de toute façon un pointeur qui sera passé.

    le MAX_PATH dans l'entete de la fonction n'a aucun effet, si ce n'est pour certains compilateurs qui peuvent signaler un indice explicite hors tableau...
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  10. #10
    Expert éminent
    Avatar de Emmanuel Delahaye
    Profil pro
    Retraité
    Inscrit en
    Décembre 2003
    Messages
    14 512
    Détails du profil
    Informations personnelles :
    Âge : 68
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2003
    Messages : 14 512
    Par défaut
    Citation Envoyé par NecroMagik
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    void listDirectory(char chemin[MAX_PATH]);
    Un tableau de 512octets passé à une fonction, n'est-ce pas un cas ou un pointeur serait de mise?
    misconception

    http://emmanuel-delahaye.developpez.....htm#param_tab

Discussions similaires

  1. Réponses: 0
    Dernier message: 22/03/2012, 16h37
  2. Réponses: 1
    Dernier message: 29/09/2008, 16h21
  3. Réponses: 3
    Dernier message: 06/11/2007, 09h29
  4. [AJAX] Restaurer l'état de listes liées par Ajax
    Par vallica dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 27/10/2006, 13h36
  5. list : no such file or directory :(
    Par Bakura dans le forum C++
    Réponses: 23
    Dernier message: 13/06/2006, 16h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo