views:

783

answers:

5

I'm looking to write a portable filesystem scanner, capable of listing all files on a given directory path recursively.

To do this, I'm attempting to use cygwin for my compiler, making use of dirent.h and using the template:

#include <dirent.h> 
#include <stdio.h> 

int main(void)
{
  DIR           *d;
  struct dirent *dir;
  d = opendir(".");
  if (d)
  {
    while ((dir = readdir(d)) != NULL)
    {
      // Stuff
    }    
    closedir(d);
  }    
  return(0);
}

But need to add recursive directory searching as well. To do this, my solution was to attempt to opendir() on the next file, and judge the error code to determine if it was successfully opened as a directory (which I would then recurse on) or if it was returned to be 'not a directory', which would then be listed as just a file.

I admit it feels very klugey, but I have been unable to find a better method that can retain some portability (not win32), even after hours of searching.

So my simplified solution (some psuedo for simplicity) is looking something like this:

int scan(string startdir)
{
  DIR           *d;
  struct dirent *dir;
  d = opendir(startdir.cstr());
  if (d)
  {
    while ((dir = readdir(d)) != NULL)
    {
      if( NOT '.' AND NOT '..')
      {
        if(temp = opendir(startdir + d) == NULL)
        {
           //FILE OR ERROR
        }else{
          //Opened successfully as a directory, so recurse
          scan(startdir + d->d_name + "\\");
        }
      }
    }
    closedir(d);
  }
  return(0);
}

This is just half rewritten psuedo code to keep it simple, but it seems to work (although I'm very open to suggestions on better ways to do this).

The major issue I'm having, however, is a particular link file 'c:\cygwin\dev\fd' which seems to be opening as a directory and recursively opening itself over and over infinitely.

The 'fd' file is 4KB, 106 bytes with no extension and is a shortcut that does not point anywhere in Windows.

This error seems to indicate that either this kludgey method is bugged, or there's a problem in the cygwin implementation that I'm compiling in.

As a short example:

Error Reading: c:\cygwin\dev\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\0 No such file or directory

Excluding that directory, the search seems to work well. But I'm not alright with hard coding an exclusion in to the scanner.

If anyone has any ideas, suggestions, solutions, or alternative methods to this problem, your input would be appreciated.

Thanks.

A: 

That is a virtual filesystem, maybe with symlinks. Cygwin supports symlinks, and you might have to factor that in.

Marco van de Voort
+1  A: 

If you can use boost, consider using boost::filesystem. The tutorials include a simple ls program that you can easily extend to work recursively. The library also includes methods to query the types of files, which probably can solve your specific problem.

Dani van der Meer
Although it is probably a great idea, I am hesistant to use any other libraries (even free ones) that require further discussion and approval from the higher ups. I will look into it further (as I've seen it mentioned elsewhere as well) and possibly make the pitch. Thanks for the feedback
KevenK
A: 

You do realise that cygwin has all the UNIX tools.

Find is very usefull.

Martin York
+1  A: 

The culprit seems to be that the fd file links into /proc/

I do not guarantee it to be true, but I am under the impression that this enables the scanner to recursively loop through its own directory structure.

My efforts with readlink() to address this issue were promising at first, but I'm finding that with deeper levels of scanning, it becomes unreliable and the errors can still occur.

I am now looking into other ways to achieve this functionality (ie boost::filesystem).

KevenK
A: 

The cygwin library has both ftw() and fts(), use one of those.