QFile::rename: use the open file's ID, instead of using the file name
To do that, we needed to add virtual id() in QAbstractFileEngine and override it in QFSFileEngine. It might be useful to return other types of IDs for the other file engines, but this commit does not attempt that just yet. Change-Id: I1eba2b016de74620bfc8fffd14ccafe0762b3c38 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
f9bfc8b91c
commit
ad3b41a06d
@ -677,6 +677,17 @@ bool QAbstractFileEngine::setPermissions(uint perms)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.9
|
||||
|
||||
Return an identifier that (hopefully) uniquely identifies this file in the
|
||||
system. Returns an invalid QByteArray() if that cannot be calculated.
|
||||
*/
|
||||
QByteArray QAbstractFileEngine::id() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
/*!
|
||||
Return the file engine's current file name in the format
|
||||
specified by \a file.
|
||||
|
@ -141,6 +141,7 @@ public:
|
||||
virtual QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const;
|
||||
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const;
|
||||
virtual bool setPermissions(uint perms);
|
||||
virtual QByteArray id() const;
|
||||
virtual QString fileName(FileName file=DefaultName) const;
|
||||
virtual uint ownerId(FileOwner) const;
|
||||
virtual QString owner(FileOwner) const;
|
||||
|
@ -570,7 +570,9 @@ QFile::rename(const QString &newName)
|
||||
// Note: this does not take file engines into account.
|
||||
QByteArray targetId = QFileSystemEngine::id(QFileSystemEntry(newName));
|
||||
if (!targetId.isNull()) {
|
||||
QByteArray fileId = QFileSystemEngine::id(QFileSystemEntry(d->fileName));
|
||||
QByteArray fileId = d->fileEngine ?
|
||||
d->fileEngine->id() :
|
||||
QFileSystemEngine::id(QFileSystemEntry(d->fileName));
|
||||
if (fileId != targetId || d->fileName.compare(newName, Qt::CaseInsensitive)) {
|
||||
// ### Race condition. If a file is moved in after this, it /will/ be
|
||||
// overwritten. On Unix, the proper solution is to use hardlinks:
|
||||
|
@ -92,6 +92,7 @@ public:
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
#if defined(Q_OS_UNIX)
|
||||
static bool fillMetaData(int fd, QFileSystemMetaData &data); // what = PosixStatFlags
|
||||
static QByteArray id(int fd);
|
||||
static bool setPermissions(int fd, QFile::Permissions permissions, QSystemError &error,
|
||||
QFileSystemMetaData *data = nullptr);
|
||||
#endif
|
||||
@ -104,6 +105,7 @@ public:
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
static bool fillPermissions(const QFileSystemEntry &entry, QFileSystemMetaData &data,
|
||||
QFileSystemMetaData::MetaDataFlags what);
|
||||
static QByteArray id(HANDLE fHandle);
|
||||
static QString owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own);
|
||||
static QString nativeAbsoluteFilePath(const QString &path);
|
||||
#endif
|
||||
|
@ -348,6 +348,20 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
|
||||
return result;
|
||||
}
|
||||
|
||||
//static
|
||||
QByteArray QFileSystemEngine::id(int id)
|
||||
{
|
||||
QT_STATBUF statResult;
|
||||
if (QT_FSTAT(id, &statResult)) {
|
||||
qErrnoWarning("fstat() failed for fd %d", id);
|
||||
return QByteArray();
|
||||
}
|
||||
QByteArray result = QByteArray::number(quint64(statResult.st_dev), 16);
|
||||
result += ':';
|
||||
result += QByteArray::number(quint64(statResult.st_ino));
|
||||
return result;
|
||||
}
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::resolveUserName(uint userId)
|
||||
{
|
||||
|
@ -621,13 +621,19 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
|
||||
FILE_SHARE_READ, OPEN_EXISTING, NULL);
|
||||
#endif // Q_OS_WINRT
|
||||
if (handle != INVALID_HANDLE_VALUE) {
|
||||
result = QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
|
||||
fileIdWin8(handle) : fileId(handle);
|
||||
result = id(handle);
|
||||
CloseHandle(handle);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//static
|
||||
QByteArray QFileSystemEngine::id(HANDLE fHandle)
|
||||
{
|
||||
return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8 ?
|
||||
fileIdWin8(HANDLE(fHandle)) : fileId(HANDLE(fHandle));
|
||||
}
|
||||
|
||||
//static
|
||||
QString QFileSystemEngine::owner(const QFileSystemEntry &entry, QAbstractFileEngine::FileOwner own)
|
||||
{
|
||||
|
@ -93,6 +93,7 @@ public:
|
||||
QStringList entryList(QDir::Filters filters, const QStringList &filterNames) const Q_DECL_OVERRIDE;
|
||||
FileFlags fileFlags(FileFlags type) const Q_DECL_OVERRIDE;
|
||||
bool setPermissions(uint perms) Q_DECL_OVERRIDE;
|
||||
QByteArray id() const override;
|
||||
QString fileName(FileName file) const Q_DECL_OVERRIDE;
|
||||
uint ownerId(FileOwner) const Q_DECL_OVERRIDE;
|
||||
QString owner(FileOwner) const Q_DECL_OVERRIDE;
|
||||
|
@ -596,6 +596,14 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const
|
||||
return ret;
|
||||
}
|
||||
|
||||
QByteArray QFSFileEngine::id() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
if (d->fd != -1)
|
||||
return QFileSystemEngine::id(d->fd);
|
||||
return QFileSystemEngine::id(d->fileEntry);
|
||||
}
|
||||
|
||||
QString QFSFileEngine::fileName(FileName file) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
|
@ -718,6 +718,24 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(QAbstractFileEngine::Fil
|
||||
return ret;
|
||||
}
|
||||
|
||||
QByteArray QFSFileEngine::id() const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
HANDLE h = d->fileHandle;
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
int localFd = d->fd;
|
||||
if (d->fh && d->fileEntry.isEmpty())
|
||||
localFd = QT_FILENO(d->fh);
|
||||
if (localFd != -1)
|
||||
h = HANDLE(_get_osfhandle(localFd));
|
||||
}
|
||||
if (h != INVALID_HANDLE_VALUE)
|
||||
return QFileSystemEngine::id(h);
|
||||
|
||||
// file is not open, try by path
|
||||
return QFileSystemEngine::id(d->fileEntry);
|
||||
}
|
||||
|
||||
QString QFSFileEngine::fileName(FileName file) const
|
||||
{
|
||||
Q_D(const QFSFileEngine);
|
||||
|
Loading…
Reference in New Issue
Block a user