diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp index 9606ec68e9c..89727673d31 100644 --- a/src/corelib/io/qabstractfileengine.cpp +++ b/src/corelib/io/qabstractfileengine.cpp @@ -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. diff --git a/src/corelib/io/qabstractfileengine_p.h b/src/corelib/io/qabstractfileengine_p.h index 48b3dec3249..58fa776e49a 100644 --- a/src/corelib/io/qabstractfileengine_p.h +++ b/src/corelib/io/qabstractfileengine_p.h @@ -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; diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp index a8403071452..f7e711a7cf7 100644 --- a/src/corelib/io/qfile.cpp +++ b/src/corelib/io/qfile.cpp @@ -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: diff --git a/src/corelib/io/qfilesystemengine_p.h b/src/corelib/io/qfilesystemengine_p.h index 196ed8df698..e3e52f6eaad 100644 --- a/src/corelib/io/qfilesystemengine_p.h +++ b/src/corelib/io/qfilesystemengine_p.h @@ -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 diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp index c3906c3207e..6640e2b7e72 100644 --- a/src/corelib/io/qfilesystemengine_unix.cpp +++ b/src/corelib/io/qfilesystemengine_unix.cpp @@ -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) { diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp index 5ed2671ab4e..1cb4c756999 100644 --- a/src/corelib/io/qfilesystemengine_win.cpp +++ b/src/corelib/io/qfilesystemengine_win.cpp @@ -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) { diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h index 593ecc26871..ab9ad3aa6b7 100644 --- a/src/corelib/io/qfsfileengine_p.h +++ b/src/corelib/io/qfsfileengine_p.h @@ -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; diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index 3f4f593d811..c613368a91f 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -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); diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp index fb3cdd39818..7a010df671b 100644 --- a/src/corelib/io/qfsfileengine_win.cpp +++ b/src/corelib/io/qfsfileengine_win.cpp @@ -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);