#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;

/***********************
    There is a bug in the way this program traverses directories.
    If you figure out what the bug is, please let me know.
    koxenrider@sol-biotech.com

    Thanks to Steffen Conrad for pointing out the error and supplying the fix!
***********************/

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);
                perror("\terror?");
            }
        }
        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

        strDir = sdir + (string)"/" + (string)dptr->d_name;
        int statRet = stat(strDir.c_str(), &st); //Thanks! to Steffen Conrad of Germany for pointing out this error and supplying the fix!
        if (statRet != -1 && S_ISDIR(st.st_mode)) {
            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: " + strDir;
        m_vectData.push_back(str);
    }
    closedir(dirp);
}

int main(){
    listDir(".", 0);
    for (int i=0; i<m_vectData.size(); i++){
        printf("%s\n", m_vectData[i].c_str());
    }
    return 0;
}


