0

i am trying to recursively open files using the functionality provided in dirent.h

My problem is: i could not make it to skip directories which failed to open. I want it to open the directories which it can and skip those which it can't and move to the next directory instead of exiting with failure. What should i do to fix this?

Here is a simple code i tried to use

int acessdirs(const char *path)
{
    struct dirent *entry;
    DIR *dp;
    char fpath[300];
    if(dp=opendir(path))
    {
        while((entry=readdir(dp)))
            do things here
    }
    else
    {
        std::cout<<"error opening directory";
        return 0;
    }
    return 1;
}

I used this same style on windows 7 and it works fine.But it crashed on windows xp and when i debugged it i found that it crashes while trying to open "system volume information". I really dont need to access this folder and i was hoping if there is any way to skip it.

Here is my real code:

It is a little bit long.

int listdir(const char *path) 
{
  struct dirent *entry;
  DIR *dp;

  if(dp = opendir(path))
  {
    struct stat buf ;

    while((entry = readdir(dp)))
    {
        std::string p(path);
        p += "\\";
        p += entry->d_name;
         char fpath[300];
        if(!stat(p.c_str(), &buf))
        {
            if(S_ISREG(buf.st_mode))
            {  
                sprintf(fpath,"%s\\%s",path,entry->d_name);
                stat(fpath, &buf);
                std::cout<<"\n Size of \t"<<fpath<<"\t"<<buf.st_size;
                fmd5=MDFile (fpath);        
            }//inner second if
            if(S_ISDIR(buf.st_mode) &&  
         // the following is to ensure we do not dive into directories "." and ".."
                      strcmp(entry->d_name, ".")  && strcmp(entry->d_name, "..") )
            {
                listdir(p.c_str());
            }
        }//inner first if
        else
            std::cout << "ERROR in stat\n";
    }//end while
    closedir(dp);
  }//first if
  else
  {
      std::cout << "ERROR in opendir\n";
      return 0;
  }
  return 1;   

 }//listdir()
  • `access` is spelled with two `c`. – hochl May 01 '12 at 00:01
  • How does this code even compile? You have a variable called `dip` and you refer to it as `dp`. Also, in the future, please indent your code so that it is comprehensible. – Celada May 01 '12 at 00:02
  • You pasted too little code for us to even understand where the problem is. Is `accessdirs` called in a loop? What does that loop do when `0` is returned? Where's the recursion exactly? Does the "do things here" call `accessdirs`? – David Schwartz May 01 '12 at 00:03
  • @Greg: You were probably right, why delete your answer? The function either calls itself recursively or is inside a loop in its caller. Most likely, when it returns `0`, that causes the loop to terminate without continuing to process other entries in that same directory. – David Schwartz May 01 '12 at 00:05
  • The program crashes probably because you don't check errors properly. The code we need to see is in `do things here` – David Heffernan May 01 '12 at 00:07
  • @user1366861 how is fpath declared? – Dave May 01 '12 at 02:46

1 Answers1

1

Your biggest problem seems to be here:

sprintf(fpath,"%s\\%s",path,entry->d_name);
stat(fpath, &buf);

Without seeing fpath's declatation, it's tough to tell for certain, but you're either

  • Overflowing fpath in the sprintf call, leading to undefined behavior. "System Volume Information" is a long name. You should really use snprintf.

  • Not checking the return value of the stat call. If it returns -1, I'n not sure what the contents of buf will be.

More importantly, if you can use POSIX stuff, the function ftw is standard, and should provide most of the functionality you're trying to implement here.

Dave
  • 10,964
  • 3
  • 32
  • 54