summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-06-29 12:55:54 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-07-18 15:51:35 +0000
commitad3b41a06d9ba7219c79b5548c5b11698787288d (patch)
tree557d65faed341e73d8fded4dede9ba70a1c1496e /src/corelib/io
parentf9bfc8b91cd8ea755808751ab6268e37ffd6c17a (diff)
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>
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qabstractfileengine.cpp11
-rw-r--r--src/corelib/io/qabstractfileengine_p.h1
-rw-r--r--src/corelib/io/qfile.cpp4
-rw-r--r--src/corelib/io/qfilesystemengine_p.h2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp14
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp10
-rw-r--r--src/corelib/io/qfsfileengine_p.h1
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp8
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp18
9 files changed, 66 insertions, 3 deletions
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 9606ec68e9..89727673d3 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -678,6 +678,17 @@ bool QAbstractFileEngine::setPermissions(uint perms)
}
/*!
+ \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 48b3dec324..58fa776e49 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 a840307145..f7e711a7cf 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 196ed8df69..e3e52f6eaa 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 c3906c3207..6640e2b7e7 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -349,6 +349,20 @@ QByteArray QFileSystemEngine::id(const QFileSystemEntry &entry)
}
//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)
{
#if !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && !defined(Q_OS_OPENBSD)
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 5ed2671ab4..1cb4c75699 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -621,14 +621,20 @@ 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)
{
QString name;
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 593ecc2687..ab9ad3aa6b 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 3f4f593d81..c613368a91 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 fb3cdd3981..7a010df671 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);