Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

wvdiriter.cc

Go to the documentation of this file.
00001 /*
00002  * Worldvisions Weaver Software:
00003  *   Copyright (C) 1997-2002 Net Integration Technologies, Inc.
00004  *
00005  * Directory iterator.  Recursively uses opendir and readdir, so you don't
00006  * have to.  Basically implements 'find'.
00007  *
00008  */
00009 
00010 #include "wvdiriter.h"
00011 
00012 #ifdef _WIN32
00013 #define S_ISDIR(x) (_S_IFDIR | (x))
00014 #define lstat stat
00015 #endif
00016 
00017 WvDirIter::WvDirIter( WvStringParm dirname,
00018                       bool _recurse, bool _skip_mounts, size_t sizeof_stat )
00019     : relpath(""), dir(dirs)
00020 /****************************************************************************/
00021 {
00022     // if this assertion fails, then you probably used different compiler
00023     // options for the wvstreams library and the calling program.  Check
00024     // for defines like _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE.
00025     assert(sizeof_stat == sizeof(struct stat));
00026     
00027     recurse = _recurse;
00028     go_up   = false;
00029     skip_mounts = _skip_mounts;
00030     found_top = false;
00031 
00032     DIR * d = opendir( dirname );
00033     if( d ) {
00034         Dir * dd = new Dir( d, dirname );
00035         dirs.prepend( dd, true );
00036     }
00037 }
00038 
00039 WvDirIter::~WvDirIter()
00040 /*********************/
00041 {
00042     dirs.zap();
00043 }
00044 
00045 bool WvDirIter::isok() const
00046 /**************************/
00047 {
00048     return( dirs.count() > 0 );
00049 }
00050 
00051 bool WvDirIter::isdir() const
00052 /***************************/
00053 {
00054     return( S_ISDIR( info.st_mode ) );
00055 }
00056 
00057 void WvDirIter::rewind()
00058 /**********************/
00059 {
00060     // have to closedir() everything that isn't the one we started with,
00061     // and rewind that.
00062     while( dirs.count() > 1 ) {
00063         dir.rewind();
00064         dir.next();
00065         dir.unlink();
00066     }
00067 
00068     if( isok() ) {
00069         dir.rewind();
00070         dir.next();
00071         rewinddir( dir->d );
00072     }
00073 }
00074 
00075 
00076 bool WvDirIter::next()
00077 /********************/
00078 // use readdir... and if that returns a directory, opendir() it and prepend
00079 // it to dirs, so we start reading it until it's done.
00080 {
00081     struct dirent * dent = NULL;
00082 
00083     if( !isok() )
00084         return( false );
00085 
00086     bool tryagain;
00087     do {
00088         bool ok = false;
00089         tryagain = false;
00090 
00091         // unrecurse if the user wants to
00092         if( go_up ) {
00093             go_up = false;
00094             if( dirs.count() > 1 ) {
00095                 dir.unlink();
00096                 dir.rewind();
00097                 dir.next();
00098             } else
00099                 return( false );
00100         }
00101 
00102         do {
00103             dent = readdir( dir->d );
00104             if( dent ) {
00105                 info.fullname = WvString( "%s/%s", dir->dirname, dent->d_name );
00106                 info.name = dent->d_name;
00107 
00108                 if (relpath == "")
00109                     info.relname = info.name;
00110                 else
00111                     info.relname = WvString("%s%s", relpath, info.name);
00112 
00113                 ok = ( lstat( info.fullname, &info ) == 0
00114                             && strcmp( dent->d_name, "." )
00115                             && strcmp( dent->d_name, ".." ) );
00116 
00117                 if (ok && !found_top)
00118                 {
00119                     lstat(info.fullname, &topdir);
00120                     topdir.fullname = info.fullname;
00121                     topdir.name = info.name;
00122                     topdir.relname = info.relname;
00123                     found_top = true;
00124                 }
00125             }
00126         } while( dent && !ok );
00127 
00128         if( dent ) {
00129             // recurse?
00130             if( recurse && S_ISDIR( info.st_mode ) &&
00131                     ( !skip_mounts || info.st_dev == topdir.st_dev) ) {
00132                 DIR * d = opendir( info.fullname );
00133                 if( d ) {
00134                     relpath = WvString( "%s%s/", relpath, info.name );
00135                     Dir * dd = new Dir( d, info.fullname );
00136                     dirs.prepend( dd, true );
00137                     dir.rewind();
00138                     dir.next();
00139                 }
00140             }
00141         } else {
00142             // end of directory.  if we recursed, unlink it and go up a 
00143             // notch.  if this is the top level, DON'T close it, so that
00144             // the user can ::rewind() again if he wants.
00145             if( dirs.count() > 1 ) {
00146                 if (dirs.count() == 2)
00147                     relpath = WvString("");
00148                 else
00149                     relpath = WvString( "%s/", getdirname(relpath) );
00150 
00151                 dir.unlink();
00152                 dir.rewind();
00153                 dir.next();
00154                 tryagain = true;
00155             }
00156         }
00157 
00158     } while( tryagain );
00159 
00160     return( dent != NULL );
00161 }
00162 

Generated on Wed Dec 15 15:08:11 2004 for WvStreams by  doxygen 1.3.9.1