Fix QAbstractFileEngine::clone misuse

QFile::copy was assuming that the target file was native and therefore
it could simply take the file descriptor to clone. While that was not
currently a problem, in theory it could be as we do have one writeable
file engine besides QFSFileEngine (QWinRTFileEngine).

By refactoring to take the parameter as a QAbstractFileEngine, we can
ensure that the target file is a native file.

Change-Id: Ib7a1737987bf4c4a8c51fffd14d0c048fd509025
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
This commit is contained in:
Thiago Macieira 2017-07-12 18:41:35 -07:00
parent 284fff1217
commit 9312ec54db
6 changed files with 18 additions and 12 deletions

View File

@ -864,13 +864,14 @@ bool QAbstractFileEngine::unmap(uchar *address)
/*! /*!
\since 5.10 \since 5.10
Copies the contents from the file specified by \a sourceHandle to this file Duplicates the contents of this file (starting from the current position)
by cloning it. to the file specified by the engine \a target.
Returns \c true on success; otherwise, \c false is returned. Returns \c true on success; otherwise, \c false is returned.
*/ */
bool QAbstractFileEngine::clone(int sourceHandle) bool QAbstractFileEngine::cloneTo(QAbstractFileEngine *target)
{ {
Q_UNUSED(sourceHandle); Q_UNUSED(target);
return false; return false;
} }

View File

@ -150,7 +150,7 @@ public:
virtual QDateTime fileTime(FileTime time) const; virtual QDateTime fileTime(FileTime time) const;
virtual void setFileName(const QString &file); virtual void setFileName(const QString &file);
virtual int handle() const; virtual int handle() const;
virtual bool clone(int sourceHandle); virtual bool cloneTo(QAbstractFileEngine *target);
bool atEnd() const; bool atEnd() const;
uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags); uchar *map(qint64 offset, qint64 size, QFile::MemoryMapFlags flags);
bool unmap(uchar *ptr); bool unmap(uchar *ptr);

View File

@ -804,7 +804,7 @@ QFile::copy(const QString &newName)
close(); close();
d->setError(QFile::CopyError, tr("Cannot open for output")); d->setError(QFile::CopyError, tr("Cannot open for output"));
} else { } else {
if (!out.d_func()->engine()->clone(d->engine()->handle())) { if (!d->engine()->cloneTo(out.d_func()->engine())) {
char block[4096]; char block[4096];
qint64 totalRead = 0; qint64 totalRead = 0;
while (!atEnd()) { while (!atEnd()) {

View File

@ -110,7 +110,7 @@ public:
qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 read(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE; qint64 readLine(char *data, qint64 maxlen) Q_DECL_OVERRIDE;
qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE; qint64 write(const char *data, qint64 len) Q_DECL_OVERRIDE;
bool clone(int sourceHandle) override; bool cloneTo(QAbstractFileEngine *target) override;
bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) Q_DECL_OVERRIDE; bool extension(Extension extension, const ExtensionOption *option = 0, ExtensionReturn *output = 0) Q_DECL_OVERRIDE;
bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE; bool supportsExtension(Extension extension) const Q_DECL_OVERRIDE;

View File

@ -735,16 +735,19 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
/*! /*!
\reimp \reimp
*/ */
bool QFSFileEngine::clone(int sourceHandle) bool QFSFileEngine::cloneTo(QAbstractFileEngine *target)
{ {
if ((target->fileFlags(LocalDiskFlag) & LocalDiskFlag) == 0)
return false;
#if defined(Q_OS_LINUX) #if defined(Q_OS_LINUX)
Q_D(QFSFileEngine); Q_D(QFSFileEngine);
# if !defined FICLONE # if !defined FICLONE
# define FICLONE _IOW (0x94, 9, int) # define FICLONE _IOW (0x94, 9, int)
# endif # endif
return ::ioctl(d->fd, FICLONE, sourceHandle) == 0; int srcfd = d->nativeHandle();
int dstfd = target->handle();
return ::ioctl(dstfd, FICLONE, srcfd) == 0;
#else #else
Q_UNUSED(sourceHandle);
return false; return false;
#endif #endif
} }

View File

@ -1032,9 +1032,11 @@ bool QFSFileEnginePrivate::unmap(uchar *ptr)
/*! /*!
\reimp \reimp
*/ */
bool QFSFileEngine::clone(int sourceHandle) bool QFSFileEngine::cloneTo(QAbstractFileEngine *target)
{ {
Q_UNUSED(sourceHandle); // There's some Windows Server 2016 API, but we won't
// bother with it.
Q_UNUSED(target);
return false; return false;
} }