qdir_win32.cpp
Go to the documentation of this file.
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 
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 
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 
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 
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_)
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 
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 
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 
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 );
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.utf8() );
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
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;
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
static QCString name
Definition: declinfo.cpp:673
QString nameFilt
Definition: qdir.h:190
static void slashify(QString &)
Definition: qdir_unix.cpp:65
QString nameFilter() const
Definition: qdir.h:203
bool isEmpty() const
Definition: qstring.h:682
#define STATBUF
Definition: qfiledefs_p.h:199
QString lower() const
Definition: qstring.cpp:13375
Iterator append(const T &x)
Definition: qvaluelist.h:372
static QCString result
The QRegExp class provides pattern matching using regular expressions or wildcards.
Definition: qregexp.h:46
#define CHDIR
Definition: qfiledefs_p.h:222
static QString homeDirPath()
Definition: qdir_unix.cpp:69
SortSpec sortS
Definition: qdir.h:192
QString copy() const
Definition: qstring.h:685
static const QFileInfoList * drives()
Definition: qdir_unix.cpp:276
virtual QString dirName() const
Definition: qdir.cpp:300
#define PATH_MAX
Definition: qfiledefs_p.h:92
FilterSpec filtS
Definition: qdir.h:191
#define RMDIR
Definition: qfiledefs_p.h:225
#define STAT
Definition: qfiledefs_p.h:201
type * first()
Definition: qinternallist.h:87
SortSpec
Definition: qdir.h:74
void clear()
Definition: qvaluelist.h:396
const bool FALSE
Definition: qglobal.h:370
QStringList qt_makeFilterList(const QString &filter)
Definition: qdir.cpp:1010
QString dPath
Definition: qdir.h:187
static bool isRelativePath(const QString &path)
Definition: qdir_unix.cpp:169
The QString class provides an abstraction of Unicode text and the classic C null-terminated char arra...
Definition: qstring.h:350
void qWarning(const char *msg,...)
Definition: qglobal.cpp:409
virtual bool isRoot() const
Definition: qdir_unix.cpp:114
#define FF_GETNEXT
Definition: qdir_win32.cpp:283
static QString fromLatin1(const char *, int len=-1)
Definition: qstring.cpp:14539
#define IS_RDONLY
Definition: qdir_win32.cpp:278
QDir()
Definition: qdir.cpp:137
decltype(auto) constexpr size(T &&obj)
ADL-aware version of std::size.
Definition: StdUtils.h:92
#define IS_ARCH
Definition: qdir_win32.cpp:279
QInternalList< QFileInfo > QFileInfoList
Definition: qdir.h:47
const char * data() const
Definition: qstring.h:542
virtual bool mkdir(const QString &dirName, bool acceptAbsPath=TRUE) const
Definition: qdir_unix.cpp:98
QChar at(uint i) const
Definition: qstring.h:492
A list of strings.
Definition: qstringlist.h:51
void setFile(const QString &file)
Definition: qfileinfo.cpp:219
virtual bool rename(const QString &name, const QString &newName, bool acceptAbsPaths=TRUE)
Definition: qdir_unix.cpp:119
virtual bool readDirEntries(const QString &nameFilter, int FilterSpec, int SortSpec)
Definition: qdir_unix.cpp:177
uint length() const
Definition: qstring.h:679
std::void_t< T > n
#define FF_ERROR
Definition: qdir_win32.cpp:284
static QString currentDirPath()
Definition: qdir_unix.cpp:141
const unsigned short * ucs2() const
Definition: qstring.cpp:12092
static QString rootDirPath()
Definition: qdir_unix.cpp:163
#define MKDIR
Definition: qfiledefs_p.h:224
p
Definition: test.py:223
#define GETCWD
Definition: qfiledefs_p.h:221
void append(const type *d)
Definition: qinternallist.h:61
virtual QString canonicalPath() const
Definition: qdir_unix.cpp:79
string tmp
Definition: languages.py:63
static QCString encodeName(const QString &fileName)
Definition: qfile.cpp:494
type * next()
Definition: qinternallist.h:89
static QString fromUcs2(const unsigned short *ucs2)
Definition: qstring.cpp:12119
unsigned int Q_UINT32
Definition: qglobal.h:420
static QString decodeName(const QCString &localFileName)
Definition: qfile.cpp:529
int qt_cmp_si_sortSpec
Definition: qdir.cpp:1139
#define IS_SYSTEM
Definition: qdir_win32.cpp:281
void setAutoDelete(bool enable)
Definition: qcollection.h:55
QStringList * fList
Definition: qdir.h:188
unsigned short ushort
Definition: qglobal.h:350
#define CHECK_PTR(p)
Definition: qglobal.h:601
virtual bool rmdir(const QString &dirName, bool acceptAbsPath=TRUE) const
Definition: qdir_unix.cpp:104
virtual QString path() const
Definition: qdir.h:198
Q_EXPORT char * qstrcpy(char *dst, const char *src)
Definition: qcstring.h:87
uint allDirs
Definition: qdir.h:194
static QString p_getenv(QString name)
Definition: qdir_win32.cpp:62
bool isNull() const
Definition: qstring.h:379
#define IS_SUBDIR
Definition: qdir_win32.cpp:277
virtual QString filePath(const QString &fileName, bool acceptAbsPath=TRUE) const
Definition: qdir.cpp:323
#define FF_GETFIRST
Definition: qdir_win32.cpp:282
static const Null null
Definition: qstring.h:376
uint dirty
Definition: qdir.h:193
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:51
uint count() const
Definition: qinternallist.h:56
#define ACCESS
Definition: qfiledefs_p.h:216
QCString utf8() const
Definition: qstring.cpp:14507
FilterSpec
Definition: qdir.h:55
def filters(nticks=9600, tick=0.5 *units.us, npitches=3000, pitch=1.0)
Definition: __init__.py:555
virtual bool exists() const
Definition: qdir.cpp:820
const bool TRUE
Definition: qglobal.h:371
QFileInfoList * fiList
Definition: qdir.h:189
QString right(uint len) const
Definition: qstring.cpp:13231
QChar upper() const
Definition: qstring.cpp:11248
static bool setCurrent(const QString &path)
Definition: qdir_unix.cpp:134
int qt_cmp_si(const void *, const void *)
Definition: qdir.cpp:1145
#define IS_HIDDEN
Definition: qdir_win32.cpp:280
virtual bool isReadable() const
Definition: qdir_unix.cpp:109
def rename(src, dest)