source: trunk/src/tools/qdir_pm.cpp@ 10

Last change on this file since 10 was 8, checked in by dmik, 20 years ago

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 13.6 KB
Line 
1/****************************************************************************
2** $Id: qdir_pm.cpp 8 2005-11-16 19:36:46Z dmik $
3**
4** Implementation of QDir class
5**
6** Copyright (C) 1992-2003 Trolltech AS. All rights reserved.
7** Copyright (C) 2004 Norman ASA. Initial OS/2 Port.
8** Copyright (C) 2005 netlabs.org. Further OS/2 Development.
9**
10** This file is part of the tools module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qplatformdefs.h"
39
40#include "qdir.h"
41#include "qdir_p.h"
42#include "qnamespace.h"
43#include "qfileinfo.h"
44#include "qfiledefs_p.h"
45#include "qregexp.h"
46#include "qstringlist.h"
47
48#ifdef QT_THREAD_SUPPORT
49# include <private/qmutexpool_p.h>
50#endif // QT_THREAD_SUPPORT
51
52#include "qt_os2.h"
53
54void QDir::slashify( QString& n )
55{
56 if ( n.isNull() )
57 return;
58 for ( int i=0; i<(int)n.length(); i++ ) {
59 if ( n[i] == '\\' )
60 n[i] = '/';
61 }
62}
63
64QString QDir::homeDirPath()
65{
66 QString d;
67 d = QFile::decodeName( getenv("HOME") );
68 if ( d.isEmpty() || !QFile::exists( d ) ) {
69 d = QFile::decodeName( getenv("HOMEDRIVE") ) + QFile::decodeName( getenv("HOMEPATH") );
70 if ( d.isEmpty() || !QFile::exists( d ) )
71 d = rootDirPath();
72 }
73 slashify( d );
74 return d;
75}
76
77/*!
78 Returns the canonical path, i.e. a path without symbolic links or
79 redundant "." or ".." elements.
80
81 On systems that do not have symbolic links this function will
82 always return the same string that absPath() returns. If the
83 canonical path does not exist (normally due to dangling symbolic
84 links) canonicalPath() returns QString::null.
85
86 \sa path(), absPath(), exists(), cleanDirPath(), dirName(),
87 absFilePath(), QString::isNull()
88*/
89
90QString QDir::canonicalPath() const
91{
92 QString r;
93
94#if defined(Q_CC_GNU)
95 char drv = 0;
96 if ( dPath[0].isLetter() && dPath[1] == ':' ) {
97 drv = _getdrive();
98 _chdrive( dPath[0].upper().latin1() );
99 }
100#else
101 int drv = 0;
102 if ( dPath[0].isLetter() && dPath[1] == ':' ) {
103 drv = _getdrive();
104 _chdrive( dPath[0].upper().latin1() - 'A' + 1 );
105 }
106#endif
107
108 char cur[PATH_MAX];
109 QT_GETCWD( cur, PATH_MAX );
110 if ( QT_CHDIR( QFile::encodeName( dPath ) ) == 0 ) {
111 char tmp[PATH_MAX];
112 if ( QT_GETCWD( tmp, PATH_MAX ) != 0 )
113 r = QFile::decodeName( tmp );
114 }
115 QT_CHDIR( cur );
116
117 if ( drv )
118 _chdrive( drv );
119
120 slashify( r );
121 return r;
122}
123
124/*!
125 Creates a directory.
126
127 If \a acceptAbsPath is TRUE a path starting with a separator ('/')
128 will create the absolute directory; if \a acceptAbsPath is FALSE
129 any number of separators at the beginning of \a dirName will be
130 removed.
131
132 Returns TRUE if successful; otherwise returns FALSE.
133
134 \sa rmdir()
135*/
136
137bool QDir::mkdir( const QString &dirName, bool acceptAbsPath ) const
138{
139 return QT_MKDIR( QFile::encodeName( filePath( dirName, acceptAbsPath ) ) ) == 0;
140}
141
142/*!
143 Removes a directory.
144
145 If \a acceptAbsPath is TRUE a path starting with a separator ('/')
146 will remove the absolute directory; if \a acceptAbsPath is FALSE
147 any number of separators at the beginning of \a dirName will be
148 removed.
149
150 The directory must be empty for rmdir() to succeed.
151
152 Returns TRUE if successful; otherwise returns FALSE.
153
154 \sa mkdir()
155*/
156
157bool QDir::rmdir( const QString &dirName, bool acceptAbsPath ) const
158{
159 return QT_RMDIR( QFile::encodeName( filePath( dirName, acceptAbsPath ) ) ) == 0;
160}
161
162
163/*!
164 Returns TRUE if the directory is readable \e and we can open files
165 by name; otherwise returns FALSE.
166
167 \warning A FALSE value from this function is not a guarantee that
168 files in the directory are not accessible.
169
170 \sa QFileInfo::isReadable()
171*/
172
173bool QDir::isReadable() const
174{
175 return QT_ACCESS( QFile::encodeName( dPath ), R_OK ) == 0;
176}
177
178/*!
179 Returns TRUE if the directory is the root directory; otherwise
180 returns FALSE.
181
182 Note: If the directory is a symbolic link to the root directory
183 this function returns FALSE. If you want to test for this use
184 canonicalPath(), e.g.
185 \code
186 QDir d( "/tmp/root_link" );
187 d = d.canonicalPath();
188 if ( d.isRoot() )
189 qWarning( "It is a root link" );
190 \endcode
191
192 \sa root(), rootDirPath()
193*/
194
195bool QDir::isRoot() const
196{
197 return dPath == "/" || dPath == "//" ||
198 (dPath[0].isLetter() && dPath.mid(1,dPath.length()) == ":/");
199}
200
201/*!
202 Renames a file or directory.
203
204 If \a acceptAbsPaths is TRUE a path starting with a separator
205 ('/') will rename the file with the absolute path; if \a
206 acceptAbsPaths is FALSE any number of separators at the beginning
207 of the names will be removed.
208
209 Returns TRUE if successful; otherwise returns FALSE.
210
211 On most file systems, rename() fails only if \a oldName does not
212 exist or if \a newName and \a oldName are not on the same
213 partition. On Windows, rename() will fail if \a newName already
214 exists. However, there are also other reasons why rename() can
215 fail. For example, on at least one file system rename() fails if
216 \a newName points to an open file.
217*/
218
219bool QDir::rename( const QString &oldName, const QString &newName,
220 bool acceptAbsPaths )
221{
222 if ( oldName.isEmpty() || newName.isEmpty() ) {
223#if defined(QT_CHECK_NULL)
224 qWarning( "QDir::rename: Empty or null file name" );
225#endif
226 return FALSE;
227 }
228 QString fn1 = filePath( oldName, acceptAbsPaths );
229 QString fn2 = filePath( newName, acceptAbsPaths );
230 return ::rename( QFile::encodeName( fn1 ), QFile::encodeName( fn2 ) ) == 0;
231}
232/*!
233 Sets the application's current working directory to \a path.
234 Returns TRUE if the directory was successfully changed; otherwise
235 returns FALSE.
236*/
237
238
239bool QDir::setCurrent( const QString &path )
240{
241 return QT_CHDIR( QFile::encodeName( path ) ) == 0;
242}
243
244/*!
245 Returns the absolute path of the application's current directory.
246
247 \sa current()
248*/
249
250QString QDir::currentDirPath()
251{
252 QString result;
253
254 char currentName[PATH_MAX];
255 if ( QT_GETCWD(currentName,PATH_MAX) != 0 ) {
256 result = QFile::decodeName( currentName );
257 }
258 slashify( result );
259 return result;
260}
261
262/*!
263 Returns the absolute path for the root directory.
264
265 For UNIX operating systems this returns "/". For Windows file
266 systems this normally returns "c:/". For OS/2 this returns "x:/"
267 where \c x is the system boot drive letter.
268
269 \sa root() drives()
270*/
271
272
273QString QDir::rootDirPath()
274{
275 ULONG bootDrive = 0;
276 DosQuerySysInfo( QSV_BOOT_DRIVE, QSV_BOOT_DRIVE, (PVOID)bootDrive, sizeof(bootDrive) );
277 QString d = QChar( (char)(bootDrive + 'A' - 1) );
278 d += ":/";
279 return d;
280}
281
282/*!
283 Returns TRUE if \a path is relative; returns FALSE if it is
284 absolute.
285
286 \sa isRelative()
287*/
288
289bool QDir::isRelativePath( const QString &path )
290{
291 return !(path[0] == '/' || path[0] == '\\' ||
292 (path[0].isLetter() && path[1] == ':')); // drive, e.g. a: or network drive
293}
294
295/*!
296 \internal
297 Reads directory entries.
298*/
299
300bool QDir::readDirEntries( const QString &nameFilter,
301 int filterSpec, int sortSpec )
302{
303 int i;
304
305 QValueList<QRegExp> filters = qt_makeFilterList( nameFilter );
306
307 bool doDirs = (filterSpec & Dirs) != 0;
308 bool doFiles = (filterSpec & Files) != 0;
309 bool noSymLinks = (filterSpec & NoSymLinks) != 0;
310 bool doReadable = (filterSpec & Readable) != 0;
311 bool doWritable = (filterSpec & Writable) != 0;
312 bool doExecable = (filterSpec & Executable) != 0;
313
314 // FilterSpec::Drives is mentioned in the docs but never used in Qt/Win32.
315 // So do we for compatibility reasons.
316
317 bool first = TRUE;
318 QString p = dPath.copy();
319 int plen = p.length();
320 HDIR ff = (HDIR) HDIR_CREATE;
321 FILEFINDBUF3 finfo = {0};
322 ULONG fcount = 1;
323 APIRET rc = 0;
324 ULONG attribute = FILE_READONLY | FILE_ARCHIVED | FILE_DIRECTORY;
325 QFileInfo fi;
326
327 if (filterSpec & Modified) attribute |= MUST_HAVE_ARCHIVED;
328 if (filterSpec & Hidden) attribute |= FILE_HIDDEN;
329 if (filterSpec & System) attribute |= FILE_SYSTEM;
330
331 if ( plen == 0 ) {
332#if defined(QT_CHECK_NULL)
333 qWarning( "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 += QString::fromLatin1("*.*");
340
341 rc = DosFindFirst( QFile::encodeName( p ), &ff, attribute,
342 &finfo, sizeof(finfo), &fcount, FIL_STANDARD );
343
344 if ( !fList ) {
345 fList = new QStringList;
346 Q_CHECK_PTR( fList );
347 } else {
348 fList->clear();
349 }
350
351 if ( rc != 0 ) {
352 // if it is a floppy disk drive, it might just not have a file on it
353 if ( plen > 1 && p[1] == ':' &&
354 ( p[0]=='A' || p[0]=='a' || p[0]=='B' || p[0]=='b' ) ) {
355 if ( !fiList ) {
356 fiList = new QFileInfoList;
357 Q_CHECK_PTR( fiList );
358 fiList->setAutoDelete( TRUE );
359 } else {
360 fiList->clear();
361 }
362 return TRUE;
363 }
364#if defined(QT_CHECK_RANGE)
365 qWarning( "QDir::readDirEntries: Cannot read the directory: %s (UTF8)",
366 dPath.utf8().data() );
367#endif
368 return FALSE;
369 }
370
371 if ( !fiList ) {
372 fiList = new QFileInfoList;
373 Q_CHECK_PTR( fiList );
374 fiList->setAutoDelete( TRUE );
375 } else {
376 fiList->clear();
377 }
378
379 for ( ;; ) {
380 if ( first )
381 first = FALSE;
382 else {
383 if ( DosFindNext( ff, &finfo, sizeof(finfo), &fcount) != 0 )
384 break;
385 }
386 int attrib = finfo.attrFile;
387 bool isDir = (attrib & FILE_DIRECTORY) != 0;
388 bool isFile = !isDir;
389 bool isSymLink = FALSE;
390 bool isReadable = TRUE;
391 bool isWritable = (attrib & FILE_READONLY) == 0;
392 bool isExecable = FALSE;
393
394 QString fname;
395 fname = QFile::decodeName( (const char*)finfo.achName );
396
397 if ( !qt_matchFilterList(filters, fname) && !(allDirs && isDir) )
398 continue;
399
400 if ( (doDirs && isDir) || (doFiles && isFile) ) {
401 QString name = fname;
402 slashify(name);
403 if ( doExecable && isFile ) {
404 QString ext = name.right(4).lower();
405 if ( ext == ".exe" || ext == ".com" || ext == ".bat" ||
406 ext == ".cmd" )
407 isExecable = TRUE;
408 }
409
410 if ( noSymLinks && isSymLink )
411 continue;
412 if ( (filterSpec & RWEMask) != 0 )
413 if ( (doReadable && !isReadable) ||
414 (doWritable && !isWritable) ||
415 (doExecable && !isExecable) )
416 continue;
417 fi.setFile( *this, name );
418 fiList->append( new QFileInfo( fi ) );
419 }
420 }
421 DosFindClose( ff );
422
423 // Sort...
424 QDirSortItem* si= new QDirSortItem[fiList->count()];
425 QFileInfo* itm;
426 i=0;
427 for (itm = fiList->first(); itm; itm = fiList->next())
428 si[i++].item = itm;
429 qt_cmp_si_sortSpec = sortSpec;
430 qsort( si, i, sizeof(si[0]), qt_cmp_si );
431 // put them back in the list
432 fiList->setAutoDelete( FALSE );
433 fiList->clear();
434 int j;
435 for ( j=0; j<i; j++ ) {
436 fiList->append( si[j].item );
437 fList->append( si[j].item->fileName() );
438 }
439 delete [] si;
440 fiList->setAutoDelete( TRUE );
441
442 if ( filterSpec == (FilterSpec)filtS && sortSpec == (SortSpec)sortS &&
443 nameFilter == nameFilt )
444 dirty = FALSE;
445 else
446 dirty = TRUE;
447 return TRUE;
448}
449
450
451/*!
452 Returns a list of the root directories on this system. On Windows
453 this returns a number of QFileInfo objects containing "C:/", "D:/"
454 etc. On other operating systems, it returns a list containing just
455 one root directory (e.g. "/").
456
457 The returned pointer is owned by Qt. Callers should \e not delete
458 or modify it.
459*/
460
461const QFileInfoList * QDir::drives()
462{
463 // at most one instance of QFileInfoList is leaked, and this variable
464 // points to that list
465 static QFileInfoList * knownMemoryLeak = 0;
466
467#ifdef QT_THREAD_SUPPORT
468 QMutexLocker locker( qt_global_mutexpool ?
469 qt_global_mutexpool->get( &knownMemoryLeak ) : 0 );
470#endif // QT_THREAD_SUPPORT
471
472 if ( !knownMemoryLeak ) {
473 knownMemoryLeak = new QFileInfoList;
474 knownMemoryLeak->setAutoDelete( TRUE );
475 }
476
477 if ( !knownMemoryLeak->count() ) {
478 ULONG driveBits, dummy;
479 DosQueryCurrentDisk( &dummy, &driveBits );
480 driveBits &= 0x3ffffff;
481
482 char driveName[4];
483 qstrcpy( driveName, "A:/" );
484
485 while( driveBits ) {
486 if ( driveBits & 1 )
487 knownMemoryLeak->append( new QFileInfo( QString::fromLatin1(driveName).upper() ) );
488 driveName[0]++;
489 driveBits = driveBits >> 1;
490 }
491 }
492
493 return knownMemoryLeak;
494}
Note: See TracBrowser for help on using the repository browser.