qWarning("QFile::copy: Empty or null file name");
return false;
}
- if (QFile(newName).exists()) {
- // ### Race condition. If a file is moved in after this, it /will/ be
- // overwritten. On Unix, the proper solution is to use hardlinks:
- // return ::link(old, new) && ::remove(old); See also rename().
- d->setError(QFile::CopyError, tr("Destination file exists"));
- return false;
- }
+
unsetError();
close();
- if(error() == QFile::NoError) {
- if(fileEngine()->copy(newName)) {
- unsetError();
- return true;
- } else {
- bool error = false;
- if(!open(QFile::ReadOnly)) {
- error = true;
- d->setError(QFile::CopyError, tr("Cannot open %1 for input").arg(d->fileName));
- } else {
- QString fileTemplate = QLatin1String("%1/qt_temp.XXXXXX");
-#ifdef QT_NO_TEMPORARYFILE
- QFile out(fileTemplate.arg(QFileInfo(newName).path()));
- if (!out.open(QIODevice::ReadWrite))
- error = true;
-#else
- QTemporaryFile out(fileTemplate.arg(QFileInfo(newName).path()));
- if (!out.open()) {
- out.setFileTemplate(fileTemplate.arg(QDir::tempPath()));
- if (!out.open())
- error = true;
- }
-#endif
- if (error) {
- out.close();
- close();
- d->setError(QFile::CopyError, tr("Cannot open for output"));
- } else {
- char block[4096];
- qint64 totalRead = 0;
- while(!atEnd()) {
- qint64 in = read(block, sizeof(block));
- if (in <= 0)
- break;
- totalRead += in;
- if(in != out.write(block, in)) {
- close();
- d->setError(QFile::CopyError, tr("Failure to write block"));
- error = true;
- break;
- }
- }
-
- if (totalRead != size()) {
- // Unable to read from the source. The error string is
- // already set from read().
- error = true;
- }
- if (!error && !out.rename(newName)) {
- error = true;
- close();
- d->setError(QFile::CopyError, tr("Cannot create %1 for output").arg(newName));
- }
-#ifdef QT_NO_TEMPORARYFILE
- if (error)
- out.remove();
-#else
- if (!error)
- out.setAutoRemove(false);
-#endif
- }
- }
- if(!error) {
- QFile::setPermissions(newName, permissions());
- close();
- unsetError();
- return true;
- }
- }
+ if(error() == QFile::NoError && fileEngine()->copy(newName)) {
+ unsetError();
+ return true;
}
return false;
}
#include "qfsfileengine.h"
#include "qfile.h"
#include "qfileinfo.h"
+#include "qcore_unix_p.h"
#include <stdlib.h> // for realpath()
#include <unistd.h>
//static
bool QFileSystemEngine::copyFile(const QFileSystemEntry &source, const QFileSystemEntry &target, QSystemError &error)
{
-#ifdef Q_OS_LINUX
-
-// not in qplatformdefs.h since it is Linux specific
-#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
-# define QT_SENDFILE ::sendfile64
-#else
-# define QT_SENDFILE ::sendfile
-#endif
-
QT_STATBUF st;
if (QT_STAT(source.nativeFilePath().constData(), &st) == 0) {
if (!S_ISREG(st.st_mode))
return false;
}
- QT_OFF_T tosend = st.st_size;
- ssize_t sendresult = QT_SENDFILE(targetfd, sourcefd, Q_NULLPTR, tosend);
- while (sendresult != tosend) {
+ QT_OFF_T tocopy = st.st_size;
+
+#ifdef Q_OS_LINUX
+// not in qplatformdefs.h since it is platform specific
+#if defined(QT_USE_XOPEN_LFS_EXTENSIONS) && defined(QT_LARGEFILE_SUPPORT)
+# define QT_SENDFILE ::sendfile64
+#else
+# define QT_SENDFILE ::sendfile
+#endif
+
+ ssize_t sendresult = QT_SENDFILE(targetfd, sourcefd, Q_NULLPTR, tocopy);
+ while (sendresult != tocopy) {
if (sendresult == -1) {
error = QSystemError(errno, QSystemError::StandardLibraryError);
::close(sourcefd);
::close(targetfd);
return false;
}
- tosend -= sendresult;
- sendresult = QT_SENDFILE(targetfd, sourcefd, &tosend, tosend);
+ tocopy -= sendresult;
+ sendresult = QT_SENDFILE(targetfd, sourcefd, &tocopy, tocopy);
}
+#undef QT_SENDFILE
+// TODO: FreeBSD sendfile() support, signature is different
+#else
+ size_t totalwrite = 0;
+ char copybuffer[BUFSIZ]; // BUFSIZ is defined in stdio.h
+ while (QT_OFF_T(totalwrite) != tocopy) {
+ const size_t readresult = QT_READ(sourcefd, copybuffer, sizeof(copybuffer));
+ if (readresult == -1) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ ::close(sourcefd);
+ ::close(targetfd);
+ return false;
+ }
+
+ const size_t writeresult = QT_WRITE(targetfd, copybuffer, readresult);
+ if (writeresult != readresult) {
+ error = QSystemError(errno, QSystemError::StandardLibraryError);
+ ::close(sourcefd);
+ ::close(targetfd);
+ return false;
+ }
+
+ totalwrite += readresult;
+ }
+#endif
::close(sourcefd);
::close(targetfd);
return true;
-
-#undef QT_SENDFILE
-
-#else
- Q_UNUSED(source);
- Q_UNUSED(target);
- error = QSystemError(ENOSYS, QSystemError::StandardLibraryError); //Function not implemented
- return false;
-#endif // Q_OS_LINUX
}
//static