Root/
Source at commit 1322 created 12 years 7 months ago. By meklort, Add doxygen to utils folder | |
---|---|
1 | /******************************************************************************␊ |
2 | *␊ |
3 | * ␊ |
4 | *␊ |
5 | * Copyright (C) 1997-2001 by Dimitri van Heesch.␊ |
6 | *␊ |
7 | * Permission to use, copy, modify, and distribute this software and its␊ |
8 | * documentation under the terms of the GNU General Public License is hereby ␊ |
9 | * granted. No representations are made about the suitability of this software ␊ |
10 | * for any purpose. It is provided "as is" without express or implied warranty.␊ |
11 | * See the GNU General Public License for more details.␊ |
12 | *␊ |
13 | * Documents produced by Doxygen are derivative works derived from the␊ |
14 | * input used in their production; they are not affected by this license.␊ |
15 | *␊ |
16 | * Based on qdir_unix.cpp ␊ |
17 | *␊ |
18 | * Copyright (C) 1992-2000 Trolltech AS.␊ |
19 | */␊ |
20 | ␊ |
21 | ␊ |
22 | #include "qglobal.h"␊ |
23 | ␊ |
24 | #include "qdir.h"␊ |
25 | #ifndef QT_NO_DIR␊ |
26 | ␊ |
27 | ␊ |
28 | #include "qfileinfo.h"␊ |
29 | #include "qfiledefs_p.h"␊ |
30 | #include "qregexp.h"␊ |
31 | #include "qstringlist.h"␊ |
32 | #include <stdlib.h>␊ |
33 | #include <ctype.h>␊ |
34 | #if defined(_OS_WIN32_)␊ |
35 | #if defined(_CC_BOOL_DEF_)␊ |
36 | #undef bool␊ |
37 | #include <windows.h>␊ |
38 | #define bool int␊ |
39 | #else␊ |
40 | #include <windows.h>␊ |
41 | #endif␊ |
42 | #endif␊ |
43 | #if defined(_OS_OS2EMX_)␊ |
44 | extern Q_UINT32 DosQueryCurrentDisk(Q_UINT32*,Q_UINT32*);␊ |
45 | #define NO_ERROR 0␊ |
46 | #endif␊ |
47 | ␊ |
48 | extern QStringList qt_makeFilterList( const QString &filter );␊ |
49 | ␊ |
50 | extern int qt_cmp_si_sortSpec;␊ |
51 | ␊ |
52 | #if defined(Q_C_CALLBACKS)␊ |
53 | extern "C" {␊ |
54 | #endif␊ |
55 | ␊ |
56 | extern int qt_cmp_si( const void *, const void * );␊ |
57 | ␊ |
58 | #if defined(Q_C_CALLBACKS)␊ |
59 | }␊ |
60 | #endif␊ |
61 | ␊ |
62 | static QString p_getenv( QString name )␊ |
63 | {␊ |
64 | DWORD len = GetEnvironmentVariableW( ( LPCWSTR ) qt_winTchar ( name, TRUE ), NULL, 0 );␊ |
65 | if ( len == 0 )␊ |
66 | return QString::null;␊ |
67 | /* ansi: we allocate too much memory, but this shouldn't be the problem here ... */␊ |
68 | LPWSTR buf = (LPWSTR)new WCHAR[ len ];␊ |
69 | len = GetEnvironmentVariableW ( ( LPCWSTR ) qt_winTchar ( name, TRUE ), buf, len );␊ |
70 | if ( len == 0 )␊ |
71 | {␊ |
72 | delete[] buf;␊ |
73 | return QString::null;␊ |
74 | }␊ |
75 | QString ret = qt_winQString ( buf );␊ |
76 | delete[] buf;␊ |
77 | return ret;␊ |
78 | }␊ |
79 | ␊ |
80 | ␊ |
81 | void QDir::slashify( QString& n )␊ |
82 | {␊ |
83 | for ( int i=0; i<(int)n.length(); i++ ) ␊ |
84 | {␊ |
85 | if ( n[i] == '\\' )␊ |
86 | n[i] = '/';␊ |
87 | }␊ |
88 | }␊ |
89 | ␊ |
90 | QString QDir::homeDirPath()␊ |
91 | {␊ |
92 | QString d = p_getenv ( "HOME" );␊ |
93 | if ( d.isNull () ) {␊ |
94 | d = p_getenv ( "USERPROFILE" );␊ |
95 | if ( d.isNull () ) {␊ |
96 | QString homeDrive = p_getenv ( "HOMEDRIVE" );␊ |
97 | QString homePath = p_getenv ( "HOMEPATH" );␊ |
98 | if ( !homeDrive.isNull () && !homePath.isNull () ) {␊ |
99 | d = homeDrive + homePath;␊ |
100 | } else {␊ |
101 | d = rootDirPath ();␊ |
102 | }␊ |
103 | }␊ |
104 | }␊ |
105 | slashify( d );␊ |
106 | return d;␊ |
107 | }␊ |
108 | ␊ |
109 | QString QDir::canonicalPath() const␊ |
110 | {␊ |
111 | QString r;␊ |
112 | ␊ |
113 | char cur[PATH_MAX];␊ |
114 | char tmp[PATH_MAX];␊ |
115 | GETCWD( cur, PATH_MAX );␊ |
116 | if ( CHDIR(QFile::encodeName(dPath)) >= 0 ) {␊ |
117 | ␉GETCWD( tmp, PATH_MAX );␊ |
118 | ␉r = QFile::decodeName(tmp);␊ |
119 | }␊ |
120 | CHDIR( cur );␊ |
121 | ␊ |
122 | slashify( r );␊ |
123 | return r;␊ |
124 | }␊ |
125 | ␊ |
126 | bool QDir::mkdir( const QString &dirName, bool acceptAbsPath ) const␊ |
127 | {␊ |
128 | #if defined(__CYGWIN32_)␊ |
129 | return MKDIR( QFile::encodeName(filePath(dirName,acceptAbsPath)), 0777 ) == 0;␊ |
130 | #else␊ |
131 | return _wmkdir( ( LPCWSTR ) filePath( dirName, acceptAbsPath ).ucs2() ) == 0;␊ |
132 | #endif␊ |
133 | }␊ |
134 | ␊ |
135 | bool QDir::rmdir( const QString &dirName, bool acceptAbsPath ) const␊ |
136 | {␊ |
137 | #if defined(__CYGWIN32_)␊ |
138 | return RMDIR( QFile::encodeName(filePath(dirName,acceptAbsPath)) ) == 0;␊ |
139 | #else␊ |
140 | return _wrmdir( ( LPCWSTR ) filePath( dirName, acceptAbsPath ).ucs2() ) == 0;␊ |
141 | #endif␊ |
142 | }␊ |
143 | ␊ |
144 | bool QDir::isReadable() const␊ |
145 | {␊ |
146 | QString path = dPath;␊ |
147 | if ( ( path[ 0 ] == '\\' ) || ( path[ 0 ] == '/' ) )␊ |
148 | path = rootDirPath() + path;␊ |
149 | #if defined(__CYGWIN32_)␊ |
150 | return ACCESS( QFile::encodeName(dPath), R_OK ) == 0;␊ |
151 | #else␊ |
152 | return ( _waccess( (wchar_t*) path.ucs2(), R_OK ) == 0 );␊ |
153 | #endif␊ |
154 | }␊ |
155 | ␊ |
156 | bool QDir::isRoot() const␊ |
157 | {␊ |
158 | QString path = dPath;␊ |
159 | slashify( path );␊ |
160 | return path == rootDirPath ();␊ |
161 | }␊ |
162 | ␊ |
163 | bool QDir::rename( const QString &name, const QString &newName,␊ |
164 | ␉␉ bool acceptAbsPaths␉)␊ |
165 | {␊ |
166 | if ( name.isEmpty() || newName.isEmpty() ) {␊ |
167 | #if defined(CHECK_NULL)␊ |
168 | ␉qWarning( "QDir::rename: Empty or null file name(s)" );␊ |
169 | #endif␊ |
170 | ␉return FALSE;␊ |
171 | }␊ |
172 | QString fn1 = filePath( name, acceptAbsPaths );␊ |
173 | QString fn2 = filePath( newName, acceptAbsPaths );␊ |
174 | #if defined(__CYGWIN32_)␊ |
175 | return ::rename( QFile::encodeName(fn1),␊ |
176 | ␉␉ QFile::encodeName(fn2) ) == 0;␊ |
177 | #else␊ |
178 | return MoveFileW( ( LPCWSTR ) fn1.ucs2(), ( LPCWSTR ) fn2.ucs2() ) != 0; ␊ |
179 | #endif␊ |
180 | }␊ |
181 | ␊ |
182 | bool QDir::setCurrent( const QString &path )␊ |
183 | {␊ |
184 | #if defined(__CYGWIN32_)␊ |
185 | int r;␊ |
186 | r = CHDIR( QFile::encodeName(path) );␊ |
187 | return r >= 0;␊ |
188 | #else␊ |
189 | if ( !QDir( path ).exists() )␊ |
190 | return false;␊ |
191 | return ( SetCurrentDirectoryW( ( LPCWSTR ) path.ucs2() ) >= 0 );␊ |
192 | #endif␊ |
193 | }␊ |
194 | ␊ |
195 | QString QDir::currentDirPath()␊ |
196 | {␊ |
197 | QString result;␊ |
198 | ␊ |
199 | #if defined(__CYGWIN32_)␊ |
200 | ␊ |
201 | STATBUF st;␊ |
202 | if ( STAT( ".", &st ) == 0 ) {␊ |
203 | ␉char currentName[PATH_MAX];␊ |
204 | ␉if ( GETCWD( currentName, PATH_MAX ) != 0 )␊ |
205 | ␉ result = QFile::decodeName(currentName);␊ |
206 | #if defined(DEBUG)␊ |
207 | ␉if ( result.isNull() )␊ |
208 | ␉ qWarning( "QDir::currentDirPath: getcwd() failed" );␊ |
209 | #endif␊ |
210 | } else {␊ |
211 | #if defined(DEBUG)␊ |
212 | ␉qWarning( "QDir::currentDirPath: stat(\".\") failed" );␊ |
213 | #endif␊ |
214 | }␊ |
215 | ␊ |
216 | #else␊ |
217 | ␊ |
218 | DWORD size = 0;␊ |
219 | WCHAR currentName[ PATH_MAX ];␊ |
220 | size = ::GetCurrentDirectoryW( PATH_MAX, currentName );␊ |
221 | if ( size != 0 ) {␊ |
222 | if ( size > PATH_MAX ) {␊ |
223 | WCHAR * newCurrentName = new WCHAR[ size ];␊ |
224 | if ( ::GetCurrentDirectoryW( PATH_MAX, newCurrentName ) != 0 )␊ |
225 | result = QString::fromUcs2( ( ushort* ) newCurrentName );␊ |
226 | delete [] newCurrentName;␊ |
227 | } else {␊ |
228 | result = QString::fromUcs2( ( ushort* ) currentName );␊ |
229 | }␊ |
230 | }␊ |
231 | ␊ |
232 | if ( result.length() >= 2 && result[ 1 ] == ':' )␊ |
233 | result[ 0 ] = result.at( 0 ).upper(); // Force uppercase drive letters.␊ |
234 | #endif␊ |
235 | slashify( result );␊ |
236 | return result;␊ |
237 | }␊ |
238 | ␊ |
239 | QString QDir::rootDirPath()␊ |
240 | {␊ |
241 | QString d = p_getenv ( "SystemDrive" );␊ |
242 | if ( d.isNull () )␊ |
243 | d = QString::fromLatin1( "c:" ); // not "c:\\" !␊ |
244 | slashify ( d );␊ |
245 | return d;␊ |
246 | }␊ |
247 | ␊ |
248 | bool QDir::isRelativePath( const QString &path )␊ |
249 | {␊ |
250 | if ( path.isEmpty() )␊ |
251 | return TRUE;␊ |
252 | int p = 0;␊ |
253 | if ( path[ 0 ].isLetter() && path[ 1 ] == ':' )␊ |
254 | p = 2; // we have checked the first 2.␊ |
255 | return ( ( path[ p ] != '/' ) && ( path[ p ] != '\\' ) );␊ |
256 | }␊ |
257 | ␊ |
258 | #undef IS_SUBDIR␊ |
259 | #undef IS_RDONLY␊ |
260 | #undef IS_ARCH␊ |
261 | #undef IS_HIDDEN␊ |
262 | #undef IS_SYSTEM␊ |
263 | #undef FF_GETFIRST␊ |
264 | #undef FF_GETNEXT␊ |
265 | #undef FF_ERROR␊ |
266 | ␊ |
267 | #if defined(_OS_WIN32_)␊ |
268 | #define IS_SUBDIR FILE_ATTRIBUTE_DIRECTORY␊ |
269 | #define IS_RDONLY FILE_ATTRIBUTE_READONLY␊ |
270 | #define IS_ARCH FILE_ATTRIBUTE_ARCHIVE␊ |
271 | #define IS_HIDDEN FILE_ATTRIBUTE_HIDDEN␊ |
272 | #define IS_SYSTEM FILE_ATTRIBUTE_SYSTEM␊ |
273 | #define FF_GETFIRST FindFirstFile␊ |
274 | #define FF_GETNEXT FindNextFile␊ |
275 | #define FF_ERROR INVALID_HANDLE_VALUE␊ |
276 | #else␊ |
277 | #define IS_SUBDIR _A_SUBDIR␊ |
278 | #define IS_RDONLY _A_RDONLY␊ |
279 | #define IS_ARCH _A_ARCH␊ |
280 | #define IS_HIDDEN _A_HIDDEN␊ |
281 | #define IS_SYSTEM _A_SYSTEM␊ |
282 | #define FF_GETFIRST _findfirst␊ |
283 | #define FF_GETNEXT _findnext␊ |
284 | #define FF_ERROR -1␊ |
285 | #endif␊ |
286 | ␊ |
287 | ␊ |
288 | bool QDir::readDirEntries( const QString &nameFilter,␊ |
289 | ␉␉␉ int filterSpec, int sortSpec )␊ |
290 | {␊ |
291 | int i;␊ |
292 | if ( !fList ) {␊ |
293 | ␉fList = new QStringList;␊ |
294 | ␉CHECK_PTR( fList );␊ |
295 | ␉fiList = new QFileInfoList;␊ |
296 | ␉CHECK_PTR( fiList );␊ |
297 | ␉fiList->setAutoDelete( TRUE );␊ |
298 | } else {␊ |
299 | ␉fList->clear();␊ |
300 | ␉fiList->clear();␊ |
301 | }␊ |
302 | ␊ |
303 | QStringList filters = qt_makeFilterList( nameFilter );␊ |
304 | ␊ |
305 | bool doDirs␉ = (filterSpec & Dirs)␉!= 0;␊ |
306 | bool doFiles = (filterSpec & Files)␉!= 0;␊ |
307 | bool noSymLinks = (filterSpec & NoSymLinks) != 0;␊ |
308 | bool doReadable = (filterSpec & Readable)␉!= 0;␊ |
309 | bool doWritable = (filterSpec & Writable)␉!= 0;␊ |
310 | bool doExecable = (filterSpec & Executable) != 0;␊ |
311 | bool doHidden = (filterSpec & Hidden)␉!= 0;␊ |
312 | // show hidden files if the user asks explicitly for e.g. .*␊ |
313 | if ( !doHidden && !nameFilter.isEmpty() && nameFilter[0] == '.' )␊ |
314 | doHidden = TRUE;␊ |
315 | bool doModified = (filterSpec & Modified) != 0;␊ |
316 | bool doSystem = (filterSpec & System) != 0;␊ |
317 | ␊ |
318 | QRegExp wc( nameFilter.data(), FALSE, TRUE ); // wild card, case insensitive␊ |
319 | bool first = TRUE;␊ |
320 | QString p = dPath.copy();␊ |
321 | int plen = p.length();␊ |
322 | #if defined(_OS_WIN32_)␊ |
323 | HANDLE ff;␊ |
324 | WIN32_FIND_DATAW finfo;␊ |
325 | #else␊ |
326 | long ff;␊ |
327 | _finddata_t finfo;␊ |
328 | #endif␊ |
329 | QFileInfo fi;␊ |
330 | if ( plen == 0 )␊ |
331 | {␊ |
332 | #if defined(CHECK_NULL)␊ |
333 | warning( "QDir::readDirEntries: No directory name specified" );␊ |
334 | #endif␊ |
335 | return FALSE;␊ |
336 | }␊ |
337 | if ( p.at(plen-1) != '/' && p.at(plen-1) != '\\' )␊ |
338 | p += '/';␊ |
339 | p += "*.*";␊ |
340 | ␊ |
341 | #if defined(__CYGWIN32_)␊ |
342 | ff = FF_GETFIRST( p.data(), &finfo );␊ |
343 | #else␊ |
344 | ff = FindFirstFileW ( ( LPCWSTR ) p.ucs2(), &finfo );␊ |
345 | #endif␊ |
346 | if ( ff == FF_ERROR ) ␊ |
347 | {␊ |
348 | #if defined(DEBUG)␊ |
349 | warning( "QDir::readDirEntries: Cannot read the directory: %s",␊ |
350 | (const char *)dPath );␊ |
351 | #endif␊ |
352 | return FALSE;␊ |
353 | }␊ |
354 | ␊ |
355 | while ( TRUE ) ␊ |
356 | {␊ |
357 | ␉if ( first )␊ |
358 | ␉ first = FALSE;␊ |
359 | ␉else ␊ |
360 | {␊ |
361 | #if defined(__CYGWIN32_)␊ |
362 | ␉ if ( FF_GETNEXT(ff,&finfo) == -1 )␊ |
363 | ␉␉break;␊ |
364 | #else␊ |
365 | ␉ //if ( !FF_GETNEXT(ff,&finfo) )␊ |
366 | ␉ //␉break;␊ |
367 | if (!FindNextFileW(ff, &finfo ))␊ |
368 | break;␊ |
369 | #endif␊ |
370 | ␉}␊ |
371 | #if defined(__CYGWIN32_)␊ |
372 | ␉int attrib = finfo.attrib;␊ |
373 | #else␊ |
374 | ␉int attrib = finfo.dwFileAttributes;␊ |
375 | #endif␊ |
376 | ␉bool isDir␉= (attrib & IS_SUBDIR) != 0;␊ |
377 | ␉bool isFile␉= !isDir;␊ |
378 | ␉bool isSymLink␉= FALSE;␊ |
379 | ␉bool isReadable = TRUE;␊ |
380 | ␉bool isWritable = (attrib & IS_RDONLY) == 0;␊ |
381 | ␉bool isExecable = FALSE;␊ |
382 | ␉bool isModified = (attrib & IS_ARCH) != 0;␊ |
383 | ␉bool isHidden␉= (attrib & IS_HIDDEN) != 0;␊ |
384 | ␉bool isSystem␉= (attrib & IS_SYSTEM) != 0;␊ |
385 | ␊ |
386 | #if defined(__CYGWIN32_)␊ |
387 | ␉const char *fname = finfo.name;␊ |
388 | #else␊ |
389 | ␉//const char *fname = finfo.cFileName;␊ |
390 | QString fname = QString::fromUcs2( ( const unsigned short* ) finfo.cFileName);␊ |
391 | #endif␊ |
392 | ␉if ( wc.match(fname.utf8()) == -1 && !(allDirs && isDir) )␊ |
393 | ␉ continue;␊ |
394 | ␊ |
395 | ␉QString name = fname;␊ |
396 | ␉if ( doExecable ) ␊ |
397 | {␊ |
398 | ␉ QString ext = name.right(4).lower();␊ |
399 | ␉ if ( ext == ".exe" || ext == ".com" || ext == ".bat" ||␊ |
400 | ␉␉ ext == ".pif" || ext == ".cmd" )␊ |
401 | ␉␉isExecable = TRUE;␊ |
402 | ␉}␊ |
403 | ␊ |
404 | ␉if ( (doDirs && isDir) || (doFiles && isFile) ) ␊ |
405 | {␊ |
406 | ␉ if ( noSymLinks && isSymLink )␊ |
407 | ␉␉continue;␊ |
408 | ␉ if ( (filterSpec & RWEMask) != 0 )␊ |
409 | ␉␉if ( (doReadable && !isReadable) ||␊ |
410 | ␉␉ (doWritable && !isWritable) ||␊ |
411 | ␉␉ (doExecable && !isExecable) )␊ |
412 | ␉␉ continue;␊ |
413 | ␉ if ( doModified && !isModified )␊ |
414 | ␉␉continue;␊ |
415 | ␉ if ( !doHidden && isHidden )␊ |
416 | ␉␉continue;␊ |
417 | ␉ if ( !doSystem && isSystem )␊ |
418 | ␉␉continue;␊ |
419 | ␉ fi.setFile( *this, name );␊ |
420 | ␉ fiList->append( new QFileInfo( fi ) );␊ |
421 | ␉}␊ |
422 | }␊ |
423 | #if defined(__CYGWIN32_)␊ |
424 | _findclose( ff );␊ |
425 | #else␊ |
426 | FindClose( ff );␊ |
427 | #endif␊ |
428 | ␊ |
429 | // Sort...␊ |
430 | QDirSortItem* si= new QDirSortItem[fiList->count()];␊ |
431 | QFileInfo* itm;␊ |
432 | i=0;␊ |
433 | for (itm = fiList->first(); itm; itm = fiList->next())␊ |
434 | ␉si[i++].item = itm;␊ |
435 | qt_cmp_si_sortSpec = sortSpec;␊ |
436 | qsort( si, i, sizeof(si[0]), qt_cmp_si );␊ |
437 | // put them back in the list␊ |
438 | fiList->setAutoDelete( FALSE );␊ |
439 | fiList->clear();␊ |
440 | int j;␊ |
441 | for ( j=0; j<i; j++ ) {␊ |
442 | ␉fiList->append( si[j].item );␊ |
443 | ␉fList->append( si[j].item->fileName() );␊ |
444 | }␊ |
445 | delete [] si;␊ |
446 | fiList->setAutoDelete( TRUE );␊ |
447 | ␊ |
448 | if ( filterSpec == (FilterSpec)filtS && sortSpec == (SortSpec)sortS &&␊ |
449 | ␉ nameFilter == nameFilt )␊ |
450 | ␉dirty = FALSE;␊ |
451 | else␊ |
452 | ␉dirty = TRUE;␊ |
453 | return TRUE;␊ |
454 | }␊ |
455 | ␊ |
456 | const QFileInfoList * QDir::drives()␊ |
457 | {␊ |
458 | // at most one instance of QFileInfoList is leaked, and this variable␊ |
459 | // points to that list␊ |
460 | static QFileInfoList * knownMemoryLeak = 0;␊ |
461 | ␊ |
462 | if ( !knownMemoryLeak ) {␊ |
463 | ␉knownMemoryLeak = new QFileInfoList;␊ |
464 | ␊ |
465 | #if defined(_OS_WIN32_)␊ |
466 | ␉Q_UINT32 driveBits = (Q_UINT32) GetLogicalDrives() & 0x3ffffff;␊ |
467 | #elif defined(_OS_OS2EMX_)␊ |
468 | ␉Q_UINT32 driveBits, cur;␊ |
469 | ␉if (DosQueryCurrentDisk(&cur,&driveBits) != NO_ERROR)␊ |
470 | ␉ exit(1);␊ |
471 | ␉driveBits &= 0x3ffffff;␊ |
472 | #endif␊ |
473 | ␉char driveName[4];␊ |
474 | ␉qstrcpy( driveName, "a:/" );␊ |
475 | ␉while( driveBits ) {␊ |
476 | ␉ if ( driveBits & 1 )␊ |
477 | ␉␉knownMemoryLeak->append( new QFileInfo( driveName ) );␊ |
478 | ␉ driveName[0]++;␊ |
479 | ␉ driveBits = driveBits >> 1;␊ |
480 | ␉}␊ |
481 | }␊ |
482 | ␊ |
483 | return knownMemoryLeak;␊ |
484 | }␊ |
485 | #endif //QT_NO_DIR␊ |
486 |