]> git.saurik.com Git - wxWidgets.git/blame - src/unix/dir.cpp
More build system polishing.. mostly. Some stuff ported over from
[wxWidgets.git] / src / unix / dir.cpp
CommitLineData
1944c6bd
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: unix/dir.cpp
3// Purpose: wxDir implementation for Unix/POSIX systems
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 08.12.99
7// RCS-ID: $Id$
8// Copyright: (c) 1999 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9// Licence: wxWindows license
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#ifdef __GNUG__
21 #pragma implementation "dir.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#ifndef WX_PRECOMP
32 #include "wx/intl.h"
33 #include "wx/log.h"
34#endif // PCH
35
36#include "wx/dir.h"
37#include "wx/filefn.h" // for wxMatchWild
38
39#include <sys/types.h>
1357a7dd
VZ
40#include <sys/stat.h>
41#include <unistd.h>
1944c6bd
VZ
42
43#include <dirent.h>
44
45// ----------------------------------------------------------------------------
46// macros
47// ----------------------------------------------------------------------------
48
49#define M_DIR ((wxDirData *)m_data)
50
51// ----------------------------------------------------------------------------
52// private classes
53// ----------------------------------------------------------------------------
54
55// this class stores everything we need to enumerate the files
56class wxDirData
57{
58public:
59 wxDirData(const wxString& dirname);
60 ~wxDirData();
61
62 bool IsOk() const { return m_dir != NULL; }
63
64 void SetFileSpec(const wxString& filespec) { m_filespec = filespec; }
65 void SetFlags(int flags) { m_flags = flags; }
66
67 void Rewind() { rewinddir(m_dir); }
68 bool Read(wxString *filename);
69
35332784
VZ
70 const wxString& GetName() const { return m_dirname; }
71
1944c6bd
VZ
72private:
73 DIR *m_dir;
74
75 wxString m_dirname;
76 wxString m_filespec;
77
78 int m_flags;
79};
80
81// ============================================================================
82// implementation
83// ============================================================================
84
85// ----------------------------------------------------------------------------
86// wxDirData
87// ----------------------------------------------------------------------------
88
89#if !defined( __VMS__ ) || ( __VMS_VER >= 70000000 )
90
91wxDirData::wxDirData(const wxString& dirname)
92 : m_dirname(dirname)
93{
94 m_dir = NULL;
95
96 // throw away the trailing slashes
97 size_t n = m_dirname.length();
98 wxCHECK_RET( n, _T("empty dir name in wxDir") );
99
100 while ( n > 0 && m_dirname[--n] == '/' )
101 ;
102
103 m_dirname.Truncate(n + 1);
104
105 // do open the dir
106 m_dir = opendir(m_dirname.fn_str());
107}
108
109wxDirData::~wxDirData()
110{
111 if ( m_dir )
112 {
113 if ( closedir(m_dir) != 0 )
114 {
115 wxLogLastError(_T("closedir"));
116 }
117 }
118}
119
120bool wxDirData::Read(wxString *filename)
121{
b0d36402 122 dirent *de = (dirent *)NULL; // just to silence compiler warnings
1944c6bd
VZ
123 bool matches = FALSE;
124
b0d36402
VZ
125 // speed up string concatenation in the loop a bit
126 wxString path = m_dirname;
127 path += _T('/');
128 path.reserve(path.length() + 255);
129
1944c6bd
VZ
130 while ( !matches )
131 {
132 de = readdir(m_dir);
133 if ( !de )
134 return FALSE;
135
136 // don't return "." and ".." unless asked for
137 if ( de->d_name[0] == '.' &&
138 ((de->d_name[1] == '.' && de->d_name[2] == '\0') ||
139 (de->d_name[1] == '\0')) )
140 {
141 if ( !(m_flags & wxDIR_DOTDOT) )
142 continue;
b0d36402
VZ
143
144 // we found a valid match
145 break;
1944c6bd
VZ
146 }
147
148 // check the type now
b0d36402 149 if ( !(m_flags & wxDIR_FILES) && !wxDir::Exists(path + de->d_name) )
1944c6bd
VZ
150 {
151 // it's a file, but we don't want them
152 continue;
153 }
b0d36402 154 else if ( !(m_flags & wxDIR_DIRS) && wxDir::Exists(path + de->d_name) )
1944c6bd
VZ
155 {
156 // it's a dir, and we don't want it
157 continue;
158 }
159
160 // finally, check the name
b0d36402 161 if ( m_filespec.empty() )
1944c6bd
VZ
162 {
163 matches = m_flags & wxDIR_HIDDEN ? TRUE : de->d_name[0] != '.';
164 }
165 else
166 {
167 // test against the pattern
168 matches = wxMatchWild(m_filespec, de->d_name,
169 !(m_flags & wxDIR_HIDDEN));
170 }
171 }
172
173 *filename = de->d_name;
174
175 return TRUE;
176}
177
178#else // old VMS (TODO)
179
180wxDirData::wxDirData(const wxString& WXUNUSED(dirname))
181{
182 wxFAIL_MSG(_T("not implemented"));
183}
184
185wxDirData::~wxDirData()
186{
187}
188
189bool wxDirData::Read(wxString * WXUNUSED(filename))
190{
191 return FALSE;
192}
193
194#endif // not or new VMS/old VMS
195
196// ----------------------------------------------------------------------------
197// wxDir helpers
198// ----------------------------------------------------------------------------
199
200/* static */
201bool wxDir::Exists(const wxString& dir)
202{
203 return wxPathExists(dir);
204}
205
206// ----------------------------------------------------------------------------
207// wxDir construction/destruction
208// ----------------------------------------------------------------------------
209
210wxDir::wxDir(const wxString& dirname)
211{
212 m_data = NULL;
213
214 (void)Open(dirname);
215}
216
217bool wxDir::Open(const wxString& dirname)
218{
219 delete M_DIR;
220 m_data = new wxDirData(dirname);
221
222 if ( !M_DIR->IsOk() )
223 {
224 wxLogSysError(_("Can not enumerate files in directory '%s'"),
225 dirname.c_str());
226
227 delete M_DIR;
228 m_data = NULL;
229
230 return FALSE;
231 }
232
233 return TRUE;
234}
235
236bool wxDir::IsOpened() const
237{
238 return m_data != NULL;
239}
240
35332784
VZ
241wxString wxDir::GetName() const
242{
243 wxString name;
244 if ( m_data )
245 {
246 name = M_DIR->GetName();
247 if ( !name.empty() && (name.Last() == _T('/')) )
248 {
249 // chop off the last (back)slash
250 name.Truncate(name.length() - 1);
251 }
252 }
253
254 return name;
255}
256
1944c6bd
VZ
257wxDir::~wxDir()
258{
259 delete M_DIR;
260}
261
262// ----------------------------------------------------------------------------
263// wxDir enumerating
264// ----------------------------------------------------------------------------
265
266bool wxDir::GetFirst(wxString *filename,
267 const wxString& filespec,
268 int flags) const
269{
270 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
271
272 M_DIR->Rewind();
273
274 M_DIR->SetFileSpec(filespec);
275 M_DIR->SetFlags(flags);
276
277 return GetNext(filename);
278}
279
280bool wxDir::GetNext(wxString *filename) const
281{
282 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
283
284 wxCHECK_MSG( filename, FALSE, _T("bad pointer in wxDir::GetNext()") );
285
286 return M_DIR->Read(filename);
287}
1357a7dd
VZ
288
289bool wxDir::HasSubDirs(const wxString& spec)
290{
291 wxCHECK_MSG( IsOpened(), FALSE, _T("must wxDir::Open() first") );
292
293 if ( spec.empty() )
294 {
295 // faster check for presence of any subdirectory: normally each subdir
296 // has a hard link to the parent directory and so, knowing that there
297 // are at least "." and "..", we have a subdirectory if and only if
298 // links number is > 2 - this is just a guess but it works fairly well
299 // in practice
300 //
301 // note that we may guess wrongly in one direction only: i.e. we may
302 // return true when there are no subdirectories but this is ok as the
303 // caller will learn it soon enough when it calls GetFirst(wxDIR)
304 // anyhow
305 wxStructStat stBuf;
306 if ( wxStat(M_DIR->GetName(), &stBuf) == 0 )
307 {
308 switch ( stBuf.st_nlink )
309 {
310 case 2:
311 // just "." and ".."
312 return FALSE;
313
314 case 0:
315 case 1:
316 // weird filesystem, don't try to guess for it, use dumb
317 // method below
318 break;
319
320 default:
321 // assume we have subdirs - may turn out to be wrong if we
322 // have other hard links to this directory but it's not
323 // that bad as explained above
324 return TRUE;
325 }
326 }
327 }
328
329 // just try to find first directory
330 wxString s;
331 return GetFirst(&s, spec, wxDIR_DIRS | wxDIR_HIDDEN);
332}
333