#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Location
    Istanbul, TR
    Posts
    85
    Rep Power
    11

    recursion to find subdirs and files in subdirs


    i am writing a program that finds all files in a dir and stores them in myarr pointer array.. If it finds subdirs
    then stores them in subdir pointer array.. But when it finds sub-directories i want it to enter that sub-directories and
    get the files and subdirs again and add it in myarr and subdir pointer arrays.. I have to use recursion here but when i compile it
    it give Segmentation fault.. Below is the code i couldnt find where i am making wrong

    thanks in advanced for any help...

    s_i is sub-directory index (global variable) and f_i is file index (global variable)
    to know which element of pointer array i am working on..

    Code:
    void ** open_mydir(char sdir[]) {
    
        struct  dirent  *dptr;
        struct  stat st;
        char    *buff; 
        DIR     *dirp;
    
    
        if( (dirp = opendir(sdir)) == NULL ) {
             fprintf(stderr,"Error opening %s ",buff);
             exit(1);
        }
    
            while(dptr = readdir(dirp)) {
    
    		/*skip if find . and .. */
                    if ((strcmp(dptr->d_name, ".") == 0 ||  strcmp(dptr->d_name, "..") == 0)) {
                            continue;
                    }
    
    		/* if find sub-directory store it in subdir pointer array */
                    if (stat (dptr->d_name, &st) != -1  && S_ISDIR (st.st_mode)) {
    
    			/* allocate memory for given path + filename_found_in_DIR */
                            if (NULL == (subdir[s_i] = (char *) malloc(strlen(dptr->d_name) + strlen(sdir) + 2))) {
                                     fprintf(stderr, "Unable to allocate memory.\n");
                                    exit(1);
                            }
                    /*join given path and file name (/home/jazzy/cfiles + subdirname_found_in_DIR) */
                    sprintf(subdir[s_i],"%s%c%s",strdup(sdir),'/',strdup(dptr->d_name));
                    s_i++;
                    continue;
                    }
                    
                    /* if it is a file than store it in myarr pointer array */
                    if (NULL == (myarr[f_i] = (char *) malloc(strlen(dptr->d_name) + strlen(sdir) + 2))) {
                            fprintf(stderr, "Unable to allocate memory.\n");
                            exit(1);
                    }
                    /*join given path and file name (/home/jazzy/cfiles + filename_found_in_DIR) */
                    sprintf(myarr[f_i],"%s%c%s",strdup(sdir),'/',strdup(dptr->d_name));
                    f_i++;
            }
    
    	/* here gives SEGMENTATION FAULT */
    	while(*subdir != 0) {
    		/* send sub-directories to open_mydir func again to add files and subdirs in it*/
    	         open_mydir(*subdir); 
    	         *subdir++;
    	        }
    
            closedir(dirp);
    }
    
    aliitle part of my main program is
    
    char **myarr;
    char **subdir;
    static int f_i=0,s_i=0;
    
    int main(int argc, char * argv[]) {
    
            int i;
    
            if (argc != 4 ) {
                    printf("Usage: %s Source_Path date Destination_Path\n",argv[0]);
                    printf("Ex   : %s /home/jazzy/cfiles 20030801 /home/jazzy/deploy\n",argv[0]);
                    exit(1);
            }
    	/*i allocate memory for myarr pointer array here in main function*/
            if (NULL == (myarr = (char **) malloc(100 * sizeof(char **)))) {
                    fprintf(stderr, "Unable to allocate memory.\n");
                    exit(1);
            }
            /*i allocate memory for subdir pointer array here in main function */
            if (NULL == (subdir = (char **) malloc(100 * sizeof(char **)))) {
                    fprintf(stderr, "Unable to allocate memory.\n");
                    exit(1);
            }
    
            open_mydir(argv[1]); 
            /*this  call works great here if i comment the lines where i  make recursion in open_mydir function*/  
    
    
    ............. and the code goes on and on....
  2. #2
  3. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243

    Why not allow C++ to manage memory?


    Here is a version I wrote in C++. I let the vector class manage memory for me, half of the code is error handling.

    Code:
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <errno.h>
    #include <stdio.h>
    
    #include <string>
    #include <vector>
    
    using namespace std;
    
    vector < string > m_vectData;
    
    void listDir(const char * sdir, int count){
        string str;
        struct  dirent  *dptr;
        struct  stat st;
        DIR     *dirp;
                     
        if( (dirp = opendir(sdir)) == NULL ) {
            fprintf(stderr,"Error opening %s:\n",sdir);
            switch(errno){
                case EACCES : {
                    fprintf(stderr,"\tSearch permission is denied for a component of the path name prefix of dirname or read permission is denied for the directory.\n");
                    break;
                }
                case ENAMETOOLONG : {
                    fprintf(stderr,"\tThe length of the dirname parameter exceeds PATH_MAX or a path name component is longer than NAME_MAX.\n");
                    break;
                }
                case ENOENT : {
                    fprintf(stderr,"\tThe named directory does not exist or dirname points to an empty string or a component of dirname is not a directory.\n");
                    break;
                }
                case ENOTDIR : {
                    fprintf(stderr,"\tThe argument dirname does not refer to a directory.\n");
                    break;
                }
                case ENOMEM : {
                    fprintf(stderr,"\tNot enough memory to create the directory stream.\n");
                    break;
                }
                default : {
                    fprintf(stderr, "\tUnknown value for errno: %d\n", errno);
                }
            }
            return;
        }
        while(dptr = readdir(dirp)) {
    
            //skip if find . and ..
            if ((strcmp(dptr->d_name, ".") == 0 ||  strcmp(dptr->d_name, "..") == 0)) {
                continue;
            }
    
            str = "";
            for (int i=0; i<count; i++)
                str += " ";//indentation for better viewing
    
            if (stat (dptr->d_name, &st) != -1  && S_ISDIR (st.st_mode)) {
                //join given path and file name
                str += "D: " + (string) sdir + (string) "/" + (string) dptr->d_name;
                m_vectData.push_back(str);
                listDir(str.c_str(), count + 1);
                continue;
            }
                    
            //join given path and file name
            str += "F: " + (string) sdir + (string) "/" + (string) dptr->d_name;
            m_vectData.push_back(str);
        }
    }
    
    int main(){
        listDir(".", 0);
        for (int i=0; i<m_vectData.size(); i++){
            printf("%s\n", m_vectData[i].c_str());
        }
        return 0;
    }

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Location
    Istanbul, TR
    Posts
    85
    Rep Power
    11
    it is good to use vector class.. thanks for help..But
    your code also dont enter in the subdirs and get the files in subdirs and if it finds subdir in a subdir it doesnt show it.. I mean it only shows the first subdirectory..

    i want to enter subdirectories recursivley and get the files in all subdirectories...

    And one more interesting thing is when i send

    listDir("/home", 0); it returns

    F: /home/jazzy
    F: /home/ppp0
    F: /home/www
    ;;;

    it says the the jazzy ppp0 and www are files not directory.. i

    or
    listDir("/usr", 0); it returns

    F: /usr/bin
    F: /usr/lib
    F: /usr/libexec
    F: /usr/sbin
    F: /usr/share
    F: /usr/X11R6
    F: /usr/dict
    F: /usr/etc
    F: /usr/games

    dont understand this.. a little confused..

    thanks in advanced for any help...
  6. #4
  7. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    I appologize, I sent one version before the last (it had a bug in it, stupid, but a bit devious). Here is the correct version:

    Code:
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <dirent.h>
    #include <errno.h>
    #include <stdio.h>
    
    #include <string>
    #include <vector>
    
    using namespace std;
    
    vector < string > m_vectData;
    
    void listDir(const char * sdir, int count){
        string str, strDir;
        struct  dirent  *dptr;
        struct  stat st;
        DIR     *dirp;
                     
        if( (dirp = opendir(sdir)) == NULL ) {
            fprintf(stderr,"Error opening %s:\n",sdir);
            switch(errno){
                case EACCES : {
                    fprintf(stderr,"\tSearch permission is denied for a component of the path name prefix of dirname or read permission is denied for the directory.\n");
                    break;
                }
                case ENAMETOOLONG : {
                    fprintf(stderr,"\tThe length of the dirname parameter exceeds PATH_MAX or a path name component is longer than NAME_MAX.\n");
                    break;
                }
                case ENOENT : {
                    fprintf(stderr,"\tThe named directory does not exist or dirname points to an empty string or a component of dirname is not a directory.\n");
                    break;
                }
                case ENOTDIR : {
                    fprintf(stderr,"\tThe argument dirname does not refer to a directory.\n");
                    break;
                }
                case ENOMEM : {
                    fprintf(stderr,"\tNot enough memory to create the directory stream.\n");
                    break;
                }
                default : {
                    fprintf(stderr, "\tUnknown value for errno: %d\n", errno);
                }
            }
            return;
        }
        while(dptr = readdir(dirp)) {
    
            //skip if find . and ..
            if ((strcmp(dptr->d_name, ".") == 0 ||  strcmp(dptr->d_name, "..") == 0)) {
                continue;
            }
    
            str = "";
            for (int i=0; i<count; i++)
                str += "  ";//indentation for better viewing
    
            if (stat (dptr->d_name, &st) != -1  && S_ISDIR (st.st_mode)) {
                //join given path and file name
                strDir = sdir + (string) "/" + (string) dptr->d_name;
                str += "D: " + strDir;
                m_vectData.push_back(str);
    
                //here is the recursion
                listDir(strDir.c_str(), count + 1);
                continue;
            }
                    
            //join given path and file name
            str += "F: " + (string) sdir + (string) "/" + (string) dptr->d_name;
            m_vectData.push_back(str);
        }
    }
    
    int main(){
        listDir(".", 0);
        for (int i=0; i<m_vectData.size(); i++){
            printf("%s\n", m_vectData[i].c_str());
        }
        return 0;
    }

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  8. #5
  9. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Location
    Istanbul, TR
    Posts
    85
    Rep Power
    11
    thank you very much for the quick reply..
    Now it enters a subdir in a subdir.. But it acceses only the second subdir.. if a subdir exists in the second subdir it only shows the subdir name not the contents of 2th subdir...

    //// my main dir
    F: ./test
    F: ./mytime.c
    F: ./sta
    F: ./install.sh
    F: ./mystat
    D: ./XXX // first subdirectory
    F: ./XXX/YYY //YYY is a subdir in XXX and in it there are files but program dont show them.. ..Our program acceses to the 1th subdirectory only and second subdir's name not its contents..
    F: ./XXX/deneme
    F: ./myc
    F: ./test.c
    F: ./mytime
    D: ./scripts
    F: ./scripts/jdrules
    F: ./scripts/jbackupdb
    F: ./scripts/jrget
    F: ./scripts/cvsget
    F: ./scripts/deploy.pl
    F: ./scripts/jreboot
    F: ./scripts/jbackupq
    F: ./scripts/TXTX // here also TXTX is a subdir too but program doesnt show its contents
    F: ./passwd
    F: ./bakkk
    F: ./elmarr.c.save
    F: ./ss.c
    F: ./plu
    F: ./plu.cpp

    But again thank you very much for your help and for your time.. i dont want to take your time for this problem.. I will study more the recursive functions and try to find the problem..
  10. #6
  11. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    It runs fine on FreeBSD 4.4...

    Code:
    sol-biotech% ./a.out 
    D: ./CryptPassword
      F: ./CryptPassword/index.html
      F: ./CryptPassword/procChangePassword.sql
      F: ./CryptPassword/procCryptPassword.sql
      F: ./CryptPassword/procUserAuthorized.sql
    F: ./index.html
    D: ./wipeIt
      F: ./wipeIt/wipeIt.c
    F: ./DirectoryListing.cpp
    F: ./a.out
    I put an exact copy of what produced this listing on my web site:

    http://sol-biotech.com/code/DirectoryListing.cpp

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  12. #7
  13. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    4
    Rep Power
    0

    dirent.h file


    I have VC++ 5 and I do not have this file...how do I obtain this file?
  14. #8
  15. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    This is a *nix program and won't run on Windows.

    Try this one: http://sol-biotech.com/code/WinDirectoryListing.cpp

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw
  16. #9
  17. No Profile Picture
    Junior Member
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Posts
    4
    Rep Power
    0
    ty for your help :)
  18. #10
  19. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Aug 2003
    Location
    Istanbul, TR
    Posts
    85
    Rep Power
    11

    freebsd


    mitakeet,

    i install Freebsd 4.7 and i see that the program can only access the first subdir..
    In your bsd box it is also working to the fisrts subdirectory..Because you dont have subdirectories under CryptPassword and wipeIt. If a subdirectory was exist in one of these subdirectories (in CryptPassword or wipeIt) then you wont able to see the contents of subdirectories in subdirectories under
    CryptPassword and wipeIt

    For example;

    make a new dir in your CryptPassword directory calleled XXX and put a few files in it.. Then enter this CryptPassword/XXX and create a new subdirectory YYY in XXX and put a few files in YYY too..
    Then you will see the program will not show the contents of XXX and YYY..

    Code:
    sol-biotech% ./a.out 
    D: ./CryptPassword
      F: ./CryptPassword/index.html
      F: ./CryptPassword/procChangePassword.sql
      F: ./CryptPassword/procCryptPassword.sql
      F: ./CryptPassword/procUserAuthorized.sql
      F: ./XXX  // here comes newly added XXX but this is a subdir not regular files. The program cant show the contents in it..
    F: ./index.html
    D: ./wipeIt
      F: ./wipeIt/wipeIt.c
    F: ./DirectoryListing.cpp
    F: ./a.out
    Briefly the program makes recursion only for 1 subdir.. It doesnt access the second subdir.. can you make the above XXX YYY example and send the results for me?
  20. #11
  21. I'm Baaaaaaack!
    Devshed God 1st Plane (5500 - 5999 posts)

    Join Date
    Jul 2003
    Location
    Maryland
    Posts
    5,538
    Rep Power
    243
    I dunno what the problem is. Sometimes it goes down several levels, sometimes it doesn't. Sometimes it calls a directory a file, sometimes it calls a file a directory. I tried a couple of changes to the program and got different results, but they were still wrong. I spend most of my time on Windows so haven't put that to much use. If you figure out what the problem is, please let me know.

    My blog, The Fount of Useless Information http://sol-biotech.com/wordpress/
    Free code: http://sol-biotech.com/code/.
    Secure Programming: http://sol-biotech.com/code/SecProgFAQ.html.
    Performance Programming: http://sol-biotech.com/code/PerformanceProgramming.html.
    LinkedIn Profile: http://www.linkedin.com/in/keithoxenrider

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw

IMN logo majestic logo threadwatch logo seochat tools logo