Qt 4.8
qfsfileengine_win.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #define _POSIX_
43 #include "qplatformdefs.h"
44 #include "qabstractfileengine.h"
45 #include "private/qfsfileengine_p.h"
46 #include "qfilesystemengine_p.h"
47 #include <qdebug.h>
48 
49 #include "qfile.h"
50 #include "qdir.h"
51 #include "private/qmutexpool_p.h"
52 #include "qvarlengtharray.h"
53 #include "qdatetime.h"
54 #include "qt_windows.h"
55 
56 #if !defined(Q_OS_WINCE)
57 # include <sys/types.h>
58 # include <direct.h>
59 # include <winioctl.h>
60 #else
61 # include <types.h>
62 #endif
63 #include <objbase.h>
64 #include <shlobj.h>
65 #include <initguid.h>
66 #include <accctrl.h>
67 #include <ctype.h>
68 #include <limits.h>
69 #define SECURITY_WIN32
70 #include <security.h>
71 
72 #ifndef PATH_MAX
73 #define PATH_MAX FILENAME_MAX
74 #endif
75 
77 
78 #if !defined(Q_OS_WINCE)
79 static inline bool isUncPath(const QString &path)
80 {
81  // Starts with \\, but not \\.
82  return (path.startsWith(QLatin1String("\\\\"))
83  && path.size() > 2 && path.at(2) != QLatin1Char('.'));
84 }
85 #endif
86 
91 {
92  if (path.startsWith(QLatin1String("\\\\.\\")))
93  return path;
94 
96 #if !defined(Q_OS_WINCE)
97  QString prefix = QLatin1String("\\\\?\\");
98  if (isUncPath(absPath)) {
99  prefix.append(QLatin1String("UNC\\")); // "\\\\?\\UNC\\"
100  absPath.remove(0, 2);
101  }
102  return prefix + absPath;
103 #else
104  return absPath;
105 #endif
106 }
107 
108 /*
109  \internal
110 */
111 bool QFSFileEnginePrivate::nativeOpen(QIODevice::OpenMode openMode)
112 {
114 
115  // All files are opened in share mode (both read and write).
116  DWORD shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
117 
118  int accessRights = 0;
119  if (openMode & QIODevice::ReadOnly)
120  accessRights |= GENERIC_READ;
121  if (openMode & QIODevice::WriteOnly)
122  accessRights |= GENERIC_WRITE;
123 
124  SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE };
125 
126  // WriteOnly can create files, ReadOnly cannot.
127  DWORD creationDisp = (openMode & QIODevice::WriteOnly) ? OPEN_ALWAYS : OPEN_EXISTING;
128  // Create the file handle.
129  fileHandle = CreateFile((const wchar_t*)fileEntry.nativeFilePath().utf16(),
130  accessRights,
131  shareMode,
132  &securityAtts,
133  creationDisp,
134  FILE_ATTRIBUTE_NORMAL,
135  NULL);
136 
137  // Bail out on error.
138  if (fileHandle == INVALID_HANDLE_VALUE) {
139  q->setError(QFile::OpenError, qt_error_string());
140  return false;
141  }
142 
143  // Truncate the file after successfully opening it if Truncate is passed.
144  if (openMode & QIODevice::Truncate)
145  q->setSize(0);
146 
147  // Seek to the end when in Append mode.
148  if (openMode & QFile::Append) {
149  ::SetFilePointer(fileHandle, 0, 0, FILE_END);
150  }
151 
152  return true;
153 }
154 
155 /*
156  \internal
157 */
159 {
161  if (fh || fd != -1) {
162  // stdlib / stdio mode.
163  return closeFdFh();
164  }
165 
166  // Windows native mode.
167  bool ok = true;
168 
169 #ifndef Q_OS_WINCE
170  if (cachedFd != -1) {
171  if (::_close(cachedFd) && !::CloseHandle(fileHandle)) {
173  ok = false;
174  }
175 
176  // System handle is closed with associated file descriptor.
177  fileHandle = INVALID_HANDLE_VALUE;
178  cachedFd = -1;
179 
180  return ok;
181  }
182 #endif
183 
184  if ((fileHandle == INVALID_HANDLE_VALUE || !::CloseHandle(fileHandle))) {
186  ok = false;
187  }
188  fileHandle = INVALID_HANDLE_VALUE;
189  return ok;
190 }
191 
192 /*
193  \internal
194 */
196 {
197  if (fh) {
198  // Buffered stdlib mode.
199  return flushFh();
200  }
201  if (fd != -1) {
202  // Unbuffered stdio mode; always succeeds (no buffer).
203  return true;
204  }
205 
206  // Windows native mode; flushing is
207  // unnecessary. FlushFileBuffers(), the equivalent of sync() or
208  // fsync() on Unix, does a low-level flush to the disk, and we
209  // don't expose an API for this.
210  return true;
211 }
212 
213 /*
214  \internal
215 */
217 {
218  Q_Q(const QFSFileEngine);
219  QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q);
220 
221  // ### Don't flush; for buffered files, we should get away with ftell.
222  thatQ->flush();
223 
224  // Always retrive the current information
226 #if defined(Q_OS_WINCE)
227  // Buffered stdlib mode.
228  if (fh) {
229  QT_OFF_T oldPos = QT_FTELL(fh);
230  QT_FSEEK(fh, 0, SEEK_END);
231  qint64 fileSize = (qint64)QT_FTELL(fh);
232  QT_FSEEK(fh, oldPos, SEEK_SET);
233  if (fileSize == -1) {
234  fileSize = 0;
236  }
237  return fileSize;
238  }
239  if (fd != -1) {
240  thatQ->setError(QFile::UnspecifiedError, QLatin1String("Not implemented!"));
241  return 0;
242  }
243 #endif
244  bool filled = false;
245  if (fileHandle != INVALID_HANDLE_VALUE && openMode != QIODevice::NotOpen )
248  else
250 
251  if (!filled) {
253  }
254  return metaData.size();
255 }
256 
257 /*
258  \internal
259 */
261 {
262  Q_Q(const QFSFileEngine);
263  QFSFileEngine *thatQ = const_cast<QFSFileEngine *>(q);
264 
265  if (fh || fd != -1) {
266  // stdlib / stido mode.
267  return posFdFh();
268  }
269 
270  // Windows native mode.
271  if (fileHandle == INVALID_HANDLE_VALUE)
272  return 0;
273 
274 #if !defined(Q_OS_WINCE)
275  LARGE_INTEGER currentFilePos;
276  LARGE_INTEGER offset;
277  offset.QuadPart = 0;
278  if (!::SetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_CURRENT)) {
280  return 0;
281  }
282 
283  return qint64(currentFilePos.QuadPart);
284 #else
285  LARGE_INTEGER filepos;
286  filepos.HighPart = 0;
287  DWORD newFilePointer = SetFilePointer(fileHandle, 0, &filepos.HighPart, FILE_CURRENT);
288  if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
290  return 0;
291  }
292 
293  filepos.LowPart = newFilePointer;
294  return filepos.QuadPart;
295 #endif
296 }
297 
298 /*
299  \internal
300 */
302 {
304 
305  if (fh || fd != -1) {
306  // stdlib / stdio mode.
307  return seekFdFh(pos);
308  }
309 
310 #if !defined(Q_OS_WINCE)
311  LARGE_INTEGER currentFilePos;
312  LARGE_INTEGER offset;
313  offset.QuadPart = pos;
314  if (!::SetFilePointerEx(fileHandle, offset, &currentFilePos, FILE_BEGIN)) {
316  return false;
317  }
318 
319  return true;
320 #else
321  DWORD newFilePointer;
322  LARGE_INTEGER *li = reinterpret_cast<LARGE_INTEGER*>(&pos);
323  newFilePointer = SetFilePointer(fileHandle, li->LowPart, &li->HighPart, FILE_BEGIN);
324  if (newFilePointer == 0xFFFFFFFF && GetLastError() != NO_ERROR) {
325  q->setError(QFile::PositionError, qt_error_string());
326  return false;
327  }
328 
329  return true;
330 #endif
331 }
332 
333 /*
334  \internal
335 */
337 {
339 
340  if (fh || fd != -1) {
341  // stdio / stdlib mode.
342  if (fh && nativeIsSequential() && feof(fh)) {
343  q->setError(QFile::ReadError, qt_error_string(int(errno)));
344  return -1;
345  }
346 
347  return readFdFh(data, maxlen);
348  }
349 
350  // Windows native mode.
351  if (fileHandle == INVALID_HANDLE_VALUE)
352  return -1;
353 
354  DWORD bytesToRead = DWORD(maxlen); // <- lossy
355 
356  // Reading on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
357  // the chunks are too large, so we limit the block size to 32MB.
358  static const DWORD maxBlockSize = 32 * 1024 * 1024;
359 
360  qint64 totalRead = 0;
361  do {
362  DWORD blockSize = qMin<DWORD>(bytesToRead, maxBlockSize);
363  DWORD bytesRead;
364  if (!ReadFile(fileHandle, data + totalRead, blockSize, &bytesRead, NULL)) {
365  if (totalRead == 0) {
366  // Note: only return failure if the first ReadFile fails.
367  q->setError(QFile::ReadError, qt_error_string());
368  return -1;
369  }
370  break;
371  }
372  if (bytesRead == 0)
373  break;
374  totalRead += bytesRead;
375  bytesToRead -= bytesRead;
376  } while (totalRead < maxlen);
377  return qint64(totalRead);
378 }
379 
380 /*
381  \internal
382 */
384 {
386 
387  if (fh || fd != -1) {
388  // stdio / stdlib mode.
389  return readLineFdFh(data, maxlen);
390  }
391 
392  // Windows native mode.
393  if (fileHandle == INVALID_HANDLE_VALUE)
394  return -1;
395 
396  // ### No equivalent in Win32?
397  return q->QAbstractFileEngine::readLine(data, maxlen);
398 }
399 
400 /*
401  \internal
402 */
404 {
406 
407  if (fh || fd != -1) {
408  // stdio / stdlib mode.
409  return writeFdFh(data, len);
410  }
411 
412  // Windows native mode.
413  if (fileHandle == INVALID_HANDLE_VALUE)
414  return -1;
415 
416  qint64 bytesToWrite = DWORD(len); // <- lossy
417 
418  // Writing on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
419  // the chunks are too large, so we limit the block size to 32MB.
420  static const DWORD maxBlockSize = 32 * 1024 * 1024;
421 
422  qint64 totalWritten = 0;
423  do {
424  DWORD blockSize = qMin<DWORD>(bytesToWrite, maxBlockSize);
425  DWORD bytesWritten;
426  if (!WriteFile(fileHandle, data + totalWritten, blockSize, &bytesWritten, NULL)) {
427  if (totalWritten == 0) {
428  // Note: Only return error if the first WriteFile failed.
429  q->setError(QFile::WriteError, qt_error_string());
430  return -1;
431  }
432  break;
433  }
434  if (bytesWritten == 0)
435  break;
436  totalWritten += bytesWritten;
437  bytesToWrite -= bytesWritten;
438  } while (totalWritten < len);
439  return qint64(totalWritten);
440 }
441 
442 /*
443  \internal
444 */
446 {
447  if (fh || fd != -1)
448  return fh ? QT_FILENO(fh) : fd;
449 #ifndef Q_OS_WINCE
450  if (cachedFd != -1)
451  return cachedFd;
452 
453  int flags = 0;
455  flags |= _O_APPEND;
457  flags |= _O_RDONLY;
458  cachedFd = _open_osfhandle((intptr_t) fileHandle, flags);
459  return cachedFd;
460 #else
461  return -1;
462 #endif
463 }
464 
465 /*
466  \internal
467 */
469 {
470 #if !defined(Q_OS_WINCE)
471  HANDLE handle = fileHandle;
472  if (fh || fd != -1)
473  handle = (HANDLE)_get_osfhandle(fh ? QT_FILENO(fh) : fd);
474  if (handle == INVALID_HANDLE_VALUE)
475  return false;
476 
477  DWORD fileType = GetFileType(handle);
478  return (fileType == FILE_TYPE_CHAR)
479  || (fileType == FILE_TYPE_PIPE);
480 #else
481  return false;
482 #endif
483 }
484 
486 {
489  bool ret = QFileSystemEngine::removeFile(d->fileEntry, error);
490  if (!ret)
491  setError(QFile::RemoveError, error.toString());
492  return ret;
493 }
494 
495 bool QFSFileEngine::copy(const QString &copyName)
496 {
499  bool ret = QFileSystemEngine::copyFile(d->fileEntry, QFileSystemEntry(copyName), error);
500  if (!ret)
501  setError(QFile::CopyError, error.toString());
502  return ret;
503 }
504 
505 bool QFSFileEngine::rename(const QString &newName)
506 {
509  bool ret = QFileSystemEngine::renameFile(d->fileEntry, QFileSystemEntry(newName), error);
510  if (!ret)
511  setError(QFile::RenameError, error.toString());
512  return ret;
513 }
514 
515 bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) const
516 {
517  return QFileSystemEngine::createDirectory(QFileSystemEntry(name), createParentDirectories);
518 }
519 
520 bool QFSFileEngine::rmdir(const QString &name, bool recurseParentDirectories) const
521 {
522  return QFileSystemEngine::removeDirectory(QFileSystemEntry(name), recurseParentDirectories);
523 }
524 
525 bool QFSFileEngine::caseSensitive() const
526 {
527  return false;
528 }
529 
530 bool QFSFileEngine::setCurrentPath(const QString &path)
531 {
533 }
534 
536 {
537 #if !defined(Q_OS_WINCE)
538  QString ret;
539  //if filename is a drive: then get the pwd of that drive
540  if (fileName.length() >= 2 &&
541  fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':')) {
542  int drv = fileName.toUpper().at(0).toLatin1() - 'A' + 1;
543  if (_getdrive() != drv) {
544  wchar_t buf[PATH_MAX];
545  ::_wgetdcwd(drv, buf, PATH_MAX);
546  ret = QString::fromWCharArray(buf);
547  }
548  }
549  if (ret.isEmpty()) {
550  //just the pwd
552  }
553  if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
554  ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
555  return ret;
556 #else
557  Q_UNUSED(fileName);
559 #endif
560 }
561 
563 {
565 }
566 
568 {
570 }
571 
573 {
575 }
576 
578 {
579  QFileInfoList ret;
580 #if !defined(Q_OS_WINCE)
581 #if defined(Q_OS_WIN32)
582  quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff;
583 #elif defined(Q_OS_OS2EMX)
584  quint32 driveBits, cur;
585  if (DosQueryCurrentDisk(&cur, &driveBits) != NO_ERROR)
586  exit(1);
587  driveBits &= 0x3ffffff;
588 #endif
589  char driveName[] = "A:/";
590 
591  while (driveBits) {
592  if (driveBits & 1)
593  ret.append(QFileInfo(QLatin1String(driveName)));
594  driveName[0]++;
595  driveBits = driveBits >> 1;
596  }
597  return ret;
598 #else
599  ret.append(QFileInfo(QLatin1String("/")));
600  return ret;
601 #endif
602 }
603 
604 bool QFSFileEnginePrivate::doStat(QFileSystemMetaData::MetaDataFlags flags) const
605 {
606  if (!tried_stat || !metaData.hasFlags(flags)) {
607  tried_stat = true;
608 
609 #if !defined(Q_OS_WINCE)
610  int localFd = fd;
611  if (fh && fileEntry.isEmpty())
612  localFd = QT_FILENO(fh);
613  if (localFd != -1)
614  QFileSystemEngine::fillMetaData(localFd, metaData, flags);
615 #endif
616  if (metaData.missingFlags(flags) && !fileEntry.isEmpty())
618  }
619 
620  return metaData.exists();
621 }
622 
623 
624 bool QFSFileEngine::link(const QString &newName)
625 {
626 #if !defined(Q_OS_WINCE)
627 #if !defined(QT_NO_LIBRARY) && !defined(Q_CC_MWERKS)
628  bool ret = false;
629 
630  QString linkName = newName;
631  //### assume that they add .lnk
632 
633  IShellLink *psl;
634  bool neededCoInit = false;
635 
636  HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
637 
638  if (hres == CO_E_NOTINITIALIZED) { // COM was not initialized
639  neededCoInit = true;
640  CoInitialize(NULL);
641  hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl);
642  }
643 
644  if (SUCCEEDED(hres)) {
645  hres = psl->SetPath((wchar_t *)fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
646  if (SUCCEEDED(hres)) {
647  hres = psl->SetWorkingDirectory((wchar_t *)fileName(AbsolutePathName).replace(QLatin1Char('/'), QLatin1Char('\\')).utf16());
648  if (SUCCEEDED(hres)) {
649  IPersistFile *ppf;
650  hres = psl->QueryInterface(IID_IPersistFile, (void **)&ppf);
651  if (SUCCEEDED(hres)) {
652  hres = ppf->Save((wchar_t*)linkName.utf16(), TRUE);
653  if (SUCCEEDED(hres))
654  ret = true;
655  ppf->Release();
656  }
657  }
658  }
659  psl->Release();
660  }
661  if (!ret)
662  setError(QFile::RenameError, qt_error_string());
663 
664  if (neededCoInit)
665  CoUninitialize();
666 
667  return ret;
668 #else
669  Q_UNUSED(newName);
670  return false;
671 #endif // QT_NO_LIBRARY
672 #else
673  QString linkName = newName;
674  linkName.replace(QLatin1Char('/'), QLatin1Char('\\'));
675  if (!linkName.endsWith(QLatin1String(".lnk")))
676  linkName += QLatin1String(".lnk");
677  QString orgName = fileName(AbsoluteName).replace(QLatin1Char('/'), QLatin1Char('\\'));
678  // Need to append on our own
679  orgName.prepend(QLatin1Char('"'));
680  orgName.append(QLatin1Char('"'));
681  bool ret = SUCCEEDED(SHCreateShortcut((wchar_t*)linkName.utf16(), (wchar_t*)orgName.utf16()));
682  if (!ret)
683  setError(QFile::RenameError, qt_error_string());
684  return ret;
685 #endif // Q_OS_WINCE
686 }
687 
691 QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const
692 {
693  Q_D(const QFSFileEngine);
694 
695  if (type & Refresh)
696  d->metaData.clear();
697 
698  QAbstractFileEngine::FileFlags ret = 0;
699 
700  if (type & FlagsMask)
701  ret |= LocalDiskFlag;
702 
703  bool exists;
704  {
705  QFileSystemMetaData::MetaDataFlags queryFlags = 0;
706 
707  queryFlags |= QFileSystemMetaData::MetaDataFlags(uint(type))
709 
710  // AliasType and BundleType are 0x0
711  if (type & TypesMask)
712  queryFlags |= QFileSystemMetaData::AliasType
717 
718  if (type & FlagsMask)
721 
722  queryFlags |= QFileSystemMetaData::LinkType;
723 
724  exists = d->doStat(queryFlags);
725  }
726 
727  if (exists && (type & PermsMask))
728  ret |= FileFlags(uint(d->metaData.permissions()));
729 
730  if (type & TypesMask) {
731  if ((type & LinkType) && d->metaData.isLegacyLink())
732  ret |= LinkType;
733  if (d->metaData.isDirectory()) {
734  ret |= DirectoryType;
735  } else {
736  ret |= FileType;
737  }
738  }
739  if (type & FlagsMask) {
740  if (d->metaData.exists()) {
741  ret |= ExistsFlag;
742  if (d->fileEntry.isRoot())
743  ret |= RootFlag;
744  else if (d->metaData.isHidden())
745  ret |= HiddenFlag;
746  }
747  }
748  return ret;
749 }
750 
751 QString QFSFileEngine::fileName(FileName file) const
752 {
753  Q_D(const QFSFileEngine);
754  if (file == BaseName) {
755  return d->fileEntry.fileName();
756  } else if (file == PathName) {
757  return d->fileEntry.path();
758  } else if (file == AbsoluteName || file == AbsolutePathName) {
759  QString ret;
760 
761  if (!isRelativePath()) {
762 #if !defined(Q_OS_WINCE)
763  if (d->fileEntry.filePath().startsWith(QLatin1Char('/')) || // It's a absolute path to the current drive, so \a.txt -> Z:\a.txt
764  d->fileEntry.filePath().size() == 2 || // It's a drive letter that needs to get a working dir appended
765  (d->fileEntry.filePath().size() > 2 && d->fileEntry.filePath().at(2) != QLatin1Char('/')) || // It's a drive-relative path, so Z:a.txt -> Z:\currentpath\a.txt
766  d->fileEntry.filePath().contains(QLatin1String("/../")) || d->fileEntry.filePath().contains(QLatin1String("/./")) ||
767  d->fileEntry.filePath().endsWith(QLatin1String("/..")) || d->fileEntry.filePath().endsWith(QLatin1String("/.")))
768  {
770  } else
771 #endif
772  {
773  ret = d->fileEntry.filePath();
774  }
775  } else {
776  ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->fileEntry.filePath());
777  }
778 
779  // The path should be absolute at this point.
780  // From the docs :
781  // Absolute paths begin with the directory separator "/"
782  // (optionally preceded by a drive specification under Windows).
783  if (ret.at(0) != QLatin1Char('/')) {
784  Q_ASSERT(ret.length() >= 2);
785  Q_ASSERT(ret.at(0).isLetter());
786  Q_ASSERT(ret.at(1) == QLatin1Char(':'));
787 
788  // Force uppercase drive letters.
789  ret[0] = ret.at(0).toUpper();
790  }
791 
792  if (file == AbsolutePathName) {
793  int slash = ret.lastIndexOf(QLatin1Char('/'));
794  if (slash < 0)
795  return ret;
796  else if (ret.at(0) != QLatin1Char('/') && slash == 2)
797  return ret.left(3); // include the slash
798  else
799  return ret.left(slash > 0 ? slash : 1);
800  }
801  return ret;
802  } else if (file == CanonicalName || file == CanonicalPathName) {
803  if (!(fileFlags(ExistsFlag) & ExistsFlag))
804  return QString();
806 
807  if (file == CanonicalPathName)
808  return entry.path();
809  return entry.filePath();
810  } else if (file == LinkName) {
811  return QFileSystemEngine::getLinkTarget(d->fileEntry, d->metaData).filePath();
812  } else if (file == BundleName) {
813  return QString();
814  }
815  return d->fileEntry.filePath();
816 }
817 
819 {
820  Q_D(const QFSFileEngine);
821  // drive, e.g. "a:", or UNC root, e.q. "//"
822  return d->fileEntry.isRelative();
823 }
824 
825 uint QFSFileEngine::ownerId(FileOwner /*own*/) const
826 {
827  static const uint nobodyID = (uint) -2;
828  return nobodyID;
829 }
830 
831 QString QFSFileEngine::owner(FileOwner own) const
832 {
833  Q_D(const QFSFileEngine);
834  return QFileSystemEngine::owner(d->fileEntry, own);
835 }
836 
838 {
841  bool ret = QFileSystemEngine::setPermissions(d->fileEntry, QFile::Permissions(perms), error);
842  if (!ret)
843  setError(QFile::PermissionsError, error.toString());
844  return ret;
845 }
846 
848 {
850 
851  if (d->fileHandle != INVALID_HANDLE_VALUE || d->fd != -1 || d->fh) {
852  // resize open file
853  HANDLE fh = d->fileHandle;
854 #if !defined(Q_OS_WINCE)
855  if (fh == INVALID_HANDLE_VALUE) {
856  if (d->fh)
857  fh = (HANDLE)_get_osfhandle(QT_FILENO(d->fh));
858  else
859  fh = (HANDLE)_get_osfhandle(d->fd);
860  }
861 #endif
862  if (fh == INVALID_HANDLE_VALUE)
863  return false;
864  qint64 currentPos = pos();
865 
866  if (seek(size) && SetEndOfFile(fh)) {
867  seek(qMin(currentPos, size));
868  return true;
869  }
870 
871  seek(currentPos);
872  return false;
873  }
874 
875  if (!d->fileEntry.isEmpty()) {
876  // resize file on disk
877  QFile file(d->fileEntry.filePath());
878  if (file.open(QFile::ReadWrite)) {
879  bool ret = file.resize(size);
880  if (!ret)
881  setError(QFile::ResizeError, file.errorString());
882  return ret;
883  }
884  }
885  return false;
886 }
887 
888 
889 QDateTime QFSFileEngine::fileTime(FileTime time) const
890 {
891  Q_D(const QFSFileEngine);
892 
893  if (d->doStat(QFileSystemMetaData::Times))
894  return d->metaData.fileTime(time);
895 
896  return QDateTime();
897 }
898 
900  QFile::MemoryMapFlags flags)
901 {
903  Q_UNUSED(flags);
904  if (openMode == QFile::NotOpen) {
905  q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
906  return 0;
907  }
908  if (offset == 0 && size == 0) {
909  q->setError(QFile::UnspecifiedError, qt_error_string(ERROR_INVALID_PARAMETER));
910  return 0;
911  }
912 
913  if (mapHandle == NULL) {
914  // get handle to the file
915  HANDLE handle = fileHandle;
916 
917 #ifndef Q_OS_WINCE
918  if (handle == INVALID_HANDLE_VALUE && fh)
919  handle = (HANDLE)::_get_osfhandle(QT_FILENO(fh));
920 #endif
921 
922 #ifdef Q_USE_DEPRECATED_MAP_API
923  nativeClose();
924  // handle automatically closed by kernel with mapHandle (below).
925  handle = ::CreateFileForMapping((const wchar_t*)fileEntry.nativeFilePath().utf16(),
926  GENERIC_READ | (openMode & QIODevice::WriteOnly ? GENERIC_WRITE : 0),
927  0,
928  NULL,
929  OPEN_EXISTING,
930  FILE_ATTRIBUTE_NORMAL,
931  NULL);
932  // Since this is a special case, we check if the return value was NULL and if so
933  // we change it to INVALID_HANDLE_VALUE to follow the logic inside this function.
934  if(0 == handle)
935  handle = INVALID_HANDLE_VALUE;
936 #endif
937 
938  if (handle == INVALID_HANDLE_VALUE) {
939  q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
940  return 0;
941  }
942 
943  // first create the file mapping handle
944  DWORD protection = (openMode & QIODevice::WriteOnly) ? PAGE_READWRITE : PAGE_READONLY;
945  mapHandle = ::CreateFileMapping(handle, 0, protection, 0, 0, 0);
946  if (mapHandle == NULL) {
948 #ifdef Q_USE_DEPRECATED_MAP_API
949  ::CloseHandle(handle);
950 #endif
951  return 0;
952  }
953  }
954 
955  // setup args to map
956  DWORD access = 0;
957  if (openMode & QIODevice::ReadOnly) access = FILE_MAP_READ;
958  if (openMode & QIODevice::WriteOnly) access = FILE_MAP_WRITE;
959 
960  DWORD offsetHi = offset >> 32;
961  DWORD offsetLo = offset & Q_UINT64_C(0xffffffff);
962  SYSTEM_INFO sysinfo;
963  ::GetSystemInfo(&sysinfo);
964  DWORD mask = sysinfo.dwAllocationGranularity - 1;
965  DWORD extra = offset & mask;
966  if (extra)
967  offsetLo &= ~mask;
968 
969  // attempt to create the map
970  LPVOID mapAddress = ::MapViewOfFile(mapHandle, access,
971  offsetHi, offsetLo, size + extra);
972  if (mapAddress) {
973  uchar *address = extra + static_cast<uchar*>(mapAddress);
974  maps[address] = extra;
975  return address;
976  }
977 
978  switch(GetLastError()) {
979  case ERROR_ACCESS_DENIED:
981  break;
982  case ERROR_INVALID_PARAMETER:
983  // size are out of bounds
984  default:
986  }
987 
988  ::CloseHandle(mapHandle);
989  mapHandle = NULL;
990  return 0;
991 }
992 
994 {
996  if (!maps.contains(ptr)) {
997  q->setError(QFile::PermissionsError, qt_error_string(ERROR_ACCESS_DENIED));
998  return false;
999  }
1000  uchar *start = ptr - maps[ptr];
1001  if (!UnmapViewOfFile(start)) {
1002  q->setError(QFile::PermissionsError, qt_error_string());
1003  return false;
1004  }
1005 
1006  maps.remove(ptr);
1007  if (maps.isEmpty()) {
1008  ::CloseHandle(mapHandle);
1009  mapHandle = NULL;
1010  }
1011 
1012  return true;
1013 }
1014 
uchar * map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags)
static QString fromWCharArray(const wchar_t *, int size=-1)
Returns a copy of the string, where the encoding of string depends on the size of wchar...
Definition: qstring.cpp:1019
void setError(QFile::FileError error, const QString &str)
Sets the error type to error, and the error string to errorString.
static bool fillMetaData(const QFileSystemEntry &entry, QFileSystemMetaData &data, QFileSystemMetaData::MetaDataFlags what)
double d
Definition: qnumeric_p.h:62
static QString currentPath(const QString &path=QString())
For Unix, returns the current working directory for the file engine.
const int blockSize
QString qt_error_string(int errorCode)
Definition: qglobal.cpp:2600
static bool setPermissions(const QFileSystemEntry &entry, QFile::Permissions permissions, QSystemError &error, QFileSystemMetaData *data=0)
int type
Definition: qmetatype.cpp:239
bool isLetter() const
Returns true if the character is a letter (Letter_* categories); otherwise returns false...
Definition: qchar.cpp:653
bool isRelativePath() const
Reimplemented Function
Q_DECL_CONSTEXPR const T & qMin(const T &a, const T &b)
Definition: qglobal.h:1215
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
static QString tempPath()
Returns the temporary path (i.
int remove(const Key &key)
Removes all the items that have the key from the hash.
Definition: qhash.h:784
const QChar at(int i) const
Returns the character at the given index position in the string.
Definition: qstring.h:698
bool rmdir(const QString &dirName, bool recurseParentDirectories) const
Reimplemented Function
bool copy(const QString &newName)
For windows, copy the file to file copyName.
FileFlags fileFlags(FileFlags type) const
Reimplemented Function
#define error(msg)
QString & replace(int i, int len, QChar after)
Definition: qstring.cpp:2005
int length() const
Returns the number of characters in this string.
Definition: qstring.h:696
QString & prepend(QChar c)
Definition: qstring.h:261
QString toUpper() const Q_REQUIRED_RESULT
Returns an uppercase copy of the string.
Definition: qstring.cpp:5483
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
static bool setCurrentPath(const QString &path)
Sets the current path (e.
qint64 writeFdFh(const char *data, qint64 len)
The QString class provides a Unicode character string.
Definition: qstring.h:83
static QString currentPath()
Returns the absolute path of the application&#39;s current directory.
Definition: qdir.cpp:1875
bool resize(qint64 sz)
Sets the file size (in bytes) sz.
Definition: qfile.cpp:1528
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
#define CoInitialize(x)
#define Q_D(Class)
Definition: qglobal.h:2482
bool contains(const Key &key) const
Returns true if the hash contains an item with the key; otherwise returns false.
Definition: qhash.h:872
static QString longFileName(const QString &path)
QIODevice::OpenMode openMode
#define Q_Q(Class)
Definition: qglobal.h:2483
static QFileSystemEntry currentPath()
NativePath nativeFilePath() const
bool rename(const QString &newName)
Reimplemented Function
unsigned char uchar
Definition: qglobal.h:994
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
bool flush()
Reimplemented Function
QString owner(FileOwner) const
Reimplemented Function
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static bool removeDirectory(const QFileSystemEntry &entry, bool removeEmptyParents)
static bool renameFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
QString left(int n) const Q_REQUIRED_RESULT
Returns a substring that contains the n leftmost characters of the string.
Definition: qstring.cpp:3664
int access(const char *, int)
bool setPermissions(uint perms)
Reimplemented Function
int size() const
Returns the number of characters in this string.
Definition: qstring.h:102
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
static QString homePath()
Returns the home path of the current user.
const char * name
bool caseSensitive() const
Returns true for Windows, false for Unix.
static QFileInfoList drives()
For Windows, returns the list of drives in the file system as a list of QFileInfo objects...
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
qint64 nativeRead(char *data, qint64 maxlen)
#define FALSE
Synonym for false.
Definition: qglobal.h:1019
QString fileName(FileName file) const
Reimplemented Function
QHash< uchar *, DWORD > maps
QChar toUpper() const
Returns the uppercase equivalent if the character is lowercase or titlecase; otherwise returns the ch...
Definition: qchar.cpp:1287
bool link(const QString &newName)
Creates a link from the file currently specified by fileName() to newName.
const T * ptr(const T &t)
bool hasFlags(MetaDataFlags flags) const
__int64 qint64
Definition: qglobal.h:942
void * HANDLE
Definition: qnamespace.h:1671
qint64 nativeReadLine(char *data, qint64 maxlen)
bool doStat(QFileSystemMetaData::MetaDataFlags flags) const
static QString cleanPath(const QString &path)
Removes all multiple directory separators "/" and resolves any "."s or ".."s found in the path...
Definition: qdir.cpp:2082
static QString nativeAbsoluteFilePath(const QString &path)
static QFileSystemEntry getLinkTarget(const QFileSystemEntry &link, QFileSystemMetaData &data)
QFileSystemEntry fileEntry
static bool createDirectory(const QFileSystemEntry &entry, bool createParents)
#define TRUE
Synonym for true.
Definition: qglobal.h:1018
QFileSystemMetaData metaData
static bool setCurrentPath(const QFileSystemEntry &entry)
long HRESULT
QString & append(QChar c)
Definition: qstring.cpp:1777
The QDateTime class provides date and time functions.
Definition: qdatetime.h:216
The QFile class provides an interface for reading from and writing to files.
Definition: qfile.h:65
void clearFlags(MetaDataFlags flags=AllMetaDataFlags)
int lastIndexOf(QChar c, int from=-1, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Definition: qstring.cpp:3000
static bool removeFile(const QFileSystemEntry &entry, QSystemError &error)
#define PATH_MAX
unsigned int quint32
Definition: qglobal.h:938
qint64 posFdFh() const
MetaDataFlags missingFlags(MetaDataFlags flags)
#define _O_APPEND
static QString rootPath()
Returns the root path.
bool nativeOpen(QIODevice::OpenMode openMode)
char toLatin1() const
Returns the Latin-1 character equivalent to the QChar, or 0.
Definition: qchar.h:376
qint64 readLineFdFh(char *data, qint64 maxlen)
uint ownerId(FileOwner) const
In Unix, if stat() is successful, the uid is returned if own is the owner.
QString filePath() const
qint64 nativeWrite(const char *data, qint64 len)
QDateTime fileTime(FileTime time) const
Reimplemented Function
QString toString()
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own)
static bool copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
bool remove()
Reimplemented Function
MemoryMapFlags
This enum describes special options that may be used by the map() function.
Definition: qfile.h:180
static QString fromNativeSeparators(const QString &pathName)
Returns pathName using &#39;/&#39; as file separator.
Definition: qdir.cpp:848
#define _O_RDONLY
QString & remove(int i, int len)
Removes n characters from the string, starting at the given position index, and returns a reference t...
Definition: qstring.cpp:1867
#define Q_UINT64_C(c)
Definition: qglobal.h:941
bool endsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string ends with s; otherwise returns false.
Definition: qstring.cpp:3796
The QFileInfo class provides system-independent file information.
Definition: qfileinfo.h:60
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
static QString fileName(const QString &fileUrl)
The QLatin1Char class provides an 8-bit ASCII/Latin-1 character.
Definition: qchar.h:55
#define _getdrive()
QString path() const
bool mkdir(const QString &dirName, bool createParentDirectories) const
Reimplemented Function
bool setSize(qint64 size)
Reimplemented Function
int errno
static QFileSystemEntry canonicalName(const QFileSystemEntry &entry, QFileSystemMetaData &data)
const ushort * utf16() const
Returns the QString as a &#39;\0\&#39;-terminated array of unsigned shorts.
Definition: qstring.cpp:5290
qint64 readFdFh(char *data, qint64 maxlen)
The QFSFileEngine class implements Qt&#39;s default file engine.
Definition: qfsfileengine.h:60
INT_PTR intptr_t