Make sure QDir::absoluteFilePath("/dir") includes a drive on MS
QDir::isAbsolutePath(name) thinks any path starting with a slash is absolute; however, to return a valid absolute path, we need to put a drive prefix onto such a name. So use QFileSystemEntry::isAbsolute() for that check (it believes in the need for a drive, or UNC prefix) and handle the absolute-but-for-drive case when it arises. Add a regression test and make related changes to existing tests. Task-number: QTBUG-50839 Change-Id: Id5d2b2586bb1423fa2d9375a298a4bb5241cffe0 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>bb10
parent
3ae03c3585
commit
54190595ef
|
|
@ -750,13 +750,47 @@ QString QDir::filePath(const QString &fileName) const
|
|||
QString QDir::absoluteFilePath(const QString &fileName) const
|
||||
{
|
||||
const QDirPrivate* d = d_ptr.constData();
|
||||
if (isAbsolutePath(fileName))
|
||||
// Don't trust our own isAbsolutePath(); Q_OS_WIN needs a drive.
|
||||
if (QFileSystemEntry(fileName).isAbsolute())
|
||||
return fileName;
|
||||
|
||||
d->resolveAbsoluteEntry();
|
||||
const QString absoluteDirPath = d->absoluteDirEntry.filePath();
|
||||
if (fileName.isEmpty())
|
||||
return absoluteDirPath;
|
||||
#ifdef Q_OS_WIN
|
||||
// Handle the "absolute except for drive" case (i.e. \blah not c:\blah):
|
||||
int size = absoluteDirPath.length();
|
||||
if ((fileName.startsWith(QLatin1Char('/'))
|
||||
|| fileName.startsWith(QLatin1Char('\\')))
|
||||
&& size > 1) {
|
||||
// Combine absoluteDirPath's drive with fileName
|
||||
int drive = 2; // length of drive prefix
|
||||
if (Q_UNLIKELY(absoluteDirPath.at(1).unicode() != ':')) {
|
||||
// Presumably, absoluteDirPath is an UNC path; use its //server/share
|
||||
// part as "drive" - it's as sane a thing as we can do.
|
||||
for (int i = 2; i-- > 0; ) { // Scan two "path fragments":
|
||||
while (drive < size && absoluteDirPath.at(drive).unicode() == '/')
|
||||
drive++;
|
||||
if (drive >= size) {
|
||||
qWarning("Base directory starts with neither a drive nor a UNC share: %s",
|
||||
qPrintable(QDir::toNativeSeparators(absoluteDirPath)));
|
||||
return QString();
|
||||
}
|
||||
while (drive < size && absoluteDirPath.at(drive).unicode() != '/')
|
||||
drive++;
|
||||
}
|
||||
// We'll append fileName, which starts with a slash; so omit trailing slash:
|
||||
if (absoluteDirPath.at(drive).unicode() == '/')
|
||||
drive--;
|
||||
} else if (!absoluteDirPath.at(0).isLetter()) {
|
||||
qWarning("Base directory's drive is not a letter: %s",
|
||||
qPrintable(QDir::toNativeSeparators(absoluteDirPath)));
|
||||
return QString();
|
||||
}
|
||||
return absoluteDirPath.leftRef(drive) % fileName;
|
||||
}
|
||||
#endif // Q_OS_WIN
|
||||
if (!absoluteDirPath.endsWith(QLatin1Char('/')))
|
||||
return absoluteDirPath % QLatin1Char('/') % fileName;
|
||||
return absoluteDirPath % fileName;
|
||||
|
|
|
|||
|
|
@ -1384,16 +1384,22 @@ void tst_QDir::absoluteFilePath_data()
|
|||
QTest::addColumn<QString>("fileName");
|
||||
QTest::addColumn<QString>("expectedFilePath");
|
||||
|
||||
QTest::newRow("0") << "/etc" << "/passwd" << "/passwd";
|
||||
QTest::newRow("1") << "/etc" << "passwd" << "/etc/passwd";
|
||||
QTest::newRow("2") << "/" << "passwd" << "/passwd";
|
||||
QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path";
|
||||
QTest::newRow("4") << "" << "" << QDir::currentPath();
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
QTest::newRow("5") << "//machine" << "share" << "//machine/share";
|
||||
QTest::newRow("UNC") << "//machine" << "share" << "//machine/share";
|
||||
QTest::newRow("Drive") << "c:/side/town" << "/my/way/home" << "c:/my/way/home";
|
||||
#define DRIVE "Q:"
|
||||
#else
|
||||
#define DRIVE
|
||||
#endif
|
||||
|
||||
QTest::newRow("0") << DRIVE "/etc" << "/passwd" << DRIVE "/passwd";
|
||||
QTest::newRow("1") << DRIVE "/etc" << "passwd" << DRIVE "/etc/passwd";
|
||||
QTest::newRow("2") << DRIVE "/" << "passwd" << DRIVE "/passwd";
|
||||
QTest::newRow("3") << "relative" << "path" << QDir::currentPath() + "/relative/path";
|
||||
QTest::newRow("4") << "" << "" << QDir::currentPath();
|
||||
|
||||
QTest::newRow("resource") << ":/prefix" << "foo.bar" << ":/prefix/foo.bar";
|
||||
#undef DRIVE
|
||||
}
|
||||
|
||||
void tst_QDir::absoluteFilePath()
|
||||
|
|
|
|||
Loading…
Reference in New Issue