WvStreams
wvdiriter.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * Directory iterator. Recursively uses opendir and readdir, so you don't
6 * have to. Basically implements 'find'.
7 *
8 */
9
10#include "wvdiriter.h"
11
12#if defined(_WIN32) && !defined(S_ISDIR)
13#define S_ISDIR(x) (_S_IFDIR | (x))
14#endif
15#ifdef _WIN32
16#define lstat stat
17#endif
18
19WvDirIter::WvDirIter( WvStringParm _dirname,
20 bool _recurse, bool _skip_mounts, size_t sizeof_stat )
21 : relpath(""), dir(dirs)
22/****************************************************************************/
23{
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));
28
29 recurse = _recurse;
30 go_up = false;
31 skip_mounts = _skip_mounts;
32 found_top = false;
33
34 WvString dirname(_dirname);
35 int dl = strlen(dirname);
36 if (dl != 0 && dirname[dl-1] == '/')
37 dirname.edit()[dl-1] = 0;
38
39 DIR * d = opendir( dirname );
40 if( d ) {
41 Dir * dd = new Dir( d, dirname );
42 dirs.prepend( dd, true );
43 }
44}
45
46WvDirIter::~WvDirIter()
47/*********************/
48{
49 dirs.zap();
50}
51
52bool WvDirIter::isok() const
53/**************************/
54{
55 return( !dirs.isempty() );
56}
57
58bool WvDirIter::isdir() const
59/***************************/
60{
61 return( S_ISDIR( info.st_mode ) );
62}
63
64void WvDirIter::rewind()
65/**********************/
66{
67 // have to closedir() everything that isn't the one we started with,
68 // and rewind that.
69 while( dirs.count() > 1 ) {
70 dir.rewind();
71 dir.next();
72 dir.unlink();
73 }
74
75 if( isok() ) {
76 dir.rewind();
77 dir.next();
78 rewinddir( dir->d );
79 }
80}
81
82
83bool 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.
87{
88 struct dirent * dent = NULL;
89
90 if( !isok() )
91 return( false );
92
93 bool tryagain;
94 do {
95 bool ok = false;
96 tryagain = false;
97
98 // unrecurse if the user wants to
99 if( go_up ) {
100 go_up = false;
101 if( dirs.count() > 1 ) {
102 dir.unlink();
103 dir.rewind();
104 dir.next();
105 } else
106 return( false );
107 }
108
109 do {
110 dent = readdir( dir->d );
111 if( dent ) {
112 info.fullname = WvString( "%s/%s", dir->dirname, dent->d_name );
113 info.name = dent->d_name;
114
115 if (relpath == "")
116 info.relname = info.name;
117 else
118 info.relname = WvString("%s%s", relpath, info.name);
119
120 ok = ( lstat( info.fullname, &info ) == 0
121 && strcmp( dent->d_name, "." )
122 && strcmp( dent->d_name, ".." ) );
123
124 if (ok && !found_top)
125 {
126 lstat(info.fullname, &topdir);
127 topdir.fullname = info.fullname;
128 topdir.name = info.name;
129 topdir.relname = info.relname;
130 found_top = true;
131 }
132 }
133 } while( dent && !ok );
134
135 if( dent ) {
136 // recurse?
137 if( recurse && S_ISDIR( info.st_mode ) &&
138 ( !skip_mounts || info.st_dev == topdir.st_dev) ) {
139 DIR * d = opendir( info.fullname );
140 if( d ) {
141 relpath = WvString( "%s%s/", relpath, info.name );
142 Dir * dd = new Dir( d, info.fullname );
143 dirs.prepend( dd, true );
144 dir.rewind();
145 dir.next();
146 }
147 }
148 } else {
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("");
155 else
156 relpath = WvString( "%s/", getdirname(relpath) );
157
158 dir.unlink();
159 dir.rewind();
160 dir.next();
161 tryagain = true;
162 }
163 }
164 } while( tryagain );
165
166 return( dent != NULL );
167}
168
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition wvstring.h:94
WvString is an implementation of a simple and efficient printable-string class.
Definition wvstring.h:330