From 0840556f77c131ac257f104a05676c98a3f9cf26 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 14 Mar 2018 10:44:41 +0800 Subject: [PATCH 1/8] Do cleanups in FileSystemWatcher Use Qt5 connect syntax Sort headers Add license Add anonymous namespace Replace macro defines with const variables --- src/base/filesystemwatcher.cpp | 78 ++++++++++++++++++++++------------ src/base/filesystemwatcher.h | 28 ++++++++++++ 2 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index 33aef074a..6a6143824 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -1,43 +1,69 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2018 + * + * 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 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + +#include "filesystemwatcher.h" + #include + #ifndef Q_OS_WIN -#include +#include #include -#include +#include +#endif + #if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) -#include +#include #include -#include -#elif !defined Q_OS_HAIKU +#include +#elif !defined Q_OS_WIN && !defined Q_OS_HAIKU #include #endif -#endif #include "algorithm.h" #include "base/bittorrent/magneturi.h" #include "base/bittorrent/torrentinfo.h" #include "base/preferences.h" -#include "filesystemwatcher.h" -#ifndef CIFS_MAGIC_NUMBER -#define CIFS_MAGIC_NUMBER 0xFF534D42 -#endif - -#ifndef NFS_SUPER_MAGIC -#define NFS_SUPER_MAGIC 0x6969 -#endif - -#ifndef SMB_SUPER_MAGIC -#define SMB_SUPER_MAGIC 0x517B -#endif +namespace +{ + const unsigned long CIFS_MAGIC_NUMBER = 0xFF534D42; + const unsigned long NFS_SUPER_MAGIC = 0x6969; + const unsigned long SMB_SUPER_MAGIC = 0x517B; -const int WATCH_INTERVAL = 10000; // 10 sec -const int MAX_PARTIAL_RETRIES = 5; + const int WATCH_INTERVAL = 10000; // 10 sec + const int MAX_PARTIAL_RETRIES = 5; +} FileSystemWatcher::FileSystemWatcher(QObject *parent) : QFileSystemWatcher(parent) { m_filters << "*.torrent" << "*.magnet"; - connect(this, SIGNAL(directoryChanged(QString)), SLOT(scanLocalFolder(QString))); + connect(this, &QFileSystemWatcher::directoryChanged, this, &FileSystemWatcher::scanLocalFolder); } FileSystemWatcher::~FileSystemWatcher() @@ -78,7 +104,7 @@ void FileSystemWatcher::addPath(const QString &path) // Set up the watch timer if (!m_watchTimer) { m_watchTimer = new QTimer(this); - connect(m_watchTimer, SIGNAL(timeout()), SLOT(scanNetworkFolders())); + connect(m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders); m_watchTimer->start(WATCH_INTERVAL); // 5 sec } } @@ -186,7 +212,7 @@ void FileSystemWatcher::startPartialTorrentTimer() Q_ASSERT(!m_partialTorrents.isEmpty()); if (!m_partialTorrentTimer) { m_partialTorrentTimer = new QTimer(); - connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(processPartialTorrents())); + connect(m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents); m_partialTorrentTimer->setSingleShot(true); m_partialTorrentTimer->start(WATCH_INTERVAL); } @@ -227,9 +253,9 @@ bool FileSystemWatcher::isNetworkFileSystem(QString path) // XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined? return ((strcmp(buf.f_fstypename, "nfs") == 0) || (strcmp(buf.f_fstypename, "cifs") == 0) || (strcmp(buf.f_fstypename, "smbfs") == 0)); #else - return ((buf.f_type == static_cast(CIFS_MAGIC_NUMBER)) - || (buf.f_type == static_cast(NFS_SUPER_MAGIC)) - || (buf.f_type == static_cast(SMB_SUPER_MAGIC))); + return ((buf.f_type == CIFS_MAGIC_NUMBER) + || (buf.f_type == NFS_SUPER_MAGIC) + || (buf.f_type == SMB_SUPER_MAGIC)); #endif } else { diff --git a/src/base/filesystemwatcher.h b/src/base/filesystemwatcher.h index b209bdfb7..05bd750e3 100644 --- a/src/base/filesystemwatcher.h +++ b/src/base/filesystemwatcher.h @@ -1,3 +1,31 @@ +/* + * Bittorrent Client using Qt and libtorrent. + * Copyright (C) 2018 + * + * 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 + * of the License, or (at your option) any later version. + * + * 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + */ + #ifndef FILESYSTEMWATCHER_H #define FILESYSTEMWATCHER_H From 61eddfce9073507cbc33ab320d903eef1d1a5688 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 14 Mar 2018 10:59:33 +0800 Subject: [PATCH 2/8] Refactor functions in FileSystemWatcher Use c++11 range-loop Add const Better ifdef placement Inline functions --- src/base/filesystemwatcher.cpp | 123 ++++++++++++--------------------- src/base/filesystemwatcher.h | 13 ++-- 2 files changed, 51 insertions(+), 85 deletions(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index 6a6143824..60a8db8eb 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -47,6 +47,7 @@ #include "algorithm.h" #include "base/bittorrent/magneturi.h" #include "base/bittorrent/torrentinfo.h" +#include "base/global.h" #include "base/preferences.h" namespace @@ -62,37 +63,33 @@ namespace FileSystemWatcher::FileSystemWatcher(QObject *parent) : QFileSystemWatcher(parent) { - m_filters << "*.torrent" << "*.magnet"; connect(this, &QFileSystemWatcher::directoryChanged, this, &FileSystemWatcher::scanLocalFolder); } FileSystemWatcher::~FileSystemWatcher() { #ifndef Q_OS_WIN - if (m_watchTimer) - delete m_watchTimer; + delete m_watchTimer; #endif - if (m_partialTorrentTimer) - delete m_partialTorrentTimer; + delete m_partialTorrentTimer; } QStringList FileSystemWatcher::directories() const { - QStringList dirs; + QStringList dirs = QFileSystemWatcher::directories(); #ifndef Q_OS_WIN - if (m_watchTimer) { - foreach (const QDir &dir, m_watchedFolders) - dirs << dir.canonicalPath(); - } + for (const QDir &dir : qAsConst(m_watchedFolders)) + dirs << dir.canonicalPath(); #endif - dirs << QFileSystemWatcher::directories(); return dirs; } void FileSystemWatcher::addPath(const QString &path) { + if (path.isEmpty()) return; + #if !defined Q_OS_WIN && !defined Q_OS_HAIKU - QDir dir(path); + const QDir dir(path); if (!dir.exists()) return; // Check if the path points to a network file system or not @@ -105,67 +102,43 @@ void FileSystemWatcher::addPath(const QString &path) if (!m_watchTimer) { m_watchTimer = new QTimer(this); connect(m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders); - m_watchTimer->start(WATCH_INTERVAL); // 5 sec + m_watchTimer->start(WATCH_INTERVAL); } - } - else { -#endif - // Normal mode - qDebug("FS Watching is watching %s in normal mode", qUtf8Printable(path)); - QFileSystemWatcher::addPath(path); - scanLocalFolder(path); -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU + return; } #endif + + // Normal mode + qDebug("FS Watching is watching %s in normal mode", qUtf8Printable(path)); + QFileSystemWatcher::addPath(path); + scanLocalFolder(path); } void FileSystemWatcher::removePath(const QString &path) { #ifndef Q_OS_WIN - QDir dir(path); - for (int i = 0; i < m_watchedFolders.count(); ++i) { - if (QDir(m_watchedFolders.at(i)) == dir) { - m_watchedFolders.removeAt(i); - if (m_watchedFolders.isEmpty()) - delete m_watchTimer; - return; - } + if (m_watchedFolders.removeOne(path)) { + if (m_watchedFolders.isEmpty()) + delete m_watchTimer; + return; } #endif // Normal mode QFileSystemWatcher::removePath(path); } -void FileSystemWatcher::scanLocalFolder(QString path) +void FileSystemWatcher::scanLocalFolder(const QString &path) { - qDebug("scanLocalFolder(%s) called", qUtf8Printable(path)); - QStringList torrents; - // Local folders scan - addTorrentsFromDir(QDir(path), torrents); - // Report detected torrent files - if (!torrents.empty()) { - qDebug("The following files are being reported: %s", qUtf8Printable(torrents.join("\n"))); - emit torrentsAdded(torrents); - } + processTorrentsInDir(path); } +#ifndef Q_OS_WIN void FileSystemWatcher::scanNetworkFolders() { -#ifndef Q_OS_WIN - qDebug("scanNetworkFolders() called"); - QStringList torrents; - // Network folders scan - foreach (const QDir &dir, m_watchedFolders) { - //qDebug("FSWatcher: Polling manually folder %s", qUtf8Printable(dir.path())); - addTorrentsFromDir(dir, torrents); - } - // Report detected torrent files - if (!torrents.empty()) { - qDebug("The following files are being reported: %s", qUtf8Printable(torrents.join("\n"))); - emit torrentsAdded(torrents); - } -#endif + for (const QDir &dir : qAsConst(m_watchedFolders)) + processTorrentsInDir(dir); } +#endif void FileSystemWatcher::processPartialTorrents() { @@ -207,41 +180,33 @@ void FileSystemWatcher::processPartialTorrents() emit torrentsAdded(noLongerPartial); } -void FileSystemWatcher::startPartialTorrentTimer() +void FileSystemWatcher::processTorrentsInDir(const QDir &dir) { - Q_ASSERT(!m_partialTorrents.isEmpty()); - if (!m_partialTorrentTimer) { - m_partialTorrentTimer = new QTimer(); - connect(m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents); - m_partialTorrentTimer->setSingleShot(true); - m_partialTorrentTimer->start(WATCH_INTERVAL); - } -} - -void FileSystemWatcher::addTorrentsFromDir(const QDir &dir, QStringList &torrents) -{ - const QStringList files = dir.entryList(m_filters, QDir::Files, QDir::Unsorted); - foreach (const QString &file, files) { + QStringList torrents; + const QStringList files = dir.entryList({"*.torrent", "*.magnet"}, QDir::Files); + for (const QString &file : files) { const QString fileAbsPath = dir.absoluteFilePath(file); - if (fileAbsPath.endsWith(".magnet")) { + if (file.endsWith(".magnet")) torrents << fileAbsPath; - } - else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid()) { + else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid()) torrents << fileAbsPath; - } - else if (!m_partialTorrents.contains(fileAbsPath)) { - qDebug("Partial torrent detected at: %s", qUtf8Printable(fileAbsPath)); - qDebug("Delay the file's processing..."); - m_partialTorrents.insert(fileAbsPath, 0); - } + else if (!m_partialTorrents.contains(fileAbsPath)) + m_partialTorrents[fileAbsPath] = 0; } - if (!m_partialTorrents.empty()) - startPartialTorrentTimer(); + if (!torrents.empty()) + emit torrentsAdded(torrents); + + if (!m_partialTorrents.empty() && !m_partialTorrentTimer) { + m_partialTorrentTimer = new QTimer(this); + connect(m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents); + m_partialTorrentTimer->setSingleShot(true); + m_partialTorrentTimer->start(WATCH_INTERVAL); + } } #if !defined Q_OS_WIN && !defined Q_OS_HAIKU -bool FileSystemWatcher::isNetworkFileSystem(QString path) +bool FileSystemWatcher::isNetworkFileSystem(const QString &path) { QString file = path; if (!file.endsWith("/")) diff --git a/src/base/filesystemwatcher.h b/src/base/filesystemwatcher.h index 05bd750e3..fdb4ed796 100644 --- a/src/base/filesystemwatcher.h +++ b/src/base/filesystemwatcher.h @@ -56,22 +56,23 @@ signals: void torrentsAdded(const QStringList &pathList); protected slots: - void scanLocalFolder(QString path); - void scanNetworkFolders(); + void scanLocalFolder(const QString &path); void processPartialTorrents(); +#ifndef Q_OS_WIN + void scanNetworkFolders(); +#endif private: - void startPartialTorrentTimer(); - void addTorrentsFromDir(const QDir &dir, QStringList &torrents); + void processTorrentsInDir(const QDir &dir); #if !defined Q_OS_WIN && !defined Q_OS_HAIKU - static bool isNetworkFileSystem(QString path); + static bool isNetworkFileSystem(const QString &path); #endif + #ifndef Q_OS_WIN QList m_watchedFolders; QPointer m_watchTimer; #endif - QStringList m_filters; // Partial torrents QHash m_partialTorrents; QPointer m_partialTorrentTimer; From 2ba5dd134421b9441d7dd461fea6c560f026ad17 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 14 Mar 2018 12:35:35 +0800 Subject: [PATCH 3/8] Reduce debug messages --- src/base/filesystemwatcher.cpp | 74 +++++++--------------------------- 1 file changed, 15 insertions(+), 59 deletions(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index 60a8db8eb..deaa497ef 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -30,12 +30,6 @@ #include -#ifndef Q_OS_WIN -#include -#include -#include -#endif - #if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) #include #include @@ -52,6 +46,7 @@ namespace { + // usually defined in /usr/include/linux/magic.h const unsigned long CIFS_MAGIC_NUMBER = 0xFF534D42; const unsigned long NFS_SUPER_MAGIC = 0x6969; const unsigned long SMB_SUPER_MAGIC = 0x517B; @@ -209,62 +204,23 @@ void FileSystemWatcher::processTorrentsInDir(const QDir &dir) bool FileSystemWatcher::isNetworkFileSystem(const QString &path) { QString file = path; - if (!file.endsWith("/")) - file += "/"; - file += "."; - struct statfs buf; - if (!statfs(file.toLocal8Bit().constData(), &buf)) { + if (!file.endsWith('/')) + file += '/'; + file += '.'; + + struct statfs buf {}; + if (statfs(file.toLocal8Bit().constData(), &buf) != 0) + return false; + #ifdef Q_OS_MAC // XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined? - return ((strcmp(buf.f_fstypename, "nfs") == 0) || (strcmp(buf.f_fstypename, "cifs") == 0) || (strcmp(buf.f_fstypename, "smbfs") == 0)); + return ((strncmp(buf.f_fstypename, "nfs", sizeof(buf.f_fstypename)) == 0) + || (strncmp(buf.f_fstypename, "cifs", sizeof(buf.f_fstypename)) == 0) + || (strncmp(buf.f_fstypename, "smbfs", sizeof(buf.f_fstypename)) == 0)); #else - return ((buf.f_type == CIFS_MAGIC_NUMBER) - || (buf.f_type == NFS_SUPER_MAGIC) - || (buf.f_type == SMB_SUPER_MAGIC)); + return ((buf.f_type == CIFS_MAGIC_NUMBER) + || (buf.f_type == NFS_SUPER_MAGIC) + || (buf.f_type == SMB_SUPER_MAGIC)); #endif - } - else { - std::cerr << "Error: statfs() call failed for " << qPrintable(file) << ". Supposing it is a local folder..." << std::endl; - switch(errno) { - case EACCES: - std::cerr << "Search permission is denied for a component of the path prefix of the path" << std::endl; - break; - case EFAULT: - std::cerr << "Buf or path points to an invalid address" << std::endl; - break; - case EINTR: - std::cerr << "This call was interrupted by a signal" << std::endl; - break; - case EIO: - std::cerr << "I/O Error" << std::endl; - break; - case ELOOP: - std::cerr << "Too many symlinks" << std::endl; - break; - case ENAMETOOLONG: - std::cerr << "path is too long" << std::endl; - break; - case ENOENT: - std::cerr << "The file referred by path does not exist" << std::endl; - break; - case ENOMEM: - std::cerr << "Insufficient kernel memory" << std::endl; - break; - case ENOSYS: - std::cerr << "The file system does not detect this call" << std::endl; - break; - case ENOTDIR: - std::cerr << "A component of the path is not a directory" << std::endl; - break; - case EOVERFLOW: - std::cerr << "Some values were too large to be represented in the struct" << std::endl; - break; - default: - std::cerr << "Unknown error" << std::endl; - } - - std::cerr << "Errno: " << errno << std::endl; - return false; - } } #endif From 19c733ce95b591073ab7cad45a16c77f615344fd Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 14 Mar 2018 13:51:59 +0800 Subject: [PATCH 4/8] Use specific name for rejected files --- src/base/filesystemwatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index deaa497ef..1e00817a5 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -151,7 +151,7 @@ void FileSystemWatcher::processPartialTorrents() } if (value >= MAX_PARTIAL_RETRIES) { - QFile::rename(torrentPath, torrentPath + ".invalid"); + QFile::rename(torrentPath, torrentPath + ".qbt_rejected"); return true; } From ea7eb7c0ec2221caaa0d01aaa966b1172ed85cf8 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Wed, 14 Mar 2018 14:24:44 +0800 Subject: [PATCH 5/8] Add delay before processing FS changes This prevents file renaming errors in monitored folder on linux, for example: ABC.torrent.part -> ABC.torrent --- src/base/filesystemwatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index 1e00817a5..b5f9b2308 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -124,7 +124,7 @@ void FileSystemWatcher::removePath(const QString &path) void FileSystemWatcher::scanLocalFolder(const QString &path) { - processTorrentsInDir(path); + QTimer::singleShot(2000, this, [this, path]() { processTorrentsInDir(path); }); } #ifndef Q_OS_WIN From 1876dbd523e999deb2086f0905ed5e5f82ab21f9 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 19 Mar 2018 15:04:15 +0800 Subject: [PATCH 6/8] Fix typo --- src/base/filesystemwatcher.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index b5f9b2308..1ed41c0c9 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -104,7 +104,7 @@ void FileSystemWatcher::addPath(const QString &path) #endif // Normal mode - qDebug("FS Watching is watching %s in normal mode", qUtf8Printable(path)); + qDebug("FS Watcher is watching %s in normal mode", qUtf8Printable(path)); QFileSystemWatcher::addPath(path); scanLocalFolder(path); } From bfbd978d3f1f84dd3eaf4ee25e47469239884a2c Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 19 Mar 2018 15:32:38 +0800 Subject: [PATCH 7/8] Move helper function to Utils::Fs --- src/base/filesystemwatcher.cpp | 41 +++++----------------------------- src/base/filesystemwatcher.h | 3 --- src/base/utils/fs.cpp | 35 +++++++++++++++++++++++++++-- src/base/utils/fs.h | 4 ++++ 4 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index 1ed41c0c9..a7667b247 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -28,29 +28,23 @@ #include "filesystemwatcher.h" -#include - #if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) #include #include #include -#elif !defined Q_OS_WIN && !defined Q_OS_HAIKU -#include #endif -#include "algorithm.h" +#include + +#include "base/algorithm.h" #include "base/bittorrent/magneturi.h" #include "base/bittorrent/torrentinfo.h" #include "base/global.h" #include "base/preferences.h" +#include "base/utils/fs.h" namespace { - // usually defined in /usr/include/linux/magic.h - const unsigned long CIFS_MAGIC_NUMBER = 0xFF534D42; - const unsigned long NFS_SUPER_MAGIC = 0x6969; - const unsigned long SMB_SUPER_MAGIC = 0x517B; - const int WATCH_INTERVAL = 10000; // 10 sec const int MAX_PARTIAL_RETRIES = 5; } @@ -88,7 +82,7 @@ void FileSystemWatcher::addPath(const QString &path) if (!dir.exists()) return; // Check if the path points to a network file system or not - if (isNetworkFileSystem(path)) { + if (Utils::Fs::isNetworkFileSystem(path)) { // Network mode qDebug("Network folder detected: %s", qUtf8Printable(path)); qDebug("Using file polling mode instead of inotify..."); @@ -199,28 +193,3 @@ void FileSystemWatcher::processTorrentsInDir(const QDir &dir) m_partialTorrentTimer->start(WATCH_INTERVAL); } } - -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU -bool FileSystemWatcher::isNetworkFileSystem(const QString &path) -{ - QString file = path; - if (!file.endsWith('/')) - file += '/'; - file += '.'; - - struct statfs buf {}; - if (statfs(file.toLocal8Bit().constData(), &buf) != 0) - return false; - -#ifdef Q_OS_MAC - // XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined? - return ((strncmp(buf.f_fstypename, "nfs", sizeof(buf.f_fstypename)) == 0) - || (strncmp(buf.f_fstypename, "cifs", sizeof(buf.f_fstypename)) == 0) - || (strncmp(buf.f_fstypename, "smbfs", sizeof(buf.f_fstypename)) == 0)); -#else - return ((buf.f_type == CIFS_MAGIC_NUMBER) - || (buf.f_type == NFS_SUPER_MAGIC) - || (buf.f_type == SMB_SUPER_MAGIC)); -#endif -} -#endif diff --git a/src/base/filesystemwatcher.h b/src/base/filesystemwatcher.h index fdb4ed796..acc8203ce 100644 --- a/src/base/filesystemwatcher.h +++ b/src/base/filesystemwatcher.h @@ -64,9 +64,6 @@ protected slots: private: void processTorrentsInDir(const QDir &dir); -#if !defined Q_OS_WIN && !defined Q_OS_HAIKU - static bool isNetworkFileSystem(const QString &path); -#endif #ifndef Q_OS_WIN diff --git a/src/base/utils/fs.cpp b/src/base/utils/fs.cpp index 54349498f..eee398a57 100644 --- a/src/base/utils/fs.cpp +++ b/src/base/utils/fs.cpp @@ -31,8 +31,6 @@ #include "fs.h" #include -#include -#include #include #include @@ -42,6 +40,9 @@ #include #include +#include +#include + #if defined(Q_OS_WIN) #include #elif defined(Q_OS_MAC) || defined(Q_OS_FREEBSD) @@ -301,3 +302,33 @@ bool Utils::Fs::isRegularFile(const QString &path) return (st.st_mode & S_IFMT) == S_IFREG; } + +#if !defined Q_OS_WIN && !defined Q_OS_HAIKU +bool Utils::Fs::isNetworkFileSystem(const QString &path) +{ + QString file = path; + if (!file.endsWith('/')) + file += '/'; + file += '.'; + + struct statfs buf {}; + if (statfs(file.toLocal8Bit().constData(), &buf) != 0) + return false; + +#ifdef Q_OS_MAC + // XXX: should we make sure HAVE_STRUCT_FSSTAT_F_FSTYPENAME is defined? + return ((strncmp(buf.f_fstypename, "nfs", sizeof(buf.f_fstypename)) == 0) + || (strncmp(buf.f_fstypename, "cifs", sizeof(buf.f_fstypename)) == 0) + || (strncmp(buf.f_fstypename, "smbfs", sizeof(buf.f_fstypename)) == 0)); +#else + // usually defined in /usr/include/linux/magic.h + const unsigned long CIFS_MAGIC_NUMBER = 0xFF534D42; + const unsigned long NFS_SUPER_MAGIC = 0x6969; + const unsigned long SMB_SUPER_MAGIC = 0x517B; + + return ((buf.f_type == CIFS_MAGIC_NUMBER) + || (buf.f_type == NFS_SUPER_MAGIC) + || (buf.f_type == SMB_SUPER_MAGIC)); +#endif +} +#endif diff --git a/src/base/utils/fs.h b/src/base/utils/fs.h index 14265fc13..9c70477d3 100644 --- a/src/base/utils/fs.h +++ b/src/base/utils/fs.h @@ -63,6 +63,10 @@ namespace Utils void removeDirRecursive(const QString &path); QString tempPath(); + +#if !defined Q_OS_WIN && !defined Q_OS_HAIKU + bool isNetworkFileSystem(const QString &path); +#endif } } From 65921eaf7b8f5f2a7a1ab7cbac567db54c943a84 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 19 Mar 2018 19:20:04 +0800 Subject: [PATCH 8/8] Remove QPointer wrapper --- src/base/filesystemwatcher.cpp | 32 +++++++++++--------------------- src/base/filesystemwatcher.h | 10 ++++------ 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/src/base/filesystemwatcher.cpp b/src/base/filesystemwatcher.cpp index a7667b247..78efa4693 100644 --- a/src/base/filesystemwatcher.cpp +++ b/src/base/filesystemwatcher.cpp @@ -53,14 +53,13 @@ FileSystemWatcher::FileSystemWatcher(QObject *parent) : QFileSystemWatcher(parent) { connect(this, &QFileSystemWatcher::directoryChanged, this, &FileSystemWatcher::scanLocalFolder); -} -FileSystemWatcher::~FileSystemWatcher() -{ + m_partialTorrentTimer.setSingleShot(true); + connect(&m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents); + #ifndef Q_OS_WIN - delete m_watchTimer; + connect(&m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders); #endif - delete m_partialTorrentTimer; } QStringList FileSystemWatcher::directories() const @@ -87,12 +86,8 @@ void FileSystemWatcher::addPath(const QString &path) qDebug("Network folder detected: %s", qUtf8Printable(path)); qDebug("Using file polling mode instead of inotify..."); m_watchedFolders << dir; - // Set up the watch timer - if (!m_watchTimer) { - m_watchTimer = new QTimer(this); - connect(m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders); - m_watchTimer->start(WATCH_INTERVAL); - } + + m_watchTimer.start(WATCH_INTERVAL); return; } #endif @@ -108,7 +103,7 @@ void FileSystemWatcher::removePath(const QString &path) #ifndef Q_OS_WIN if (m_watchedFolders.removeOne(path)) { if (m_watchedFolders.isEmpty()) - delete m_watchTimer; + m_watchTimer.stop(); return; } #endif @@ -155,13 +150,12 @@ void FileSystemWatcher::processPartialTorrents() // Stop the partial timer if necessary if (m_partialTorrents.empty()) { - m_partialTorrentTimer->stop(); - m_partialTorrentTimer->deleteLater(); + m_partialTorrentTimer.stop(); qDebug("No longer any partial torrent."); } else { qDebug("Still %d partial torrents after delayed processing.", m_partialTorrents.count()); - m_partialTorrentTimer->start(WATCH_INTERVAL); + m_partialTorrentTimer.start(WATCH_INTERVAL); } // Notify of new torrents @@ -186,10 +180,6 @@ void FileSystemWatcher::processTorrentsInDir(const QDir &dir) if (!torrents.empty()) emit torrentsAdded(torrents); - if (!m_partialTorrents.empty() && !m_partialTorrentTimer) { - m_partialTorrentTimer = new QTimer(this); - connect(m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents); - m_partialTorrentTimer->setSingleShot(true); - m_partialTorrentTimer->start(WATCH_INTERVAL); - } + if (!m_partialTorrents.empty() && !m_partialTorrentTimer.isActive()) + m_partialTorrentTimer.start(WATCH_INTERVAL); } diff --git a/src/base/filesystemwatcher.h b/src/base/filesystemwatcher.h index acc8203ce..5079659f6 100644 --- a/src/base/filesystemwatcher.h +++ b/src/base/filesystemwatcher.h @@ -32,7 +32,6 @@ #include #include #include -#include #include #include @@ -46,7 +45,6 @@ class FileSystemWatcher : public QFileSystemWatcher public: explicit FileSystemWatcher(QObject *parent = nullptr); - ~FileSystemWatcher(); QStringList directories() const; void addPath(const QString &path); @@ -65,14 +63,14 @@ protected slots: private: void processTorrentsInDir(const QDir &dir); + // Partial torrents + QHash m_partialTorrents; + QTimer m_partialTorrentTimer; #ifndef Q_OS_WIN QList m_watchedFolders; - QPointer m_watchTimer; + QTimer m_watchTimer; #endif - // Partial torrents - QHash m_partialTorrents; - QPointer m_partialTorrentTimer; }; #endif // FILESYSTEMWATCHER_H