QFileSystemEngine/Linux: fix when qt_lstatx() succeeds
When qt_lstatx() succeeds and the target is not a link, we'd erroneously mark the file as non-existent during the pass to check qt_statx(). All flags besides the file's modes were cleared. This is unit-tested, but only happens on Linux kernels 4.12 or later. It didn't happen to me because I already had this fix applied as part of a later change relating to QSystemResult. Task-number: QTBUG-64514 Change-Id: I938b024e38bf4aac9154fffd14f893506a1ef55b Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
parent
3c7a6a7a58
commit
4ee85ff7c5
@ -918,7 +918,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
data.entryFlags &= ~what;
|
data.entryFlags &= ~what;
|
||||||
|
|
||||||
const QByteArray nativeFilePath = entry.nativeFilePath();
|
const QByteArray nativeFilePath = entry.nativeFilePath();
|
||||||
bool entryExists = true; // innocent until proven otherwise
|
int entryErrno = 0; // innocent until proven otherwise
|
||||||
|
|
||||||
// first, we may try lstat(2). Possible outcomes:
|
// first, we may try lstat(2). Possible outcomes:
|
||||||
// - success and is a symlink: filesystem entry exists, but we need stat(2)
|
// - success and is a symlink: filesystem entry exists, but we need stat(2)
|
||||||
@ -968,7 +968,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// it doesn't exist
|
// it doesn't exist
|
||||||
entryExists = false;
|
entryErrno = errno;
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -976,8 +976,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
}
|
}
|
||||||
|
|
||||||
// second, we try a regular stat(2)
|
// second, we try a regular stat(2)
|
||||||
if (statResult != 0 && (what & QFileSystemMetaData::PosixStatFlags)) {
|
if (statResult == -1 && (what & QFileSystemMetaData::PosixStatFlags)) {
|
||||||
if (entryExists && statResult == -1) {
|
if (entryErrno == 0 && statResult == -1) {
|
||||||
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||||
statResult = qt_statx(nativeFilePath, &statxBuffer);
|
statResult = qt_statx(nativeFilePath, &statxBuffer);
|
||||||
if (statResult == -ENOSYS) {
|
if (statResult == -ENOSYS) {
|
||||||
@ -991,7 +991,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (statResult != 0) {
|
if (statResult != 0) {
|
||||||
entryExists = false;
|
entryErrno = errno;
|
||||||
data.birthTime_ = 0;
|
data.birthTime_ = 0;
|
||||||
data.metadataChangeTime_ = 0;
|
data.metadataChangeTime_ = 0;
|
||||||
data.modificationTime_ = 0;
|
data.modificationTime_ = 0;
|
||||||
@ -1010,13 +1010,13 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
if (what & (QFileSystemMetaData::UserPermissions | QFileSystemMetaData::ExistsAttribute)) {
|
if (what & (QFileSystemMetaData::UserPermissions | QFileSystemMetaData::ExistsAttribute)) {
|
||||||
// calculate user permissions
|
// calculate user permissions
|
||||||
auto checkAccess = [&](QFileSystemMetaData::MetaDataFlag flag, int mode) {
|
auto checkAccess = [&](QFileSystemMetaData::MetaDataFlag flag, int mode) {
|
||||||
if (!entryExists || (what & flag) == 0)
|
if (entryErrno != 0 || (what & flag) == 0)
|
||||||
return;
|
return;
|
||||||
if (QT_ACCESS(nativeFilePath, mode) == 0) {
|
if (QT_ACCESS(nativeFilePath, mode) == 0) {
|
||||||
// access ok (and file exists)
|
// access ok (and file exists)
|
||||||
data.entryFlags |= flag | QFileSystemMetaData::ExistsAttribute;
|
data.entryFlags |= flag | QFileSystemMetaData::ExistsAttribute;
|
||||||
} else if (errno != EACCES && errno != EROFS) {
|
} else if (errno != EACCES && errno != EROFS) {
|
||||||
entryExists = false;
|
entryErrno = errno;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1025,9 +1025,10 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
checkAccess(QFileSystemMetaData::UserExecutePermission, X_OK);
|
checkAccess(QFileSystemMetaData::UserExecutePermission, X_OK);
|
||||||
|
|
||||||
// if we still haven't found out if the file exists, try F_OK
|
// if we still haven't found out if the file exists, try F_OK
|
||||||
if (entryExists && (data.entryFlags & QFileSystemMetaData::ExistsAttribute) == 0) {
|
if (entryErrno == 0 && (data.entryFlags & QFileSystemMetaData::ExistsAttribute) == 0) {
|
||||||
entryExists = QT_ACCESS(nativeFilePath, F_OK) == 0;
|
if (QT_ACCESS(nativeFilePath, F_OK) == -1)
|
||||||
if (entryExists)
|
entryErrno = errno;
|
||||||
|
else
|
||||||
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1037,13 +1038,13 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
|
|
||||||
#if defined(Q_OS_DARWIN)
|
#if defined(Q_OS_DARWIN)
|
||||||
if (what & QFileSystemMetaData::AliasType) {
|
if (what & QFileSystemMetaData::AliasType) {
|
||||||
if (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
|
if (entryErrno == 0 && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
|
||||||
data.entryFlags |= QFileSystemMetaData::AliasType;
|
data.entryFlags |= QFileSystemMetaData::AliasType;
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (what & QFileSystemMetaData::BundleType) {
|
if (what & QFileSystemMetaData::BundleType) {
|
||||||
if (entryExists && isPackage(data, entry))
|
if (entryErrno == 0 && isPackage(data, entry))
|
||||||
data.entryFlags |= QFileSystemMetaData::BundleType;
|
data.entryFlags |= QFileSystemMetaData::BundleType;
|
||||||
|
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
|
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
|
||||||
@ -1055,19 +1056,19 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
QString fileName = entry.fileName();
|
QString fileName = entry.fileName();
|
||||||
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
|
if ((fileName.size() > 0 && fileName.at(0) == QLatin1Char('.'))
|
||||||
#if defined(Q_OS_DARWIN)
|
#if defined(Q_OS_DARWIN)
|
||||||
|| (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsHiddenKey))
|
|| (entryErrno == 0 && hasResourcePropertyFlag(data, entry, kCFURLIsHiddenKey))
|
||||||
#endif
|
#endif
|
||||||
)
|
)
|
||||||
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
data.entryFlags |= QFileSystemMetaData::HiddenAttribute;
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entryExists) {
|
if (entryErrno != 0) {
|
||||||
what &= ~QFileSystemMetaData::LinkType; // don't clear link: could be broken symlink
|
what &= ~QFileSystemMetaData::LinkType; // don't clear link: could be broken symlink
|
||||||
data.clearFlags(what);
|
data.clearFlags(what);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return data.hasFlags(what);
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
Loading…
x
Reference in New Issue
Block a user