QFileSystemEngine: a file only exists if its link count is not 0

QFileSystemMetaData::fillFromStatBuf is used when filling in the results
from both stat() as well as fstat(). Obviously the file exists if it was
stat()ed but not necessarily so by fstat(): we could be operating on a
file descriptor referring to an unlinked file or an O_TMPFILE.

Change-Id: I8d96dea9955d4c749b99fffd14cd52a8c8dd9ca1
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
bb10
Thiago Macieira 2017-07-01 14:38:55 -07:00
parent a639a4cc07
commit cb9b42b493
5 changed files with 21 additions and 6 deletions

View File

@ -421,7 +421,7 @@ QFile::exists() const
Q_D(const QFile);
// 0x1000000 = QAbstractFileEngine::Refresh, forcing an update
return (d->engine()->fileFlags(QAbstractFileEngine::FlagsMask
| QAbstractFileEngine::FileFlag(0x1000000)) & QAbstractFileEngine::ExistsFlag);
| QAbstractFileEngine::Refresh) & QAbstractFileEngine::ExistsFlag);
}
/*!

View File

@ -281,7 +281,9 @@ void QFileSystemMetaData::fillFromStatBuf(const QT_STATBUF &statBuffer)
entryFlags |= QFileSystemMetaData::SequentialType;
// Attributes
entryFlags |= QFileSystemMetaData::ExistsAttribute;
entryFlags |= QFileSystemMetaData::ExistsAttribute; // inode exists
if (statBuffer.st_nlink == 0)
entryFlags |= QFileSystemMetaData::WasDeletedAttribute;
size_ = statBuffer.st_size;
#if defined(Q_OS_DARWIN)
if (statBuffer.st_flags & UF_HIDDEN) {

View File

@ -120,9 +120,14 @@ public:
// Attributes
HiddenAttribute = 0x00100000,
SizeAttribute = 0x00200000, // Note: overlaps with QAbstractFileEngine::LocalDiskFlag
ExistsAttribute = 0x00400000,
ExistsAttribute = 0x00400000, // For historical reasons, indicates existence of data, not the file
#if defined(Q_OS_WIN)
WasDeletedAttribute = 0x0,
#else
WasDeletedAttribute = 0x40000000, // Indicates the file was deleted
#endif
Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute,
Attributes = HiddenAttribute | SizeAttribute | ExistsAttribute | WasDeletedAttribute,
// Times
CreationTime = 0x01000000, // Note: overlaps with QAbstractFileEngine::Refresh
@ -144,6 +149,7 @@ public:
| QFileSystemMetaData::DirectoryType
| QFileSystemMetaData::SequentialType
| QFileSystemMetaData::SizeAttribute
| QFileSystemMetaData::WasDeletedAttribute
| QFileSystemMetaData::Times
| QFileSystemMetaData::OwnerIds,
@ -191,6 +197,7 @@ public:
bool isLegacyLink() const { return (entryFlags & LegacyLinkType); }
bool isSequential() const { return (entryFlags & SequentialType); }
bool isHidden() const { return (entryFlags & HiddenAttribute); }
bool wasDeleted() const { return (entryFlags & WasDeletedAttribute); }
#if defined(Q_OS_WIN)
bool isLnkFile() const { return (entryFlags & WinLnkType); }
#else

View File

@ -495,11 +495,14 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
| QFileSystemMetaData::LinkType
| QFileSystemMetaData::FileType
| QFileSystemMetaData::DirectoryType
| QFileSystemMetaData::BundleType;
| QFileSystemMetaData::BundleType
| QFileSystemMetaData::WasDeletedAttribute;
if (type & FlagsMask)
queryFlags |= QFileSystemMetaData::HiddenAttribute
| QFileSystemMetaData::ExistsAttribute;
else if (type & ExistsFlag)
queryFlags |= QFileSystemMetaData::WasDeletedAttribute;
queryFlags |= QFileSystemMetaData::LinkType;
@ -531,7 +534,8 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
}
if (type & FlagsMask) {
if (exists)
// the inode existing does not mean the file exists
if (!d->metaData.wasDeleted())
ret |= ExistsFlag;
if (d->fileEntry.isRoot())
ret |= RootFlag;

View File

@ -741,6 +741,8 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
}
if (type & FlagsMask) {
if (d->metaData.exists()) {
// if we succeeded in querying, then the file exists: a file on
// Windows cannot be deleted if we have an open handle to it
ret |= ExistsFlag;
if (d->fileEntry.isRoot())
ret |= RootFlag;