summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-08-27 08:08:21 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-08-27 08:08:21 (GMT)
commit88a41bd9d0ff69dbf5695644643967ddc9b34ddf (patch)
tree07a782bb162aeba9776d3d2a2737a032e349af0d /src/corelib/io
parente2c2e7e7fb3bee99260dc5b7bfab42c9217c18c8 (diff)
parent7b45a4cbf7593c8d7a837d826d9827fee243c46c (diff)
downloadQt-88a41bd9d0ff69dbf5695644643967ddc9b34ddf.zip
Qt-88a41bd9d0ff69dbf5695644643967ddc9b34ddf.tar.gz
Qt-88a41bd9d0ff69dbf5695644643967ddc9b34ddf.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/qt-earth-staging into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/qt-earth-staging: (21 commits) Revert "Don't second-guess the "engine"; call cleanPath on absolutePaths" Revert "In 4.7 QFileInfo::absolute(File)Path returned clean paths" In 4.7 QFileInfo::absolute(File)Path returned clean paths ret is an "internal" path, no need to re-process it We prefer capitalized drive letters, make it so sooner Don't second-guess the "engine"; call cleanPath on absolutePaths Compare non-canonical paths before falling back on expensive computation Fix QDir::operator==(const QDir &) const Off-by-one error in assert condition... Leftovers from 401722ef9e6fe79bd41f9d5f79668f5c4997c8e6 Merged fileTemplate test with QTBUG_4796 Cleanup code: removing empty stubs Fix QTemporaryFile regressions and new found issues Use "native paths" on POSIX platforms as well Cleanup #includes Add output on test failure Atomic implementation of create file and obtain handle for Win/Symbian Minimize encoding conversions when generating unique file name Use QStringBuilder when copying template for modification Make Symbian follow Windows code in temporary path generation ...
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qdir.cpp10
-rw-r--r--src/corelib/io/qfileinfo.cpp6
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp7
-rw-r--r--src/corelib/io/qtemporaryfile.cpp230
4 files changed, 166 insertions, 87 deletions
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index f9196e0..c0c62e1 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -1633,9 +1633,13 @@ bool QDir::operator==(const QDir &dir) const
if (d->filters == other->filters
&& d->sort == other->sort
&& d->nameFilters == other->nameFilters) {
- d->resolveAbsoluteEntry();
- other->resolveAbsoluteEntry();
- return d->absoluteDirEntry.filePath().compare(other->absoluteDirEntry.filePath(), sensitive) == 0;
+
+ // Assume directories are the same if path is the same
+ if (d->dirEntry.filePath() == other->dirEntry.filePath())
+ return true;
+
+ // Fallback to expensive canonical path computation
+ return canonicalPath().compare(dir.canonicalPath(), sensitive) == 0;
}
return false;
}
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index ca42c87..ff328da 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -391,6 +391,11 @@ bool QFileInfo::operator==(const QFileInfo &fileinfo) const
return true;
if (d->isDefaultConstructed || fileinfo.d_ptr->isDefaultConstructed)
return false;
+
+ // Assume files are the same if path is the same
+ if (d->fileEntry.filePath() == fileinfo.d_ptr->fileEntry.filePath())
+ return true;
+
Qt::CaseSensitivity sensitive;
if (d->fileEngine == 0 || fileinfo.d_ptr->fileEngine == 0) {
if (d->fileEngine != fileinfo.d_ptr->fileEngine) // one is native, the other is a custom file-engine
@@ -406,6 +411,7 @@ bool QFileInfo::operator==(const QFileInfo &fileinfo) const
if (fileinfo.size() != size()) //if the size isn't the same...
return false;
+ // Fallback to expensive canonical path computation
return canonicalFilePath().compare(fileinfo.canonicalFilePath(), sensitive) == 0;
}
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index f704fc3..764ee6d 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -536,7 +536,7 @@ QFileSystemEntry QFileSystemEngine::absoluteName(const QFileSystemEntry &entry)
// Force uppercase drive letters.
ret[0] = ret.at(0).toUpper();
}
- return QFileSystemEntry(ret);
+ return QFileSystemEntry(ret, QFileSystemEntry::FromInternalPath());
}
//static
@@ -1052,11 +1052,12 @@ QString QFileSystemEngine::tempPath()
}
if (ret.isEmpty()) {
#if !defined(Q_OS_WINCE)
- ret = QLatin1String("c:/tmp");
+ ret = QLatin1String("C:/tmp");
#else
ret = QLatin1String("/Temp");
#endif
- }
+ } else if (ret.length() >= 2 && ret[1] == QLatin1Char(':'))
+ ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
return ret;
}
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index d457601..e80a8b6 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -44,17 +44,18 @@
#ifndef QT_NO_TEMPORARYFILE
#include "qplatformdefs.h"
-#include "qabstractfileengine.h"
#include "private/qfile_p.h"
-#include "private/qabstractfileengine_p.h"
#include "private/qfsfileengine_p.h"
+#include "private/qsystemerror_p.h"
+#include "private/qfilesystemengine_p.h"
-#if !defined(Q_OS_WINCE)
-# include <errno.h>
+#if defined(Q_OS_SYMBIAN)
+#include "private/qcore_symbian_p.h"
#endif
-#if defined(Q_OS_UNIX)
-# include "private/qcore_unix_p.h" // overrides QT_OPEN
+#if !defined(Q_OS_WIN) && !defined(Q_OS_SYMBIAN)
+#include "private/qcore_unix_p.h" // overrides QT_OPEN
+#include <errno.h>
#endif
#if defined(QT_BUILD_CORE_LIB)
@@ -63,6 +64,30 @@
QT_BEGIN_NAMESPACE
+#if defined(Q_OS_WIN) || defined(Q_OS_SYMBIAN)
+typedef ushort Char;
+
+static inline Char Latin1Char(char ch)
+{
+ return ushort(uchar(ch));
+}
+
+# ifdef Q_OS_WIN
+typedef HANDLE NativeFileHandle;
+# else // Q_OS_SYMBIAN
+# ifdef SYMBIAN_ENABLE_64_BIT_FILE_SERVER_API
+typedef RFile64 NativeFileHandle;
+# else
+typedef RFile NativeFileHandle;
+# endif
+# endif
+
+#else // POSIX
+typedef char Char;
+typedef char Latin1Char;
+typedef int NativeFileHandle;
+#endif
+
/*
* Copyright (c) 1987, 1993
* The Regents of the University of California. All rights reserved.
@@ -96,27 +121,33 @@ QT_BEGIN_NAMESPACE
\internal
Generates a unique file path and returns a native handle to the open file.
- \a path is used as a template when generating unique paths,
- \a placeholderStart and \a placeholderEnd delimit the sub-string that will
- be randomized.
+ \a path is used as a template when generating unique paths, \a pos
+ identifies the position of the first character that will be replaced in the
+ template and \a length the number of characters that may be substituted.
Returns an open handle to the newly created file if successful, an invalid
handle otherwise. In both cases, the string in \a path will be changed and
contain the generated path name.
*/
-static int createFileFromTemplate(char *const path,
- char *const placeholderStart, char *const placeholderEnd)
+static bool createFileFromTemplate(NativeFileHandle &file,
+ QFileSystemEntry::NativePath &path, size_t pos, size_t length,
+ QSystemError &error)
{
- Q_ASSERT(placeholderEnd > placeholderStart);
+ Q_ASSERT(length != 0);
+ Q_ASSERT(pos < size_t(path.length()));
+ Q_ASSERT(length <= size_t(path.length()) - pos);
+
+ Char *const placeholderStart = (Char *)path.data() + pos;
+ Char *const placeholderEnd = placeholderStart + length;
// Initialize placeholder with random chars + PID.
{
- char *rIter = placeholderEnd;
+ Char *rIter = placeholderEnd;
#if defined(QT_BUILD_CORE_LIB)
quint64 pid = quint64(QCoreApplication::applicationPid());
do {
- *--rIter = (pid % 10) + '0';
+ *--rIter = Latin1Char((pid % 10) + '0');
pid /= 10;
} while (rIter != placeholderStart && pid != 0);
#endif
@@ -124,48 +155,82 @@ static int createFileFromTemplate(char *const path,
while (rIter != placeholderStart) {
char ch = char((qrand() & 0xffff) % (26 + 26));
if (ch < 26)
- *--rIter = ch + 'A';
+ *--rIter = Latin1Char(ch + 'A');
else
- *--rIter = ch - 26 + 'a';
+ *--rIter = Latin1Char(ch - 26 + 'a');
}
}
+#ifdef Q_OS_SYMBIAN
+ RFs& fs = qt_s60GetRFs();
+#endif
+
for (;;) {
// Atomically create file and obtain handle
-#ifndef Q_OS_WIN
- {
- int fd = QT_OPEN(path, QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE, 0600);
- if (fd != -1)
- return fd;
- if (errno != EEXIST)
- return -1;
+#if defined(Q_OS_WIN)
+ file = CreateFile((const wchar_t *)path.constData(),
+ GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL, NULL);
+
+ if (file != INVALID_HANDLE_VALUE)
+ return true;
+
+ DWORD err = GetLastError();
+ if (err != ERROR_FILE_EXISTS) {
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+ }
+#elif defined(Q_OS_SYMBIAN)
+ TInt err = file.Create(fs, qt_QString2TPtrC(path),
+ EFileRead | EFileWrite | EFileShareReadersOrWriters);
+
+ if (err == KErrNone)
+ return true;
+
+ if (err != KErrAlreadyExists) {
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+ }
+#else // POSIX
+ file = QT_OPEN(path.constData(),
+ QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
+ 0600);
+
+ if (file != -1)
+ return true;
+
+ int err = errno;
+ if (err != EEXIST) {
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
}
-#else
- if (!QFileInfo(QString::fromLocal8Bit(path)).exists())
- return 1;
#endif
/* tricky little algorwwithm for backward compatibility */
- for (char *iter = placeholderStart;;) {
+ for (Char *iter = placeholderStart;;) {
// Character progression: [0-9] => 'a' ... 'z' => 'A' .. 'Z'
// String progression: "ZZaiC" => "aabiC"
- switch (*iter) {
+ switch (char(*iter)) {
case 'Z':
// Rollover, advance next character
- *iter = 'a';
- if (++iter == placeholderEnd)
- return -1;
+ *iter = Latin1Char('a');
+ if (++iter == placeholderEnd) {
+ // Out of alternatives. Return file exists error, previously set.
+ error = QSystemError(err, QSystemError::NativeError);
+ return false;
+ }
continue;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
- *iter = 'a';
+ *iter = Latin1Char('a');
break;
case 'z':
// increment 'z' to 'A'
- *iter = 'A';
+ *iter = Latin1Char('A');
break;
default:
@@ -257,7 +322,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
QString qfilename = d->fileEntry.filePath();
- // Find placeholder string.
+ // Ensure there is a placeholder mask
uint phPos = qfilename.length();
uint phLength = 0;
@@ -269,70 +334,73 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
continue;
}
- if (qfilename[phPos] == QLatin1Char('/')
- || phLength >= 6) {
+ if (phLength >= 6
+ || qfilename[phPos] == QLatin1Char('/')) {
++phPos;
break;
}
+ // start over
phLength = 0;
}
- QStringRef prefix, suffix;
- if (phLength < 6) {
- qfilename += QLatin1Char('.');
- prefix = QStringRef(&qfilename);
- phLength = 6;
- } else {
- prefix = qfilename.leftRef(phPos);
- suffix = qfilename.midRef(phPos + phLength);
- }
+ if (phLength < 6)
+ qfilename.append(QLatin1String(".XXXXXX"));
+
+ // "Nativify" :-)
+ QFileSystemEntry::NativePath filename = QFileSystemEngine::absoluteName(
+ QFileSystemEntry(qfilename, QFileSystemEntry::FromInternalPath()))
+ .nativeFilePath();
- QByteArray filename = prefix.toLocal8Bit();
+ // Find mask in native path
phPos = filename.length();
- if (suffix.isEmpty())
- filename.resize(phPos + phLength);
- else
- filename.insert(phPos + phLength, suffix.toLocal8Bit());
-
- char *path = filename.data();
-
-#ifndef Q_OS_WIN
- int fd = createFileFromTemplate(path, path + phPos, path + phPos + phLength);
- if (fd != -1) {
- // First open the fd as an external file descriptor to
- // initialize the engine properly.
- if (QFSFileEngine::open(openMode, fd)) {
-
- // Allow the engine to close the handle even if it's "external".
- d->closeFileHandle = true;
-
- // Restore the file names (open() resets them).
- d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(path, filename.length())); //note that filename is NOT a native path
- filePathIsTemplate = false;
- return true;
+ phLength = 0;
+ while (phPos != 0) {
+ --phPos;
+
+ if (filename[phPos] == Latin1Char('X')) {
+ ++phLength;
+ continue;
}
- QT_CLOSE(fd);
- }
- setError(errno == EMFILE ? QFile::ResourceError : QFile::OpenError, qt_error_string(errno));
- return false;
-#else
- if (createFileFromTemplate(path, path + phPos, path + phPos + phLength) == -1) {
- return false;
+ if (phLength >= 6) {
+ ++phPos;
+ break;
+ }
+
+ // start over
+ phLength = 0;
}
- QString template_ = d->fileEntry.filePath();
- d->fileEntry = QFileSystemEntry(QString::fromLocal8Bit(path, filename.length()));
+ Q_ASSERT(phLength >= 6);
- if (QFSFileEngine::open(openMode)) {
- filePathIsTemplate = false;
- return true;
+ QSystemError error;
+#if defined(Q_OS_WIN)
+ NativeFileHandle &file = d->fileHandle;
+#elif defined(Q_OS_SYMBIAN)
+ NativeFileHandle &file = d->symbianFile;
+#else // POSIX
+ NativeFileHandle &file = d->fd;
+#endif
+
+ if (!createFileFromTemplate(file, filename, phPos, phLength, error)) {
+ setError(QFile::OpenError, error.toString());
+ return false;
}
- d->fileEntry = QFileSystemEntry(template_, QFileSystemEntry::FromInternalPath());
- return false;
+ d->fileEntry = QFileSystemEntry(filename, QFileSystemEntry::FromNativePath());
+
+#if !defined(Q_OS_WIN)
+ d->closeFileHandle = true;
#endif
+
+ filePathIsTemplate = false;
+
+ d->openMode = openMode;
+ d->lastFlushFailed = false;
+ d->tried_stat = 0;
+
+ return true;
}
bool QTemporaryFileEngine::remove()