From 531018e58defef5221b3824dfda338b9595e0f2c Mon Sep 17 00:00:00 2001 From: Felix Geyer Date: Wed, 22 Jul 2015 17:01:12 +0200 Subject: [PATCH] Remove QSaveFile and QLockFile. They are part of Qt >= 5.1. --- src/CMakeLists.txt | 15 -- src/core/qlockfile.cpp | 344 -------------------------- src/core/qlockfile.h | 79 ------ src/core/qlockfile_p.h | 101 -------- src/core/qlockfile_unix.cpp | 244 ------------------ src/core/qlockfile_win.cpp | 227 ----------------- src/core/qsavefile.cpp | 452 ---------------------------------- src/core/qsavefile.h | 105 -------- src/core/qsavefile_p.h | 71 ------ src/gui/DatabaseTabWidget.cpp | 3 +- src/gui/DatabaseTabWidget.h | 2 +- tests/CMakeLists.txt | 3 - tests/TestQSaveFile.cpp | 204 --------------- tests/TestQSaveFile.h | 39 --- 14 files changed, 3 insertions(+), 1886 deletions(-) delete mode 100644 src/core/qlockfile.cpp delete mode 100644 src/core/qlockfile.h delete mode 100644 src/core/qlockfile_p.h delete mode 100644 src/core/qlockfile_unix.cpp delete mode 100644 src/core/qlockfile_win.cpp delete mode 100644 src/core/qsavefile.cpp delete mode 100644 src/core/qsavefile.h delete mode 100644 src/core/qsavefile_p.h delete mode 100644 tests/TestQSaveFile.cpp delete mode 100644 tests/TestQSaveFile.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0baed8fa4..083c36047 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -54,9 +54,6 @@ set(keepassx_SOURCES core/ListDeleter.h core/Metadata.cpp core/PasswordGenerator.cpp - core/qlockfile.cpp - core/qsavefile.cpp - core/qsavefile_p.h core/SignalMultiplexer.cpp core/TimeDelta.cpp core/TimeInfo.cpp @@ -143,18 +140,6 @@ if(NOT GCRYPT_HAS_SALSA20) ) endif() -if(UNIX) - set(keepassx_SOURCES - ${keepassx_SOURCES} - core/qlockfile_unix.cpp - ) -elseif(MINGW) - set(keepassx_SOURCES - ${keepassx_SOURCES} - core/qlockfile_win.cpp - ) -endif() - set(keepassx_SOURCES_MAINEXE main.cpp ) diff --git a/src/core/qlockfile.cpp b/src/core/qlockfile.cpp deleted file mode 100644 index 567440c15..000000000 --- a/src/core/qlockfile.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qlockfile.h" -#include "qlockfile_p.h" -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) -# include -#else -# include -#endif -#include - -QT_BEGIN_NAMESPACE - -/*! - \class QLockFile - \inmodule QtCore - \brief The QLockFile class provides locking between processes using a file. - \since 5.1 - - A lock file can be used to prevent multiple processes from accessing concurrently - the same resource. For instance, a configuration file on disk, or a socket, a port, - a region of shared memory... - - Serialization is only guaranteed if all processes that access the shared resource - use QLockFile, with the same file path. - - QLockFile supports two use cases: - to protect a resource for a short-term operation (e.g. verifying if a configuration - file has changed before saving new settings), and for long-lived protection of a - resource (e.g. a document opened by a user in an editor) for an indefinite amount of time. - - When protecting for a short-term operation, it is acceptable to call lock() and wait - until any running operation finishes. - When protecting a resource over a long time, however, the application should always - call setStaleLockTime(0) and then tryLock() with a short timeout, in order to - warn the user that the resource is locked. - - If the process holding the lock crashes, the lock file stays on disk and can prevent - any other process from accessing the shared resource, ever. For this reason, QLockFile - tries to detect such a "stale" lock file, based on the process ID written into the file, - and (in case that process ID got reused meanwhile), on the last modification time of - the lock file (30s by default, for the use case of a short-lived operation). - If the lock file is found to be stale, it will be deleted. - - For the use case of protecting a resource over a long time, you should therefore call - setStaleLockTime(0), and when tryLock() returns LockFailedError, inform the user - that the document is locked, possibly using getLockInfo() for more details. -*/ - -/*! - \enum QLockFile::LockError - - This enum describes the result of the last call to lock() or tryLock(). - - \value NoError The lock was acquired successfully. - \value LockFailedError The lock could not be acquired because another process holds it. - \value PermissionError The lock file could not be created, for lack of permissions - in the parent directory. - \value UnknownError Another error happened, for instance a full partition - prevented writing out the lock file. -*/ - -/*! - Constructs a new lock file object. - The object is created in an unlocked state. - When calling lock() or tryLock(), a lock file named \a fileName will be created, - if it doesn't already exist. - - \sa lock(), unlock() -*/ -QLockFile::QLockFile(const QString &fileName) - : d_ptr(new QLockFilePrivate(fileName)) -{ -} - -/*! - Destroys the lock file object. - If the lock was acquired, this will release the lock, by deleting the lock file. -*/ -QLockFile::~QLockFile() -{ - unlock(); -} - -/*! - Sets \a staleLockTime to be the time in milliseconds after which - a lock file is considered stale. - The default value is 30000, i.e. 30 seconds. - If your application typically keeps the file locked for more than 30 seconds - (for instance while saving megabytes of data for 2 minutes), you should set - a bigger value using setStaleLockTime(). - - The value of \a staleLockTime is used by lock() and tryLock() in order - to determine when an existing lock file is considered stale, i.e. left over - by a crashed process. This is useful for the case where the PID got reused - meanwhile, so the only way to detect a stale lock file is by the fact that - it has been around for a long time. - - \sa staleLockTime() -*/ -void QLockFile::setStaleLockTime(int staleLockTime) -{ - Q_D(QLockFile); - d->staleLockTime = staleLockTime; -} - -/*! - Returns the time in milliseconds after which - a lock file is considered stale. - - \sa setStaleLockTime() -*/ -int QLockFile::staleLockTime() const -{ - Q_D(const QLockFile); - return d->staleLockTime; -} - -/*! - Returns \c true if the lock was acquired by this QLockFile instance, - otherwise returns \c false. - - \sa lock(), unlock(), tryLock() -*/ -bool QLockFile::isLocked() const -{ - Q_D(const QLockFile); - return d->isLocked; -} - -/*! - Creates the lock file. - - If another process (or another thread) has created the lock file already, - this function will block until that process (or thread) releases it. - - Calling this function multiple times on the same lock from the same - thread without unlocking first is not allowed. This function will - \e dead-lock when the file is locked recursively. - - Returns \c true if the lock was acquired, false if it could not be acquired - due to an unrecoverable error, such as no permissions in the parent directory. - - \sa unlock(), tryLock() -*/ -bool QLockFile::lock() -{ - return tryLock(-1); -} - -/*! - Attempts to create the lock file. This function returns \c true if the - lock was obtained; otherwise it returns \c false. If another process (or - another thread) has created the lock file already, this function will - wait for at most \a timeout milliseconds for the lock file to become - available. - - Note: Passing a negative number as the \a timeout is equivalent to - calling lock(), i.e. this function will wait forever until the lock - file can be locked if \a timeout is negative. - - If the lock was obtained, it must be released with unlock() - before another process (or thread) can successfully lock it. - - Calling this function multiple times on the same lock from the same - thread without unlocking first is not allowed, this function will - \e always return false when attempting to lock the file recursively. - - \sa lock(), unlock() -*/ -bool QLockFile::tryLock(int timeout) -{ - Q_D(QLockFile); -#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0) - QElapsedTimer timer; -#else - QTime timer; -#endif - if (timeout > 0) - timer.start(); - int sleepTime = 100; - Q_FOREVER { - d->lockError = d->tryLock_sys(); - switch (d->lockError) { - case NoError: - d->isLocked = true; - return true; - case PermissionError: - case UnknownError: - return false; - case LockFailedError: - if (!d->isLocked && d->isApparentlyStale()) { - // Stale lock from another thread/process - // Ensure two processes don't remove it at the same time - QLockFile rmlock(d->fileName + QLatin1String(".rmlock")); - if (rmlock.tryLock()) { - if (d->isApparentlyStale() && d->removeStaleLock()) - continue; - } - } - break; - } - if (timeout == 0 || (timeout > 0 && (timer.elapsed() > timeout))) - return false; - QLockFileThread::msleep(sleepTime); - if (sleepTime < 5 * 1000) - sleepTime *= 2; - } - // not reached - return false; -} - -/*! - \fn void QLockFile::unlock() - Releases the lock, by deleting the lock file. - - Calling unlock() without locking the file first, does nothing. - - \sa lock(), tryLock() -*/ - -/*! - Retrieves information about the current owner of the lock file. - - If tryLock() returns \c false, and error() returns LockFailedError, - this function can be called to find out more information about the existing - lock file: - \list - \li the PID of the application (returned in \a pid) - \li the \a hostname it's running on (useful in case of networked filesystems), - \li the name of the application which created it (returned in \a appname), - \endlist - - Note that tryLock() automatically deleted the file if there is no - running application with this PID, so LockFailedError can only happen if there is - an application with this PID (it could be unrelated though). - - This can be used to inform users about the existing lock file and give them - the choice to delete it. After removing the file using removeStaleLockFile(), - the application can call tryLock() again. - - This function returns \c true if the information could be successfully retrieved, false - if the lock file doesn't exist or doesn't contain the expected data. - This can happen if the lock file was deleted between the time where tryLock() failed - and the call to this function. Simply call tryLock() again if this happens. -*/ -bool QLockFile::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const -{ - Q_D(const QLockFile); - return d->getLockInfo(pid, hostname, appname); -} - -bool QLockFilePrivate::getLockInfo(qint64 *pid, QString *hostname, QString *appname) const -{ - QFile reader(fileName); - if (!reader.open(QIODevice::ReadOnly)) - return false; - - QByteArray pidLine = reader.readLine(); - pidLine.chop(1); - QByteArray appNameLine = reader.readLine(); - appNameLine.chop(1); - QByteArray hostNameLine = reader.readLine(); - hostNameLine.chop(1); - if (pidLine.isEmpty()) - return false; - - qint64 thePid = pidLine.toLongLong(); - if (pid) - *pid = thePid; - if (appname) - *appname = QString::fromUtf8(appNameLine); - if (hostname) - *hostname = QString::fromUtf8(hostNameLine); - return thePid > 0; -} - -/*! - Attempts to forcefully remove an existing lock file. - - Calling this is not recommended when protecting a short-lived operation: QLockFile - already takes care of removing lock files after they are older than staleLockTime(). - - This method should only be called when protecting a resource for a long time, i.e. - with staleLockTime(0), and after tryLock() returned LockFailedError, and the user - agreed on removing the lock file. - - Returns \c true on success, false if the lock file couldn't be removed. This happens - on Windows, when the application owning the lock is still running. -*/ -bool QLockFile::removeStaleLockFile() -{ - Q_D(QLockFile); - if (d->isLocked) { - qWarning("removeStaleLockFile can only be called when not holding the lock"); - return false; - } - return d->removeStaleLock(); -} - -/*! - Returns the lock file error status. - - If tryLock() returns \c false, this function can be called to find out - the reason why the locking failed. -*/ -QLockFile::LockError QLockFile::error() const -{ - Q_D(const QLockFile); - return d->lockError; -} - -QT_END_NAMESPACE diff --git a/src/core/qlockfile.h b/src/core/qlockfile.h deleted file mode 100644 index 673026f21..000000000 --- a/src/core/qlockfile.h +++ /dev/null @@ -1,79 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QLOCKFILE_H -#define QLOCKFILE_H - -#include -#include - -QT_BEGIN_NAMESPACE - -class QLockFilePrivate; - -class QLockFile -{ -public: - QLockFile(const QString &fileName); - ~QLockFile(); - - bool lock(); - bool tryLock(int timeout = 0); - void unlock(); - - void setStaleLockTime(int); - int staleLockTime() const; - - bool isLocked() const; - bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const; - bool removeStaleLockFile(); - - enum LockError { - NoError = 0, - LockFailedError = 1, - PermissionError = 2, - UnknownError = 3 - }; - LockError error() const; - -protected: - QScopedPointer d_ptr; - -private: - Q_DECLARE_PRIVATE(QLockFile) - Q_DISABLE_COPY(QLockFile) -}; - -QT_END_NAMESPACE - -#endif // QLOCKFILE_H diff --git a/src/core/qlockfile_p.h b/src/core/qlockfile_p.h deleted file mode 100644 index 15fa37be6..000000000 --- a/src/core/qlockfile_p.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QLOCKFILE_P_H -#define QLOCKFILE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qlockfile.h" - -#include -#include - -#ifdef Q_OS_WIN -#include -#endif - -QT_BEGIN_NAMESPACE - -class QLockFileThread : public QThread -{ -public: - static void msleep(unsigned long msecs) { QThread::msleep(msecs); } -}; - -class QLockFilePrivate -{ -public: - QLockFilePrivate(const QString &fn) - : fileName(fn), -#ifdef Q_OS_WIN - fileHandle(INVALID_HANDLE_VALUE), -#else - fileHandle(-1), -#endif - staleLockTime(30 * 1000), // 30 seconds - lockError(QLockFile::NoError), - isLocked(false) - { - } - QLockFile::LockError tryLock_sys(); - bool removeStaleLock(); - bool getLockInfo(qint64 *pid, QString *hostname, QString *appname) const; - // Returns \c true if the lock belongs to dead PID, or is old. - // The attempt to delete it will tell us if it was really stale or not, though. - bool isApparentlyStale() const; - static QString processNameByPid(qint64 pid); - - QString fileName; -#ifdef Q_OS_WIN - Qt::HANDLE fileHandle; -#else - int fileHandle; -#endif - int staleLockTime; // "int milliseconds" is big enough for 24 days - QLockFile::LockError lockError; - bool isLocked; -}; - -QT_END_NAMESPACE - -#endif /* QLOCKFILE_P_H */ diff --git a/src/core/qlockfile_unix.cpp b/src/core/qlockfile_unix.cpp deleted file mode 100644 index 5b3add3c5..000000000 --- a/src/core/qlockfile_unix.cpp +++ /dev/null @@ -1,244 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt-project.org/legal -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. For licensing terms and -** conditions see http://qt.digia.com/licensing. For further information -** use the contact form at http://qt.digia.com/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qlockfile_p.h" - -#include -#include -#include -#include -#include - -#include // flock -#include // kill -#include // kill -#include // gethostname - -#include - -#if defined(Q_OS_MAC) -# include -#elif defined(Q_OS_LINUX) -# include -# include -#endif - -QT_BEGIN_NAMESPACE - -#define EINTR_LOOP(var, cmd) \ - do { \ - var = cmd; \ - } while (var == -1 && errno == EINTR) - -// don't call QT_OPEN or ::open -// call qt_safe_open -static inline int qt_safe_open(const char *pathname, int flags, mode_t mode = 0777) -{ -#ifdef O_CLOEXEC - flags |= O_CLOEXEC; -#endif - int fd; - EINTR_LOOP(fd, ::open(pathname, flags, mode)); - - // unknown flags are ignored, so we have no way of verifying if - // O_CLOEXEC was accepted - if (fd != -1) - ::fcntl(fd, F_SETFD, FD_CLOEXEC); - return fd; -} - -static inline qint64 qt_safe_write(int fd, const void *data, qint64 len) -{ - qint64 ret = 0; - EINTR_LOOP(ret, ::write(fd, data, len)); - return ret; -} - -static QByteArray localHostName() // from QHostInfo::localHostName(), modified to return a QByteArray -{ - QByteArray hostName(512, Qt::Uninitialized); - if (gethostname(hostName.data(), hostName.size()) == -1) - return QByteArray(); - hostName.truncate(strlen(hostName.data())); - return hostName; -} - -// ### merge into qt_safe_write? -static qint64 qt_write_loop(int fd, const char *data, qint64 len) -{ - qint64 pos = 0; - while (pos < len) { - const qint64 ret = qt_safe_write(fd, data + pos, len - pos); - if (ret == -1) // e.g. partition full - return pos; - pos += ret; - } - return pos; -} - -static bool setNativeLocks(int fd) -{ -#if defined(LOCK_EX) && defined(LOCK_NB) - if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs - return false; -#endif - struct flock flockData; - flockData.l_type = F_WRLCK; - flockData.l_whence = SEEK_SET; - flockData.l_start = 0; - flockData.l_len = 0; // 0 = entire file - flockData.l_pid = getpid(); - if (fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems - return false; - return true; -} - -QLockFile::LockError QLockFilePrivate::tryLock_sys() -{ - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - // Use operator% from the fast builder to avoid multiple memory allocations. - QByteArray fileData = QByteArray::number(QCoreApplication::applicationPid()) + '\n' - + QCoreApplication::applicationName().toUtf8() + '\n' - + localHostName() + '\n'; - - const QByteArray lockFileName = QFile::encodeName(fileName); - const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY | O_CREAT | O_EXCL, 0644); - if (fd < 0) { - switch (errno) { - case EEXIST: - return QLockFile::LockFailedError; - case EACCES: - case EROFS: - return QLockFile::PermissionError; - default: - return QLockFile::UnknownError; - } - } - // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fd)) - qWarning() << "setNativeLocks failed:" << strerror(errno); - - if (qt_write_loop(fd, fileData.constData(), fileData.size()) < fileData.size()) { - close(fd); - if (!QFile::remove(fileName)) - qWarning("QLockFile: Could not remove our own lock file %s.", qPrintable(fileName)); - return QLockFile::UnknownError; // partition full - } - - // We hold the lock, continue. - fileHandle = fd; - - return QLockFile::NoError; -} - -bool QLockFilePrivate::removeStaleLock() -{ - const QByteArray lockFileName = QFile::encodeName(fileName); - const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644); - if (fd < 0) // gone already? - return false; -#ifdef Q_OS_MAC - // ugly workaround: ignore setNativeLocks() result on Mac since it's broken there - setNativeLocks(fd); - bool success = (::unlink(lockFileName) == 0); -#else - bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); -#endif - close(fd); - return success; -} - -bool QLockFilePrivate::isApparentlyStale() const -{ - qint64 pid; - QString hostname, appname; - if (getLockInfo(&pid, &hostname, &appname)) { - if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) { - if (::kill(pid, 0) == -1 && errno == ESRCH) - return true; // PID doesn't exist anymore - const QString processName = processNameByPid(pid); - if (!processName.isEmpty()) { - QFileInfo fi(appname); - if (fi.isSymLink()) - fi.setFile(fi.symLinkTarget()); - if (processName.toLower() != fi.fileName().toLower()) - return true; // PID got reused by a different application. - } - } - } - const qint64 age = QFileInfo(fileName).lastModified().secsTo(QDateTime::currentDateTime()) * 1000; - return staleLockTime > 0 && age > staleLockTime; -} - -QString QLockFilePrivate::processNameByPid(qint64 pid) -{ -#if defined(Q_OS_MAC) - char name[1024]; - proc_name(pid, name, sizeof(name) / sizeof(char)); - return QFile::decodeName(name); -#elif defined(Q_OS_LINUX) - if (!QFile::exists(QString("/proc/version"))) - return QString(); - char exePath[64]; - char buf[PATH_MAX + 1]; - sprintf(exePath, "/proc/%lld/exe", pid); - size_t len = static_cast(readlink(exePath, buf, sizeof(buf))); - if (len >= sizeof(buf)) { - // The pid is gone. Return some invalid process name to fail the test. - return QString("/ERROR/"); - } - buf[len] = 0; - return QFileInfo(QFile::decodeName(buf)).fileName(); -#else - return QString(); -#endif -} - -void QLockFile::unlock() -{ - Q_D(QLockFile); - if (!d->isLocked) - return; - close(d->fileHandle); - d->fileHandle = -1; - if (!QFile::remove(d->fileName)) { - qWarning() << "Could not remove our own lock file" << d->fileName << "maybe permissions changed meanwhile?"; - // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout... - } - d->lockError = QLockFile::NoError; - d->isLocked = false; -} - -QT_END_NAMESPACE diff --git a/src/core/qlockfile_win.cpp b/src/core/qlockfile_win.cpp deleted file mode 100644 index 5fc332792..000000000 --- a/src/core/qlockfile_win.cpp +++ /dev/null @@ -1,227 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2013 David Faure -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL21$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef _UNICODE -#define _UNICODE -#endif - -#ifndef UNICODE -#define UNICODE -#endif - -#include "qlockfile_p.h" - -#include - -#include -#include -#include -#include -#include - -QT_BEGIN_NAMESPACE - -static inline QByteArray localHostName() -{ - return qgetenv("COMPUTERNAME"); -} - -static inline bool fileExists(const wchar_t *fileName) -{ - WIN32_FILE_ATTRIBUTE_DATA data; - return GetFileAttributesEx(fileName, GetFileExInfoStandard, &data); -} - -QLockFile::LockError QLockFilePrivate::tryLock_sys() -{ - const ushort* nativePath = QDir::toNativeSeparators(fileName).utf16(); - // When writing, allow others to read. - // When reading, QFile will allow others to read and write, all good. - // Adding FILE_SHARE_DELETE would allow forceful deletion of stale files, - // but Windows doesn't allow recreating it while this handle is open anyway, - // so this would only create confusion (can't lock, but no lock file to read from). - const DWORD dwShareMode = FILE_SHARE_READ; -#ifndef Q_OS_WINRT - SECURITY_ATTRIBUTES securityAtts = { sizeof(SECURITY_ATTRIBUTES), NULL, FALSE }; - HANDLE fh = CreateFile((const wchar_t*)nativePath, - GENERIC_WRITE, - dwShareMode, - &securityAtts, - CREATE_NEW, // error if already exists - FILE_ATTRIBUTE_NORMAL, - NULL); -#else // !Q_OS_WINRT - HANDLE fh = CreateFile2((const wchar_t*)nativePath, - GENERIC_WRITE, - dwShareMode, - CREATE_NEW, // error if already exists - NULL); -#endif // Q_OS_WINRT - if (fh == INVALID_HANDLE_VALUE) { - const DWORD lastError = GetLastError(); - switch (lastError) { - case ERROR_SHARING_VIOLATION: - case ERROR_ALREADY_EXISTS: - case ERROR_FILE_EXISTS: - return QLockFile::LockFailedError; - case ERROR_ACCESS_DENIED: - // readonly file, or file still in use by another process. - // Assume the latter if the file exists, since we don't create it readonly. - return fileExists((const wchar_t*)nativePath) - ? QLockFile::LockFailedError - : QLockFile::PermissionError; - default: - qWarning() << "Got unexpected locking error" << lastError; - return QLockFile::UnknownError; - } - } - - // We hold the lock, continue. - fileHandle = fh; - // Assemble data, to write in a single call to write - // (otherwise we'd have to check every write call) - QByteArray fileData; - fileData += QByteArray::number(QCoreApplication::applicationPid()); - fileData += '\n'; - fileData += QCoreApplication::applicationName().toUtf8(); - fileData += '\n'; - fileData += localHostName(); - fileData += '\n'; - DWORD bytesWritten = 0; - QLockFile::LockError error = QLockFile::NoError; - if (!WriteFile(fh, fileData.constData(), fileData.size(), &bytesWritten, NULL) || !FlushFileBuffers(fh)) - error = QLockFile::UnknownError; // partition full - return error; -} - -bool QLockFilePrivate::removeStaleLock() -{ - // QFile::remove fails on Windows if the other process is still using the file, so it's not stale. - return QFile::remove(fileName); -} - -bool QLockFilePrivate::isApparentlyStale() const -{ - qint64 pid; - QString hostname, appname; - - // On WinRT there seems to be no way of obtaining information about other - // processes due to sandboxing -#ifndef Q_OS_WINRT - if (getLockInfo(&pid, &hostname, &appname)) { - if (hostname.isEmpty() || hostname == QString::fromLocal8Bit(localHostName())) { - HANDLE procHandle = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); - if (!procHandle) - return true; - // We got a handle but check if process is still alive - DWORD dwR = ::WaitForSingleObject(procHandle, 0); - ::CloseHandle(procHandle); - if (dwR == WAIT_TIMEOUT) - return true; - const QString processName = processNameByPid(pid); - if (!processName.isEmpty() && processName != appname) - return true; // PID got reused by a different application. - } - } -#else // !Q_OS_WINRT - Q_UNUSED(pid); - Q_UNUSED(hostname); - Q_UNUSED(appname); -#endif // Q_OS_WINRT - const qint64 age = QFileInfo(fileName).lastModified().msecsTo(QDateTime::currentDateTime()); - return staleLockTime > 0 && age > staleLockTime; -} - -QString QLockFilePrivate::processNameByPid(qint64 pid) -{ -#if !defined(Q_OS_WINRT) && !defined(Q_OS_WINCE) - typedef DWORD (WINAPI *GetModuleFileNameExFunc)(HANDLE, HMODULE, LPTSTR, DWORD); - - HMODULE hPsapi = LoadLibraryA("psapi"); - if (!hPsapi) - return QString(); - - GetModuleFileNameExFunc qGetModuleFileNameEx - = (GetModuleFileNameExFunc)GetProcAddress(hPsapi, "GetModuleFileNameExW"); - if (!qGetModuleFileNameEx) { - FreeLibrary(hPsapi); - return QString(); - } - - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, DWORD(pid)); - if (!hProcess) { - FreeLibrary(hPsapi); - return QString(); - } - wchar_t buf[MAX_PATH]; - const DWORD length = qGetModuleFileNameEx(hProcess, NULL, buf, sizeof(buf) / sizeof(wchar_t)); - CloseHandle(hProcess); - FreeLibrary(hPsapi); - if (!length) - return QString(); - QString name = QString::fromWCharArray(buf, length); - int i = name.lastIndexOf(QLatin1Char('\\')); - if (i >= 0) - name.remove(0, i + 1); - i = name.lastIndexOf(QLatin1Char('.')); - if (i >= 0) - name.truncate(i); - return name; -#else - Q_UNUSED(pid); - return QString(); -#endif -} - -void QLockFile::unlock() -{ - Q_D(QLockFile); - if (!d->isLocked) - return; - CloseHandle(d->fileHandle); - int attempts = 0; - static const int maxAttempts = 500; // 500ms - while (!QFile::remove(d->fileName) && ++attempts < maxAttempts) { - // Someone is reading the lock file right now (on Windows this prevents deleting it). - QLockFileThread::msleep(1); - } - if (attempts == maxAttempts) { - qWarning() << "Could not remove our own lock file" << d->fileName << ". Either other users of the lock file are reading it constantly for 500 ms, or we (no longer) have permissions to delete the file"; - // This is bad because other users of this lock file will now have to wait for the stale-lock-timeout... - } - d->lockError = QLockFile::NoError; - d->isLocked = false; -} - -QT_END_NAMESPACE diff --git a/src/core/qsavefile.cpp b/src/core/qsavefile.cpp deleted file mode 100644 index 287f9e8e2..000000000 --- a/src/core/qsavefile.cpp +++ /dev/null @@ -1,452 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qsavefile.h" -#include "qsavefile_p.h" - -#include -#include -#include - -#ifdef Q_OS_WIN -# include -#else -# include -#endif - -QSaveFilePrivate::QSaveFilePrivate() - : tempFile(0), error(QFile::NoError) -{ -} - -QSaveFilePrivate::~QSaveFilePrivate() -{ -} - -/*! - \class QSaveFile - \brief The QSaveFile class provides an interface for safely writing to files. - - \ingroup io - - \reentrant - - QSaveFile is an I/O device for writing text and binary files, without losing - existing data if the writing operation fails. - - While writing, the contents will be written to a temporary file, and if - no error happened, commit() will move it to the final file. This ensures that - no data at the final file is lost in case an error happens while writing, - and no partially-written file is ever present at the final location. Always - use QSaveFile when saving entire documents to disk. - - QSaveFile automatically detects errors while writing, such as the full partition - situation, where write() cannot write all the bytes. It will remember that - an error happened, and will discard the temporary file in commit(). - - Much like with QFile, the file is opened with open(). Data is usually read - and written using QDataStream or QTextStream, but you can also call the - QIODevice-inherited functions read(), readLine(), readAll(), write(). - - Unlike QFile, calling close() is not allowed. commit() replaces it. If commit() - was not called and the QSaveFile instance is destroyed, the temporary file is - discarded. - - \sa QTextStream, QDataStream, QFileInfo, QDir, QFile, QTemporaryFile -*/ - -/*! - \internal -*/ -QSaveFile::QSaveFile() - : QIODevice(), d_ptr(new QSaveFilePrivate) -{ -} -/*! - Constructs a new file object with the given \a parent. -*/ -QSaveFile::QSaveFile(QObject *parent) - : QIODevice(parent), d_ptr(new QSaveFilePrivate) -{ -} -/*! - Constructs a new file object to represent the file with the given \a name. -*/ -QSaveFile::QSaveFile(const QString &name) - : QIODevice(0), d_ptr(new QSaveFilePrivate) -{ - Q_D(QSaveFile); - d->fileName = name; -} -/*! - Constructs a new file object with the given \a parent to represent the - file with the specified \a name. -*/ -QSaveFile::QSaveFile(const QString &name, QObject *parent) - : QIODevice(parent), d_ptr(new QSaveFilePrivate) -{ - Q_D(QSaveFile); - d->fileName = name; -} - -/*! - Destroys the file object, discarding the saved contents unless commit() was called. -*/ -QSaveFile::~QSaveFile() -{ - Q_D(QSaveFile); - if (d->tempFile) { - d->tempFile->setAutoRemove(true); - delete d->tempFile; - } - QIODevice::close(); - delete d; -} - -/*! - Returns false since temporary files support random access. - - \sa QIODevice::isSequential() -*/ -bool QSaveFile::isSequential() const -{ - return false; -} - -/*! - Returns the file error status. - - The I/O device status returns an error code. For example, if open() - returns false, or a read/write operation returns -1, this function can - be called to find out the reason why the operation failed. - - Unlike QFile which clears the error on the next operation, QSaveFile remembers - the error until the file is closed, in order to discard the file contents in close(). - - \sa unsetError() -*/ - -QFile::FileError QSaveFile::error() const -{ - return d_func()->error; -} - -/*! - Sets the file's error to QFile::NoError. - - This will make QSaveFile forget that an error happened during saving, so you - probably don't want to call this, unless you're really sure that you want to - save the file anyway. - - \sa error() -*/ -void QSaveFile::unsetError() -{ - d_func()->error = QFile::NoError; - setErrorString(QString()); -} - -/*! - Returns the name set by setFileName() or to the QSaveFile - constructor. - - \sa setFileName() -*/ -QString QSaveFile::fileName() const -{ - return d_func()->fileName; -} - -/*! - Sets the \a name of the file. The name can have no path, a - relative path, or an absolute path. - - \sa QFile::setFileName(), fileName() -*/ -void QSaveFile::setFileName(const QString &name) -{ - d_func()->fileName = name; -} - -/*! - Opens the file using OpenMode \a mode, returning true if successful; - otherwise false. - - Important: the \a mode must be QIODevice::WriteOnly. - It may also have additional flags, such as QIODevice::Text and QIODevice::Unbuffered. - - QIODevice::ReadWrite and QIODevice::Append are not supported at the moment. - - \sa QIODevice::OpenMode, setFileName() -*/ -bool QSaveFile::open(OpenMode mode) -{ - Q_D(QSaveFile); - if (isOpen()) { - qWarning("QSaveFile::open: File (%s) already open", qPrintable(fileName())); - return false; - } - unsetError(); - if ((mode & (ReadOnly | WriteOnly)) == 0) { - qWarning("QSaveFile::open: Open mode not specified"); - return false; - } - // In the future we could implement Append and ReadWrite by copying from the existing file to the temp file... - if ((mode & ReadOnly) || (mode & Append)) { - qWarning("QSaveFile::open: Unsupported open mode %d", int(mode)); - return false; - } - - // check if existing file is writable - QFileInfo existingFile(d->fileName); - if (existingFile.exists() && !existingFile.isWritable()) { - d->error = QFile::WriteError; - setErrorString(QSaveFile::tr("Existing file %1 is not writable").arg(d->fileName)); - return false; - } - d->tempFile = new QTemporaryFile; - d->tempFile->setAutoRemove(false); - d->tempFile->setFileTemplate(d->fileName); - if (!d->tempFile->open()) { - d->error = d->tempFile->error(); - setErrorString(d->tempFile->errorString()); - delete d->tempFile; - d->tempFile = 0; - return false; - } - QIODevice::open(mode); - if (existingFile.exists()) - d->tempFile->setPermissions(existingFile.permissions()); - return true; -} - -/*! - \reimp - Cannot be called. - Call commit() instead. -*/ -void QSaveFile::close() -{ - qFatal("QSaveFile::close called"); -} - -/* - Commits the changes to disk, if all previous writes were successful. - - It is mandatory to call this at the end of the saving operation, otherwise the file will be - discarded. - - If an error happened during writing, deletes the temporary file and returns false. - Otherwise, renames it to the final fileName and returns true on success. - Finally, closes the device. - - \sa cancelWriting() -*/ -bool QSaveFile::commit() -{ - Q_D(QSaveFile); - if (!d->tempFile) - return false; - if (!isOpen()) { - qWarning("QSaveFile::commit: File (%s) is not open", qPrintable(fileName())); - return false; - } - flush(); -#ifdef Q_OS_WIN - FlushFileBuffers(reinterpret_cast(handle())); -#elif defined(_POSIX_SYNCHRONIZED_IO) && _POSIX_SYNCHRONIZED_IO > 0 - fdatasync(d->tempFile->handle()); -#else - fsync(d->tempFile->handle()); -#endif - QIODevice::close(); - if (d->error != QFile::NoError) { - d->tempFile->remove(); - unsetError(); - delete d->tempFile; - d->tempFile = 0; - return false; - } - d->tempFile->close(); -#ifdef Q_OS_WIN - // On Windows QAbstractFileEngine::rename() fails if the the target exists, - // so we have to rename the target. - // Ideally the winapi ReplaceFile() method should be used. - QString bakname = d->fileName + "~"; - QFile::remove(bakname); - QFile::rename(d->fileName, bakname); -#endif - QAbstractFileEngine* fileEngine = d->tempFile->fileEngine(); - Q_ASSERT(fileEngine); - if (!fileEngine->rename(d->fileName)) { - d->error = fileEngine->error(); - setErrorString(fileEngine->errorString()); - d->tempFile->remove(); - delete d->tempFile; - d->tempFile = 0; -#ifdef Q_OS_WIN - QFile::rename(bakname, d->fileName); -#endif - return false; - } - delete d->tempFile; - d->tempFile = 0; -#ifdef Q_OS_WIN - QFile::remove(bakname); -#endif - return true; -} - -/*! - Sets an error code so that commit() discards the temporary file. - - Further write operations are possible after calling this method, but none - of it will have any effect, the written file will be discarded. - - \sa commit() -*/ -void QSaveFile::cancelWriting() -{ - if (!isOpen()) - return; - d_func()->error = QFile::WriteError; - setErrorString(QSaveFile::tr("Writing canceled by application")); -} - -/*! - Returns the size of the file. - \sa QFile::size() -*/ -qint64 QSaveFile::size() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->size() : qint64(-1); -} - -/*! - \reimp -*/ -qint64 QSaveFile::pos() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->pos() : qint64(-1); -} - -/*! - \reimp -*/ -bool QSaveFile::seek(qint64 offset) -{ - Q_D(QSaveFile); - return d->tempFile ? d->tempFile->seek(offset) : false; -} - -/*! - \reimp -*/ -bool QSaveFile::atEnd() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->atEnd() : true; -} - -/*! - Flushes any buffered data to the file. Returns true if successful; - otherwise returns false. -*/ -bool QSaveFile::flush() -{ - Q_D(QSaveFile); - if (d->tempFile) { - if (!d->tempFile->flush()) { - d->error = d->tempFile->error(); - setErrorString(d->tempFile->errorString()); - return false; - } - return true; - } - return false; -} - -/*! - Returns the file handle of the temporary file. - - \sa QFile::handle() -*/ -int QSaveFile::handle() const -{ - Q_D(const QSaveFile); - return d->tempFile ? d->tempFile->handle() : -1; -} - -/*! - \reimp -*/ -qint64 QSaveFile::readData(char *data, qint64 maxlen) -{ - Q_D(QSaveFile); - return d->tempFile ? d->tempFile->read(data, maxlen) : -1; -} - -/*! - \reimp -*/ -qint64 QSaveFile::writeData(const char *data, qint64 len) -{ - Q_D(QSaveFile); - if (!d->tempFile) - return -1; - const qint64 written = d->tempFile->write(data, len); - if (written != len) { - d->error = QFile::WriteError; - setErrorString(QSaveFile::tr("Partial write. Partition full?")); - } - return written; -} - -/*! - \reimp -*/ -qint64 QSaveFile::readLineData(char *data, qint64 maxlen) -{ - Q_D(QSaveFile); - return d->tempFile ? d->tempFile->readLine(data, maxlen) : -1; -} diff --git a/src/core/qsavefile.h b/src/core/qsavefile.h deleted file mode 100644 index 84d5a2450..000000000 --- a/src/core/qsavefile.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSAVEFILE_H -#define QSAVEFILE_H - -#include -#include - -#ifdef open -#error qsavefile.h must be included before any header file that defines open -#endif - -class QAbstractFileEngine; -class QSaveFilePrivate; - -class QSaveFile : public QIODevice -{ - Q_OBJECT - Q_DECLARE_PRIVATE(QSaveFile) - -public: - - QSaveFile(); - explicit QSaveFile(const QString &name); - explicit QSaveFile(QObject *parent); - QSaveFile(const QString &name, QObject *parent); - ~QSaveFile(); - - QFile::FileError error() const; - void unsetError(); - - QString fileName() const; - void setFileName(const QString &name); - - bool isSequential() const; - - virtual bool open(OpenMode flags); - bool commit(); - - void cancelWriting(); - - qint64 size() const; - qint64 pos() const; - bool seek(qint64 offset); - bool atEnd() const; - bool flush(); - - bool resize(qint64 sz); - - int handle() const; - -protected: - qint64 readData(char *data, qint64 maxlen); - qint64 writeData(const char *data, qint64 len); - qint64 readLineData(char *data, qint64 maxlen); - -private: - virtual void close(); - -private: - Q_DISABLE_COPY(QSaveFile) - - QSaveFilePrivate* const d_ptr; -}; - -#endif // QSAVEFILE_H diff --git a/src/core/qsavefile_p.h b/src/core/qsavefile_p.h deleted file mode 100644 index 549ecc1b2..000000000 --- a/src/core/qsavefile_p.h +++ /dev/null @@ -1,71 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/ -** -** This file is part of the QtCore module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** GNU Lesser General Public License Usage -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this -** file. Please review the following information to ensure the GNU Lesser -** General Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU General -** Public License version 3.0 as published by the Free Software Foundation -** and appearing in the file LICENSE.GPL included in the packaging of this -** file. Please review the following information to ensure the GNU General -** Public License version 3.0 requirements will be met: -** http://www.gnu.org/copyleft/gpl.html. -** -** Other Usage -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QSAVEFILE_P_H -#define QSAVEFILE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include - -class QSaveFilePrivate -{ -public: - QSaveFilePrivate(); - ~QSaveFilePrivate(); - - QString fileName; - QTemporaryFile *tempFile; - - QFile::FileError error; -}; - -#endif // QSAVEFILE_P_H - diff --git a/src/gui/DatabaseTabWidget.cpp b/src/gui/DatabaseTabWidget.cpp index 4c957a27f..7adeea8e5 100644 --- a/src/gui/DatabaseTabWidget.cpp +++ b/src/gui/DatabaseTabWidget.cpp @@ -18,6 +18,8 @@ #include "DatabaseTabWidget.h" #include +#include +#include #include #include "autotype/AutoType.h" @@ -25,7 +27,6 @@ #include "core/Database.h" #include "core/Group.h" #include "core/Metadata.h" -#include "core/qsavefile.h" #include "format/CsvExporter.h" #include "gui/DatabaseWidget.h" #include "gui/DatabaseWidgetStateSync.h" diff --git a/src/gui/DatabaseTabWidget.h b/src/gui/DatabaseTabWidget.h index c15408d3d..aafe666cb 100644 --- a/src/gui/DatabaseTabWidget.h +++ b/src/gui/DatabaseTabWidget.h @@ -21,7 +21,6 @@ #include #include -#include "core/qlockfile.h" #include "format/KeePass2Writer.h" #include "gui/DatabaseWidget.h" @@ -29,6 +28,7 @@ class DatabaseWidget; class DatabaseWidgetStateSync; class DatabaseOpenWidget; class QFile; +class QLockFile; struct DatabaseManagerStruct { diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 73e9fb0e9..83305057a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -138,9 +138,6 @@ add_unit_test(NAME testdeletedobjects SOURCES TestDeletedObjects.cpp add_unit_test(NAME testkeepass1reader SOURCES TestKeePass1Reader.cpp LIBS ${TEST_LIBRARIES}) -add_unit_test(NAME testqsavefile SOURCES TestQSaveFile.cpp - LIBS ${TEST_LIBRARIES}) - add_unit_test(NAME testwildcardmatcher SOURCES TestWildcardMatcher.cpp LIBS ${TEST_LIBRARIES}) diff --git a/tests/TestQSaveFile.cpp b/tests/TestQSaveFile.cpp deleted file mode 100644 index 443db5299..000000000 --- a/tests/TestQSaveFile.cpp +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "TestQSaveFile.h" - -#include - -#include - -#if defined(Q_OS_WIN) -# include -#endif - -#include "tests.h" -#include "core/qsavefile.h" - -QTEST_GUILESS_MAIN(TestQSaveFile) - -class DirCleanup -{ -public: - DirCleanup(const QString& dir, const QString& filePrefix) : m_dir(dir), m_filePrefix(filePrefix) {} - ~DirCleanup() { - QDir dir(m_dir); - QStringList files = dir.entryList(QStringList() << (m_filePrefix + "*"), QDir::Files); - Q_FOREACH (const QString& file, files) { - QFile::remove(m_dir + "/" + file); - } - - QDir().rmdir(m_dir); - } - -private: - QString m_dir; - QString m_filePrefix; -}; - -void TestQSaveFile::transactionalWrite() -{ - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QFile::remove(targetFile); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - QVERIFY(file.isOpen()); - QCOMPARE(file.fileName(), targetFile); - QVERIFY(!QFile::exists(targetFile)); - - QTextStream ts(&file); - ts << "This is test data one.\n"; - ts.flush(); - QCOMPARE(file.error(), QFile::NoError); - QVERIFY(!QFile::exists(targetFile)); - - QVERIFY(file.commit()); - QVERIFY(QFile::exists(targetFile)); - QCOMPARE(file.fileName(), targetFile); - - // Check that we can reuse a QSaveFile object - // (and test the case of an existing target file) - QVERIFY(file.open(QIODevice::WriteOnly)); - QCOMPARE(file.write("Hello"), 5LL); - QVERIFY(file.commit()); - - QFile reader(targetFile); - QVERIFY(reader.open(QIODevice::ReadOnly)); - QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Hello")); - reader.close(); - - QVERIFY(QFile::remove(targetFile)); -} - -void TestQSaveFile::autoFlush() -{ - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QFile::remove(targetFile); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - - QTextStream ts(&file); - ts << "Auto-flush."; - // no flush - QVERIFY(file.commit()); // close will emit aboutToClose, which will flush the stream - QFile reader(targetFile); - QVERIFY(reader.open(QIODevice::ReadOnly)); - QCOMPARE(QString::fromLatin1(reader.readAll().constData()), QString::fromLatin1("Auto-flush.")); - reader.close(); - - QVERIFY(QFile::remove(targetFile)); -} - -void TestQSaveFile::transactionalWriteNoPermissions() -{ -#ifdef Q_OS_UNIX - if (::geteuid() == 0) { - QSKIP("not valid running this test as root", SkipAll); - } - - // You can write into /dev/zero, but you can't create a /dev/zero.XXXXXX temp file. - QSaveFile file("/dev/zero"); - if (!QDir("/dev").exists()) { - QSKIP("/dev doesn't exist on this system", SkipAll); - } - - QVERIFY(!file.open(QIODevice::WriteOnly)); - QCOMPARE(static_cast(file.error()), static_cast(QFile::OpenError)); - QVERIFY(!file.commit()); -#endif -} - -void TestQSaveFile::transactionalWriteCanceled() -{ - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QFile::remove(targetFile); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - - QTextStream ts(&file); - ts << "This writing operation will soon be canceled.\n"; - ts.flush(); - QCOMPARE(file.error(), QFile::NoError); - QVERIFY(!QFile::exists(targetFile)); - - // We change our mind, let's abort writing - file.cancelWriting(); - - QVERIFY(!file.commit()); - - QVERIFY(!QFile::exists(targetFile)); // temp file was discarded - QCOMPARE(file.fileName(), targetFile); -} - -void TestQSaveFile::transactionalWriteErrorRenaming() -{ -#ifndef Q_OS_WIN - if (::geteuid() == 0) { - QSKIP("not valid running this test as root", SkipAll); - } - const QString dir = tmpDir(); - QVERIFY(!dir.isEmpty()); - const QString targetFile = dir + QString::fromLatin1("/outfile"); - DirCleanup dirCleanup(dir, "outfile"); - QSaveFile file(targetFile); - QVERIFY(file.open(QIODevice::WriteOnly)); - QCOMPARE(file.write("Hello"), qint64(5)); - QVERIFY(!QFile::exists(targetFile)); - -#ifdef Q_OS_UNIX - QFile dirAsFile(dir); // yay, I have to use QFile to change a dir's permissions... - QVERIFY(dirAsFile.setPermissions(QFile::Permissions(0))); // no permissions -#else - QVERIFY(file.setPermissions(QFile::ReadOwner)); -#endif - - QVERIFY(!file.commit()); - QVERIFY(!QFile::exists(targetFile)); // renaming failed - QCOMPARE(file.error(), QFile::RenameError); - - // Restore permissions so that the cleanup can happen -#ifdef Q_OS_UNIX - QVERIFY(dirAsFile.setPermissions(QFile::Permissions(QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner))); -#else - QVERIFY(file.setPermissions(QFile::ReadOwner | QFile::WriteOwner)); -#endif -#endif // !Q_OS_WIN -} - -QString TestQSaveFile::tmpDir() -{ - QTemporaryFile* tmpFile = new QTemporaryFile(QDir::tempPath() + "/qttest_temp.XXXXXX"); - if (!tmpFile->open()) { - return QString(); - } - QString dirName = tmpFile->fileName(); - delete tmpFile; - if (!QDir().mkdir(dirName)) { - return QString(); - } - - return dirName; -} diff --git a/tests/TestQSaveFile.h b/tests/TestQSaveFile.h deleted file mode 100644 index 8e1caf0e1..000000000 --- a/tests/TestQSaveFile.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2012 Felix Geyer - * Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 or (at your option) - * version 3 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#ifndef KEEPASSX_TESTQSAVEFILE_H -#define KEEPASSX_TESTQSAVEFILE_H - -#include - -class TestQSaveFile : public QObject -{ - Q_OBJECT - -private Q_SLOTS: - void transactionalWrite(); - void autoFlush(); - void transactionalWriteNoPermissions(); - void transactionalWriteCanceled(); - void transactionalWriteErrorRenaming(); - -private: - QString tmpDir(); -}; - -#endif // KEEPASSX_TESTQSAVEFILE_H