QFileSystemEngine::fillMetaData: simplify and comment the code
Took me a long while to understand what it did. Now that I do, I can also answer the question left behind during the original implementation in Qt 4.8 (commit 4fd2aced96d9095254d89f9da9c911bd88f15245 in the old history): how to know if a file exists? Change-Id: I8d96dea9955d4c749b99fffd14cdae135499a0d3 Reviewed-by: Lars Knoll <lars.knoll@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
12339481ea
commit
04f4d87bda
@ -698,43 +698,62 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
}
|
}
|
||||||
#endif // defined(Q_OS_DARWIN)
|
#endif // defined(Q_OS_DARWIN)
|
||||||
|
|
||||||
|
// if we're asking for any of the stat(2) flags, then we're getting them all
|
||||||
if (what & QFileSystemMetaData::PosixStatFlags)
|
if (what & QFileSystemMetaData::PosixStatFlags)
|
||||||
what |= QFileSystemMetaData::PosixStatFlags;
|
what |= QFileSystemMetaData::PosixStatFlags;
|
||||||
|
|
||||||
if (what & QFileSystemMetaData::ExistsAttribute) {
|
|
||||||
// FIXME: Would other queries being performed provide this bit?
|
|
||||||
what |= QFileSystemMetaData::PosixStatFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
data.entryFlags &= ~what;
|
data.entryFlags &= ~what;
|
||||||
|
|
||||||
const QByteArray nativeFilePath = entry.nativeFilePath();
|
const QByteArray nativeFilePath = entry.nativeFilePath();
|
||||||
bool entryExists = true; // innocent until proven otherwise
|
bool entryExists = true; // innocent until proven otherwise
|
||||||
|
|
||||||
|
// first, we may try lstat(2). Possible outcomes:
|
||||||
|
// - success and is a symlink: filesystem entry exists, but we need stat(2)
|
||||||
|
// -> statBufferValid = false
|
||||||
|
// - success and is not a symlink: filesystem entry exists and we're done
|
||||||
|
// -> statBufferValid = true
|
||||||
|
// - failure: really non-existent filesystem entry
|
||||||
|
// -> entryExists = false; statBufferValid = true
|
||||||
|
// both stat(2) and lstat(2) may generate a number of different errno
|
||||||
|
// conditions, but of those, the only ones that could happen and the
|
||||||
|
// entry still exist are EACCES, EFAULT, ENOMEM and EOVERFLOW. If we get
|
||||||
|
// EACCES or ENOMEM, then we have no choice on how to proceed, so we may
|
||||||
|
// as well conclude it doesn't exist; EFAULT can't happen and EOVERFLOW
|
||||||
|
// shouldn't happen because we build in _LARGEFIE64.
|
||||||
QT_STATBUF statBuffer;
|
QT_STATBUF statBuffer;
|
||||||
bool statBufferValid = false;
|
bool statBufferValid = false;
|
||||||
if (what & QFileSystemMetaData::LinkType) {
|
if (what & QFileSystemMetaData::LinkType) {
|
||||||
if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) {
|
if (QT_LSTAT(nativeFilePath, &statBuffer) == 0) {
|
||||||
if (S_ISLNK(statBuffer.st_mode)) {
|
if (S_ISLNK(statBuffer.st_mode)) {
|
||||||
|
// it's a symlink, we don't know if the file "exists"
|
||||||
data.entryFlags |= QFileSystemMetaData::LinkType;
|
data.entryFlags |= QFileSystemMetaData::LinkType;
|
||||||
} else {
|
} else {
|
||||||
|
// it's a reagular file and it exists
|
||||||
statBufferValid = true;
|
statBufferValid = true;
|
||||||
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
data.fillFromStatBuf(statBuffer);
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags
|
||||||
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
|
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
// it doesn't exist
|
||||||
entryExists = false;
|
entryExists = false;
|
||||||
|
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::LinkType;
|
data.knownFlagsMask |= QFileSystemMetaData::LinkType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// second, we try a regular stat(2)
|
||||||
if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) {
|
if (statBufferValid || (what & QFileSystemMetaData::PosixStatFlags)) {
|
||||||
if (entryExists && !statBufferValid)
|
if (entryExists && !statBufferValid) {
|
||||||
statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0);
|
statBufferValid = (QT_STAT(nativeFilePath, &statBuffer) == 0);
|
||||||
|
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||||
|
if (statBufferValid)
|
||||||
|
data.fillFromStatBuf(statBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
if (statBufferValid)
|
if (!statBufferValid) {
|
||||||
data.fillFromStatBuf(statBuffer);
|
|
||||||
else {
|
|
||||||
entryExists = false;
|
entryExists = false;
|
||||||
data.birthTime_ = 0;
|
data.birthTime_ = 0;
|
||||||
data.metadataChangeTime_ = 0;
|
data.metadataChangeTime_ = 0;
|
||||||
@ -750,34 +769,49 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
| QFileSystemMetaData::ExistsAttribute;
|
| QFileSystemMetaData::ExistsAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// third, we try access(2)
|
||||||
|
if (what & (QFileSystemMetaData::UserPermissions | QFileSystemMetaData::ExistsAttribute)) {
|
||||||
|
// calculate user permissions
|
||||||
|
auto checkAccess = [&](QFileSystemMetaData::MetaDataFlag flag, int mode) {
|
||||||
|
if (!entryExists || (what & flag) == 0)
|
||||||
|
return;
|
||||||
|
if (QT_ACCESS(nativeFilePath, mode) == 0) {
|
||||||
|
// access ok (and file exists)
|
||||||
|
data.entryFlags |= flag | QFileSystemMetaData::ExistsAttribute;
|
||||||
|
} else if (errno != EACCES && errno != EROFS) {
|
||||||
|
entryExists = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
checkAccess(QFileSystemMetaData::UserReadPermission, R_OK);
|
||||||
|
checkAccess(QFileSystemMetaData::UserWritePermission, W_OK);
|
||||||
|
checkAccess(QFileSystemMetaData::UserExecutePermission, X_OK);
|
||||||
|
|
||||||
|
// if we still haven't found out if the file exists, try F_OK
|
||||||
|
if (entryExists && (data.entryFlags & QFileSystemMetaData::ExistsAttribute) == 0) {
|
||||||
|
entryExists = QT_ACCESS(nativeFilePath, F_OK) == 0;
|
||||||
|
if (entryExists)
|
||||||
|
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
|
data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions) |
|
||||||
|
QFileSystemMetaData::ExistsAttribute;
|
||||||
|
}
|
||||||
|
|
||||||
#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 (entryExists && hasResourcePropertyFlag(data, entry, kCFURLIsAliasFileKey))
|
||||||
data.entryFlags |= QFileSystemMetaData::AliasType;
|
data.entryFlags |= QFileSystemMetaData::AliasType;
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
data.knownFlagsMask |= QFileSystemMetaData::AliasType;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (what & QFileSystemMetaData::UserPermissions) {
|
if (what & QFileSystemMetaData::BundleType) {
|
||||||
// calculate user permissions
|
if (entryExists && isPackage(data, entry))
|
||||||
|
data.entryFlags |= QFileSystemMetaData::BundleType;
|
||||||
|
|
||||||
if (entryExists) {
|
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
|
||||||
if (what & QFileSystemMetaData::UserReadPermission) {
|
|
||||||
if (QT_ACCESS(nativeFilePath, R_OK) == 0)
|
|
||||||
data.entryFlags |= QFileSystemMetaData::UserReadPermission;
|
|
||||||
}
|
|
||||||
if (what & QFileSystemMetaData::UserWritePermission) {
|
|
||||||
if (QT_ACCESS(nativeFilePath, W_OK) == 0)
|
|
||||||
data.entryFlags |= QFileSystemMetaData::UserWritePermission;
|
|
||||||
}
|
|
||||||
if (what & QFileSystemMetaData::UserExecutePermission) {
|
|
||||||
if (QT_ACCESS(nativeFilePath, X_OK) == 0)
|
|
||||||
data.entryFlags |= QFileSystemMetaData::UserExecutePermission;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.knownFlagsMask |= (what & QFileSystemMetaData::UserPermissions);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (what & QFileSystemMetaData::HiddenAttribute
|
if (what & QFileSystemMetaData::HiddenAttribute
|
||||||
&& !data.isHidden()) {
|
&& !data.isHidden()) {
|
||||||
@ -791,15 +825,8 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
|
|||||||
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
data.knownFlagsMask |= QFileSystemMetaData::HiddenAttribute;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_DARWIN)
|
|
||||||
if (what & QFileSystemMetaData::BundleType) {
|
|
||||||
if (entryExists && isPackage(data, entry))
|
|
||||||
data.entryFlags |= QFileSystemMetaData::BundleType;
|
|
||||||
|
|
||||||
data.knownFlagsMask |= QFileSystemMetaData::BundleType;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!entryExists) {
|
if (!entryExists) {
|
||||||
|
what &= ~QFileSystemMetaData::LinkType; // don't clear link: could be broken symlink
|
||||||
data.clearFlags(what);
|
data.clearFlags(what);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user