summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/io/qfsfileengine.cpp2
-rw-r--r--src/corelib/io/qfsfileengine_p.h4
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp26
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp236
-rw-r--r--src/corelib/plugin/qlibrary.cpp29
-rw-r--r--tests/auto/qfileinfo/tst_qfileinfo.cpp64
6 files changed, 249 insertions, 112 deletions
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 3d109d1..1ca19cf 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -109,7 +109,7 @@ void QFSFileEnginePrivate::init()
{
is_sequential = 0;
tried_stat = 0;
-#ifdef Q_OS_UNIX
+#if !defined(Q_OS_WINCE)
need_lstat = 1;
is_link = 0;
#endif
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 15cbf5c..b245dca 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -137,10 +137,11 @@ public:
mutable uint is_sequential : 2;
mutable uint could_stat : 1;
mutable uint tried_stat : 1;
-#ifdef Q_OS_UNIX
+#if !defined(Q_OS_WINCE)
mutable uint need_lstat : 1;
mutable uint is_link : 1;
#endif
+
bool doStat() const;
bool isSymlink() const;
@@ -161,7 +162,6 @@ protected:
#if defined(Q_OS_WIN32) || defined(Q_OS_WINCE)
QAbstractFileEngine::FileFlags getPermissions() const;
- QString getLink() const;
#endif
};
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 3bc2616..7a815fe 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -594,21 +594,21 @@ QString QFSFileEngine::homePath()
QString QFSFileEngine::rootPath()
{
#if defined(Q_OS_SYMBIAN)
- return QString::fromLatin1("C:/");
+ return QLatin1String("C:/");
#else
- return QString::fromLatin1("/");
+ return QLatin1String("/");
#endif
}
QString QFSFileEngine::tempPath()
{
#ifdef Q_OS_SYMBIAN
- QString temp = QDir::currentPath().left(2);
- temp += QString::fromLatin1( "/system/temp/");
+ QString temp = QDir::currentPath().left(2);
+ temp += QLatin1String("/system/temp/");
#else
- QString temp = QFile::decodeName(qgetenv("TMPDIR"));
- if (temp.isEmpty())
- temp = QString::fromLatin1("/tmp/");
+ QString temp = QFile::decodeName(qgetenv("TMPDIR"));
+ if (temp.isEmpty())
+ temp = QLatin1String("/tmp/");
#endif
return temp;
}
@@ -631,7 +631,7 @@ QFileInfoList QFSFileEngine::drives()
qWarning("QDir::drives: Getting drives failed");
}
#else
- ret.append(rootPath());
+ ret.append(QFileInfo(rootPath()));
#endif
return ret;
}
@@ -778,11 +778,11 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
else if (exists && (d->st.st_mode & S_IFMT) == S_IFDIR)
ret |= DirectoryType;
#if !defined(QWS) && defined(Q_OS_MAC)
- if((ret & DirectoryType) && (type & BundleType)) {
+ if ((ret & DirectoryType) && (type & BundleType)) {
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(d->filePath),
kCFURLPOSIXPathStyle, true);
UInt32 type, creator;
- if(CFBundleGetPackageInfoInDirectory(url, &type, &creator))
+ if (CFBundleGetPackageInfoInDirectory(url, &type, &creator))
ret |= BundleType;
}
#endif
@@ -943,9 +943,9 @@ QString QFSFileEngine::fileName(FileName file) const
#if !defined(QWS) && defined(Q_OS_MAC)
QCFType<CFURLRef> url = CFURLCreateWithFileSystemPath(0, QCFString(d->filePath),
kCFURLPOSIXPathStyle, true);
- if(CFDictionaryRef dict = CFBundleCopyInfoDictionaryForURL(url)) {
- if(CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) {
- if(CFGetTypeID(name) == CFStringGetTypeID())
+ if (CFDictionaryRef dict = CFBundleCopyInfoDictionaryForURL(url)) {
+ if (CFTypeRef name = (CFTypeRef)CFDictionaryGetValue(dict, kCFBundleNameKey)) {
+ if (CFGetTypeID(name) == CFStringGetTypeID())
return QCFString::toQString((CFStringRef)name);
}
}
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index afe7b35..f1f69e7 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -55,6 +55,7 @@
#if !defined(Q_OS_WINCE)
# include <sys/types.h>
# include <direct.h>
+# include <winioctl.h>
#else
# include <types.h>
#endif
@@ -88,6 +89,37 @@ typedef INT_PTR intptr_t;
# define INVALID_FILE_ATTRIBUTES (DWORD (-1))
#endif
+#if !defined(REPARSE_DATA_BUFFER_HEADER_SIZE) && !defined(Q_OS_WINCE)
+typedef struct _REPARSE_DATA_BUFFER {
+ ULONG ReparseTag;
+ USHORT ReparseDataLength;
+ USHORT Reserved;
+ union {
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ ULONG Flags;
+ WCHAR PathBuffer[1];
+ } SymbolicLinkReparseBuffer;
+ struct {
+ USHORT SubstituteNameOffset;
+ USHORT SubstituteNameLength;
+ USHORT PrintNameOffset;
+ USHORT PrintNameLength;
+ WCHAR PathBuffer[1];
+ } MountPointReparseBuffer;
+ struct {
+ UCHAR DataBuffer[1];
+ } GenericReparseBuffer;
+ };
+} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
+
+# define REPARSE_DATA_BUFFER_HEADER_SIZE FIELD_OFFSET(REPARSE_DATA_BUFFER, GenericReparseBuffer)
+# define MAXIMUM_REPARSE_DATA_BUFFER_SIZE 16384
+#endif
+
QT_BEGIN_NAMESPACE
static QString readLink(const QString &link);
@@ -122,7 +154,7 @@ QT_END_INCLUDE_NAMESPACE
void QFSFileEnginePrivate::resolveLibs()
{
static bool triedResolve = false;
- if(!triedResolve) {
+ if (!triedResolve) {
// need to resolve the security info functions
// protect initialization
@@ -130,7 +162,7 @@ void QFSFileEnginePrivate::resolveLibs()
QMutexLocker locker(QMutexPool::globalInstanceGet(&triedResolve));
// check triedResolve again, since another thread may have already
// done the initialization
- if(triedResolve) {
+ if (triedResolve) {
// another thread did initialize the security function pointers,
// so we shouldn't do it again.
return;
@@ -219,7 +251,7 @@ bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringL
if (resolveUNCLibs()) {
SHARE_INFO_1 *BufPtr, *p;
DWORD res;
- DWORD er=0,tr=0,resume=0, i;
+ DWORD er = 0, tr = 0, resume = 0, i;
do {
res = ptrNetShareEnum((wchar_t*)server.utf16(), 1, (LPBYTE *)&BufPtr, DWORD(-1), &er, &tr, &resume);
if (res == ERROR_SUCCESS || res == ERROR_MORE_DATA) {
@@ -231,7 +263,7 @@ bool QFSFileEnginePrivate::uncListSharesOnServer(const QString &server, QStringL
}
}
ptrNetApiBufferFree(BufPtr);
- } while (res==ERROR_MORE_DATA);
+ } while (res == ERROR_MORE_DATA);
return res == ERROR_SUCCESS;
}
return false;
@@ -893,7 +925,7 @@ bool QFSFileEngine::mkdir(const QString &name, bool createParentDirectories) con
for (int slash=0; slash != -1; oldslash = slash) {
slash = dirName.indexOf(QDir::separator(), oldslash+1);
if (slash == -1) {
- if(oldslash == dirName.length())
+ if (oldslash == dirName.length())
break;
slash = dirName.length();
}
@@ -948,8 +980,8 @@ bool QFSFileEngine::setCurrentPath(const QString &path)
#if !defined(Q_OS_WINCE)
return ::SetCurrentDirectory((wchar_t*)path.utf16()) != 0;
#else
- qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path);
- return true;
+ qfsPrivateCurrentDir = QFSFileEnginePrivate::longFileName(path);
+ return true;
#endif
}
@@ -987,9 +1019,9 @@ QString QFSFileEngine::currentPath(const QString &fileName)
ret[0] = ret.at(0).toUpper(); // Force uppercase drive letters.
return QDir::fromNativeSeparators(ret);
#else
- Q_UNUSED(fileName);
- if (qfsPrivateCurrentDir.isEmpty())
- qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
+ Q_UNUSED(fileName);
+ if (qfsPrivateCurrentDir.isEmpty())
+ qfsPrivateCurrentDir = QCoreApplication::applicationDirPath();
return QDir::fromNativeSeparators(qfsPrivateCurrentDir);
#endif
@@ -1021,15 +1053,15 @@ QString QFSFileEngine::homePath()
}
}
#endif
- if(ret.isEmpty() || !QFile::exists(ret)) {
+ if (ret.isEmpty() || !QFile::exists(ret)) {
ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData());
- if(ret.isEmpty() || !QFile::exists(ret)) {
+ if (ret.isEmpty() || !QFile::exists(ret)) {
ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData()) + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData());
- if(ret.isEmpty() || !QFile::exists(ret)) {
+ if (ret.isEmpty() || !QFile::exists(ret)) {
ret = QString::fromLocal8Bit(qgetenv("HOME").constData());
- if(ret.isEmpty() || !QFile::exists(ret)) {
+ if (ret.isEmpty() || !QFile::exists(ret)) {
#if defined(Q_OS_WINCE)
- ret = QString::fromLatin1("\\My Documents");
+ ret = QLatin1String("\\My Documents");
if (!QFile::exists(ret))
#endif
ret = rootPath();
@@ -1043,12 +1075,12 @@ QString QFSFileEngine::homePath()
QString QFSFileEngine::rootPath()
{
#if defined(Q_OS_WINCE)
- QString ret = QString::fromLatin1("/");
+ QString ret = QLatin1String("/");
#elif defined(Q_FS_FAT)
QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData());
- if(ret.isEmpty())
+ if (ret.isEmpty())
ret = QLatin1String("c:");
- ret += QLatin1Char('/');
+ ret.append(QLatin1Char('/'));
#elif defined(Q_OS_OS2EMX)
char dir[4];
_abspath(dir, QLatin1String("/"), _MAX_PATH);
@@ -1059,20 +1091,23 @@ QString QFSFileEngine::rootPath()
QString QFSFileEngine::tempPath()
{
- wchar_t tempPath[MAX_PATH];
- int success = GetTempPath(MAX_PATH, tempPath);
- QString ret = QString::fromWCharArray(tempPath);
-
- if (ret.isEmpty() || !success) {
+ QString ret;
+ {
+ wchar_t tempPath[MAX_PATH];
+ if (GetTempPath(MAX_PATH, tempPath))
+ ret = QString::fromWCharArray(tempPath);
+ if (!ret.isEmpty()) {
+ while (ret.endsWith(QLatin1Char('\\')))
+ ret.chop(1);
+ ret = QDir::fromNativeSeparators(ret);
+ }
+ }
+ if (ret.isEmpty()) {
#if !defined(Q_OS_WINCE)
- ret = QString::fromLatin1("c:/tmp");
+ ret = QLatin1String("c:/tmp");
#else
- ret = QString::fromLatin1("\\Temp");
+ ret = QLatin1String("/Temp");
#endif
- } else {
- ret = QDir::fromNativeSeparators(ret);
- while (ret.at(ret.length()-1) == QLatin1Char('/'))
- ret = ret.left(ret.length()-1);
}
return ret;
}
@@ -1085,21 +1120,21 @@ QFileInfoList QFSFileEngine::drives()
quint32 driveBits = (quint32) GetLogicalDrives() & 0x3ffffff;
#elif defined(Q_OS_OS2EMX)
quint32 driveBits, cur;
- if(DosQueryCurrentDisk(&cur,&driveBits) != NO_ERROR)
+ if (DosQueryCurrentDisk(&cur, &driveBits) != NO_ERROR)
exit(1);
driveBits &= 0x3ffffff;
#endif
char driveName[] = "A:/";
- while(driveBits) {
- if(driveBits & 1)
- ret.append(QString::fromLatin1(driveName));
+ while (driveBits) {
+ if (driveBits & 1)
+ ret.append(QFileInfo(QLatin1String(driveName)));
driveName[0]++;
driveBits = driveBits >> 1;
}
return ret;
#else
- ret.append(QString::fromLatin1("/"));
+ ret.append(QFileInfo(QLatin1String("/")));
return ret;
#endif
}
@@ -1112,10 +1147,11 @@ bool QFSFileEnginePrivate::doStat() const
if (filePath.isEmpty())
return could_stat;
+
QString fname = filePath.endsWith(QLatin1String(".lnk")) ? readLink(filePath) : filePath;
fname = fixIfRelativeUncPath(fname);
- UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
+ UINT oldmode = SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX);
if (fd != -1) {
#if !defined(Q_OS_WINCE)
@@ -1204,12 +1240,51 @@ bool QFSFileEnginePrivate::doStat() const
#endif
}
}
+
SetErrorMode(oldmode);
}
return could_stat;
}
+static QString readSymLink(const QString &link)
+{
+ QString result;
+#if !defined(Q_OS_WINCE)
+ HANDLE handle = CreateFile((wchar_t*)QFSFileEnginePrivate::longFileName(link).utf16(),
+ FILE_READ_EA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ 0,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
+ 0);
+ if (handle != INVALID_HANDLE_VALUE) {
+ DWORD bufsize = MAXIMUM_REPARSE_DATA_BUFFER_SIZE;
+ REPARSE_DATA_BUFFER *rdb = (REPARSE_DATA_BUFFER*)qMalloc(bufsize);
+ DWORD retsize = 0;
+ if (::DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, 0, 0, rdb, bufsize, &retsize, 0)) {
+ if (rdb->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
+ int length = rdb->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
+ int offset = rdb->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
+ const wchar_t* PathBuffer = &rdb->MountPointReparseBuffer.PathBuffer[offset];
+ result = QString::fromWCharArray(PathBuffer, length);
+ } else {
+ int length = rdb->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
+ int offset = rdb->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
+ const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
+ result = QString::fromWCharArray(PathBuffer, length);
+ }
+ // cut-off "//?/" and "/??/"
+ if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
+ result = result.mid(4);
+ }
+ qFree(rdb);
+ CloseHandle(handle);
+ }
+#endif // Q_OS_WINCE
+ return result;
+}
+
static QString readLink(const QString &link)
{
#if !defined(Q_OS_WINCE)
@@ -1233,11 +1308,11 @@ static QString readLink(const QString &link)
if (SUCCEEDED(hres)) { // Get pointer to the IPersistFile interface.
IPersistFile *ppf;
hres = psl->QueryInterface(IID_IPersistFile, (LPVOID *)&ppf);
- if(SUCCEEDED(hres)) {
+ if (SUCCEEDED(hres)) {
hres = ppf->Load((LPOLESTR)link.utf16(), STGM_READ);
//The original path of the link is retrieved. If the file/folder
//was moved, the return value still have the old path.
- if(SUCCEEDED(hres)) {
+ if (SUCCEEDED(hres)) {
if (psl->GetPath(szGotPath, MAX_PATH, &wfd, SLGP_UNCPRIORITY) == NOERROR)
ret = QString::fromWCharArray(szGotPath);
}
@@ -1267,14 +1342,6 @@ static QString readLink(const QString &link)
#endif // Q_OS_WINCE
}
-/*!
- \internal
-*/
-QString QFSFileEnginePrivate::getLink() const
-{
- return readLink(filePath);
-}
-
bool QFSFileEngine::link(const QString &newName)
{
#if !defined(Q_OS_WINCE)
@@ -1315,8 +1382,8 @@ bool QFSFileEngine::link(const QString &newName)
if (!ret)
setError(QFile::RenameError, qt_error_string());
- if(neededCoInit)
- CoUninitialize();
+ if (neededCoInit)
+ CoUninitialize();
return ret;
#else
@@ -1440,6 +1507,41 @@ QAbstractFileEngine::FileFlags QFSFileEnginePrivate::getPermissions() const
}
/*!
+ \internal
+*/
+bool QFSFileEnginePrivate::isSymlink() const
+{
+#if !defined(Q_OS_WINCE)
+ if (need_lstat) {
+ need_lstat = false;
+ is_link = false;
+
+ if (fileAttrib & FILE_ATTRIBUTE_REPARSE_POINT) {
+ QString path = QDir::toNativeSeparators(filePath);
+ // path for the FindFirstFile should not end with a trailing slash
+ while (path.endsWith(QLatin1Char('\\')))
+ path.chop(1);
+
+ WIN32_FIND_DATA findData;
+ HANDLE hFind = ::FindFirstFile((wchar_t*)QFSFileEnginePrivate::longFileName(path).utf16(),
+ &findData);
+ if (hFind != INVALID_HANDLE_VALUE) {
+ ::FindClose(hFind);
+ if ((findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
+ && (findData.dwReserved0 == IO_REPARSE_TAG_MOUNT_POINT
+ || findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK)) {
+ is_link = true;
+ }
+ }
+ }
+ }
+ return is_link;
+#else
+ return false;
+#endif // Q_OS_WINCE
+}
+
+/*!
\reimp
*/
QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::FileFlags type) const
@@ -1449,6 +1551,9 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
// Force a stat, so that we're guaranteed to get up-to-date results
if (type & Refresh) {
d->tried_stat = 0;
+#if !defined(Q_OS_WINCE)
+ d->need_lstat = 1;
+#endif
}
if (type & PermsMask) {
@@ -1472,7 +1577,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
ret |= FileType;
}
} else if (d->doStat()) {
- if (d->fileAttrib & FILE_ATTRIBUTE_REPARSE_POINT)
+ if ((type & LinkType) && d->isSymlink())
ret |= LinkType;
if (d->fileAttrib & FILE_ATTRIBUTE_DIRECTORY) {
ret |= DirectoryType;
@@ -1500,32 +1605,32 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
QString QFSFileEngine::fileName(FileName file) const
{
Q_D(const QFSFileEngine);
- if(file == BaseName) {
+ if (file == BaseName) {
int slash = d->filePath.lastIndexOf(QLatin1Char('/'));
- if(slash == -1) {
+ if (slash == -1) {
int colon = d->filePath.lastIndexOf(QLatin1Char(':'));
- if(colon != -1)
+ if (colon != -1)
return d->filePath.mid(colon + 1);
return d->filePath;
}
return d->filePath.mid(slash + 1);
- } else if(file == PathName) {
- if(!d->filePath.size())
+ } else if (file == PathName) {
+ if (!d->filePath.size())
return d->filePath;
int slash = d->filePath.lastIndexOf(QLatin1Char('/'));
- if(slash == -1) {
- if(d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
+ if (slash == -1) {
+ if (d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
return d->filePath.left(2);
return QString(QLatin1Char('.'));
} else {
- if(!slash)
+ if (!slash)
return QString(QLatin1Char('/'));
- if(slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
+ if (slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
slash++;
return d->filePath.left(slash);
}
- } else if(file == AbsoluteName || file == AbsolutePathName) {
+ } else if (file == AbsoluteName || file == AbsolutePathName) {
QString ret;
if (!isRelativePath()) {
@@ -1539,7 +1644,7 @@ QString QFSFileEngine::fileName(FileName file) const
ret = d->filePath;
}
#else
- ret = d->filePath;
+ ret = d->filePath;
#endif
} else {
ret = QDir::cleanPath(QDir::currentPath() + QLatin1Char('/') + d->filePath);
@@ -1568,7 +1673,7 @@ QString QFSFileEngine::fileName(FileName file) const
return ret.left(slash > 0 ? slash : 1);
}
return ret;
- } else if(file == CanonicalName || file == CanonicalPathName) {
+ } else if (file == CanonicalName || file == CanonicalPathName) {
if (!(fileFlags(ExistsFlag) & ExistsFlag))
return QString();
@@ -1582,9 +1687,14 @@ QString QFSFileEngine::fileName(FileName file) const
ret = ret.left(slash);
}
return ret;
- } else if(file == LinkName) {
- return QDir::fromNativeSeparators(d->getLink());
- } else if(file == BundleName) {
+ } else if (file == LinkName) {
+ QString ret;
+ if (d->filePath.endsWith(QLatin1String(".lnk")))
+ ret = readLink(d->filePath);
+ else if (d->doStat() && d->isSymlink())
+ ret = readSymLink(d->filePath);
+ return QDir::fromNativeSeparators(ret);
+ } else if (file == BundleName) {
return QString();
}
return d->filePath;
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index 3a5bb55..5cf6513 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -421,7 +421,23 @@ static bool qt_unix_query(const QString &library, uint *version, bool *debug, QB
#endif // Q_OS_UNIX && !Q_OS_MAC && !defined(Q_OS_SYMBIAN) && !defined(QT_NO_PLUGIN_CHECK)
typedef QMap<QString, QLibraryPrivate*> LibraryMap;
-Q_GLOBAL_STATIC(LibraryMap, libraryMap)
+
+struct LibraryData {
+ LibraryData() : settings(0) { }
+ ~LibraryData() {
+ delete settings;
+ }
+
+ QSettings *settings;
+ LibraryMap libraryMap;
+};
+
+Q_GLOBAL_STATIC(LibraryData, libraryData)
+
+static LibraryMap *libraryMap()
+{
+ return &(libraryData()->libraryMap);
+}
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version)
:pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), qt_version(0),
@@ -614,10 +630,12 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
.arg(fileName);
QStringList reg;
#ifndef QT_NO_SETTINGS
- QScopedPointer<QSettings> madeSettings;
if (!settings) {
- settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
- madeSettings.reset(settings);
+ settings = libraryData()->settings;
+ if (!settings) {
+ settings = new QSettings(QSettings::UserScope, QLatin1String("Trolltech"));
+ libraryData()->settings = settings;
+ }
}
reg = settings->value(regkey).toStringList();
#endif
@@ -709,9 +727,6 @@ bool QLibraryPrivate::isPlugin(QSettings *settings)
settings->setValue(regkey, queried);
#endif
}
-#ifndef QT_NO_SETTINGS
- madeSettings.reset();
-#endif
if (!success) {
if (errorString.isEmpty()){
diff --git a/tests/auto/qfileinfo/tst_qfileinfo.cpp b/tests/auto/qfileinfo/tst_qfileinfo.cpp
index 9184def..fb150e5 100644
--- a/tests/auto/qfileinfo/tst_qfileinfo.cpp
+++ b/tests/auto/qfileinfo/tst_qfileinfo.cpp
@@ -142,6 +142,7 @@ private slots:
void fileTimes();
void fileTimes_oldFile();
+ void isSymLink_data();
void isSymLink();
void isHidden_data();
@@ -169,6 +170,10 @@ private slots:
void notEqualOperator() const;
};
+tst_QFileInfo::tst_QFileInfo()
+{
+}
+
tst_QFileInfo::~tst_QFileInfo()
{
QFile::remove("brokenlink.lnk");
@@ -241,12 +246,6 @@ void tst_QFileInfo::copy()
QVERIFY(privateInfo->data != privateInfo3->data);
QVERIFY(privateInfo2->data != privateInfo3->data);
QCOMPARE(privateInfo->data, privateInfo2->data);
-
-
-}
-
-tst_QFileInfo::tst_QFileInfo()
-{
}
void tst_QFileInfo::isFile_data()
@@ -532,7 +531,6 @@ void tst_QFileInfo::canonicalFilePath()
}
# endif
#endif
-
}
void tst_QFileInfo::fileName_data()
@@ -732,7 +730,6 @@ void tst_QFileInfo::permission_data()
QTest::newRow("resource1") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ReadUser) << true;
QTest::newRow("resource2") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::WriteUser) << false;
QTest::newRow("resource3") << ":/tst_qfileinfo/resources/file1.ext1" << int(QFile::ExeUser) << false;
-
}
void tst_QFileInfo::permission()
@@ -799,8 +796,8 @@ void tst_QFileInfo::compare_data()
#else
<< false;
#endif
-
}
+
void tst_QFileInfo::compare()
{
QFETCH(QString, file1);
@@ -973,31 +970,46 @@ void tst_QFileInfo::fileTimes_oldFile()
#endif
}
-void tst_QFileInfo::isSymLink()
+void tst_QFileInfo::isSymLink_data()
{
QFile::remove("link.lnk");
QFile::remove("brokenlink.lnk");
QFile::remove("dummyfile");
- QFileInfo info1("tst_qfileinfo.cpp");
- QVERIFY( !info1.isSymLink() );
+ QFile file1("tst_qfileinfo.cpp");
+ QVERIFY(file1.link("link.lnk"));
- QFile file2("tst_qfileinfo.cpp");
- if (file2.link("link.lnk")) {
- QFileInfo info2("link.lnk");
- QVERIFY( info2.isSymLink() );
- }
+ QFile file2("dummyfile");
+ file2.open(QIODevice::WriteOnly);
+ QVERIFY(file2.link("brokenlink.lnk"));
+ file2.remove();
- QFile file3("dummyfile");
- file3.open(QIODevice::WriteOnly);
- if (file3.link("brokenlink.lnk")) {
- // In Symbian ARMV5 builds, this will panic with KERN-EXEC 3 inside OpenC fclose() call
- // in QFSFileEnginePrivate::closeFdFh(), if "dummyfile" exists prior calling to isSymLink
- // and is not deleted at the beginning of isSymLink.
- file3.remove();
- QFileInfo info3("brokenlink.lnk");
- QVERIFY( info3.isSymLink() );
+ QTest::addColumn<QString>("path");
+ QTest::addColumn<bool>("isSymLink");
+ QTest::addColumn<QString>("linkTarget");
+
+ QTest::newRow("existent file") << "tst_qfileinfo.cpp" << false << "";
+ QTest::newRow("link") << "link.lnk" << true << QFileInfo("tst_qfileinfo.cpp").absoluteFilePath();
+ QTest::newRow("broken link") << "brokenlink.lnk" << true << QFileInfo("dummyfile").absoluteFilePath();
+
+#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+ if (QSysInfo::WindowsVersion & QSysInfo::WV_VISTA) {
+ QTest::newRow("Documents and Settings") << "C:/Documents and Settings" << true << "C:/Users";
+ QTest::newRow("All Users") << "C:/Users/All Users" << true << "C:/ProgramData";
+ QTest::newRow("Default User") << "C:/Users/Default User" << true << "C:/Users/Default";
}
+#endif
+}
+
+void tst_QFileInfo::isSymLink()
+{
+ QFETCH(QString, path);
+ QFETCH(bool, isSymLink);
+ QFETCH(QString, linkTarget);
+
+ QFileInfo fi(path);
+ QCOMPARE(fi.isSymLink(), isSymLink);
+ QCOMPARE(fi.symLinkTarget(), linkTarget);
}
void tst_QFileInfo::isHidden_data()