2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
5 * Directory iterator. Recursively uses opendir and readdir, so you don't
6 * have to. Basically implements 'find'.
10 #include "wvdiriter.h"
12 #if defined(_WIN32) && !defined(S_ISDIR)
13 #define S_ISDIR(x) (_S_IFDIR | (x))
19 WvDirIter::WvDirIter( WvStringParm _dirname
,
20 bool _recurse
, bool _skip_mounts
, size_t sizeof_stat
)
21 : relpath(""), dir(dirs
)
22 /****************************************************************************/
24 // if this assertion fails, then you probably used different compiler
25 // options for the wvstreams library and the calling program. Check
26 // for defines like _FILE_OFFSET_BITS=64 and _LARGEFILE_SOURCE.
27 assert(sizeof_stat
== sizeof(struct stat
));
31 skip_mounts
= _skip_mounts
;
34 WvString
dirname(_dirname
);
35 int dl
= strlen(dirname
);
36 if (dl
!= 0 && dirname
[dl
-1] == '/')
37 dirname
.edit()[dl
-1] = 0;
39 DIR * d
= opendir( dirname
);
41 Dir
* dd
= new Dir( d
, dirname
);
42 dirs
.prepend( dd
, true );
46 WvDirIter::~WvDirIter()
47 /*********************/
52 bool WvDirIter::isok() const
53 /**************************/
55 return( !dirs
.isempty() );
58 bool WvDirIter::isdir() const
59 /***************************/
61 return( S_ISDIR( info
.st_mode
) );
64 void WvDirIter::rewind()
65 /**********************/
67 // have to closedir() everything that isn't the one we started with,
69 while( dirs
.count() > 1 ) {
83 bool WvDirIter::next()
84 /********************/
85 // use readdir... and if that returns a directory, opendir() it and prepend
86 // it to dirs, so we start reading it until it's done.
88 struct dirent
* dent
= NULL
;
98 // unrecurse if the user wants to
101 if( dirs
.count() > 1 ) {
110 dent
= readdir( dir
->d
);
112 info
.fullname
= WvString( "%s/%s", dir
->dirname
, dent
->d_name
);
113 info
.name
= dent
->d_name
;
116 info
.relname
= info
.name
;
118 info
.relname
= WvString("%s%s", relpath
, info
.name
);
120 ok
= ( lstat( info
.fullname
, &info
) == 0
121 && strcmp( dent
->d_name
, "." )
122 && strcmp( dent
->d_name
, ".." ) );
124 if (ok
&& !found_top
)
126 lstat(info
.fullname
, &topdir
);
127 topdir
.fullname
= info
.fullname
;
128 topdir
.name
= info
.name
;
129 topdir
.relname
= info
.relname
;
133 } while( dent
&& !ok
);
137 if( recurse
&& S_ISDIR( info
.st_mode
) &&
138 ( !skip_mounts
|| info
.st_dev
== topdir
.st_dev
) ) {
139 DIR * d
= opendir( info
.fullname
);
141 relpath
= WvString( "%s%s/", relpath
, info
.name
);
142 Dir
* dd
= new Dir( d
, info
.fullname
);
143 dirs
.prepend( dd
, true );
149 // end of directory. if we recursed, unlink it and go up a
150 // notch. if this is the top level, DON'T close it, so that
151 // the user can ::rewind() again if he wants.
152 if( dirs
.count() > 1 ) {
153 if (dirs
.count() == 2)
154 relpath
= WvString("");
156 relpath
= WvString( "%s/", getdirname(relpath
) );
166 return( dent
!= NULL
);