mirror of
https://github.com/d47081/qBittorrent.git
synced 2025-01-25 22:14:32 +00:00
commit
aa122b062e
@ -1,145 +1,128 @@
|
|||||||
#include <QtGlobal>
|
/*
|
||||||
#ifndef Q_OS_WIN
|
* Bittorrent Client using Qt and libtorrent.
|
||||||
#include <QSet>
|
* Copyright (C) 2018
|
||||||
#include <iostream>
|
*
|
||||||
#include <errno.h>
|
* This program is free software; you can redistribute it and/or
|
||||||
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
* modify it under the terms of the GNU General Public License
|
||||||
#include <sys/param.h>
|
* as published by the Free Software Foundation; either version 2
|
||||||
#include <sys/mount.h>
|
* of the License, or (at your option) any later version.
|
||||||
#include <string.h>
|
*
|
||||||
#elif !defined Q_OS_HAIKU
|
* This program is distributed in the hope that it will be useful,
|
||||||
#include <sys/vfs.h>
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
#endif
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
#endif
|
* 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 "algorithm.h"
|
|
||||||
#include "base/bittorrent/magneturi.h"
|
|
||||||
#include "base/bittorrent/torrentinfo.h"
|
|
||||||
#include "base/preferences.h"
|
|
||||||
#include "filesystemwatcher.h"
|
#include "filesystemwatcher.h"
|
||||||
|
|
||||||
#ifndef CIFS_MAGIC_NUMBER
|
#if defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
||||||
#define CIFS_MAGIC_NUMBER 0xFF534D42
|
#include <cstring>
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#include <sys/param.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef NFS_SUPER_MAGIC
|
#include <QtGlobal>
|
||||||
#define NFS_SUPER_MAGIC 0x6969
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef SMB_SUPER_MAGIC
|
#include "base/algorithm.h"
|
||||||
#define SMB_SUPER_MAGIC 0x517B
|
#include "base/bittorrent/magneturi.h"
|
||||||
#endif
|
#include "base/bittorrent/torrentinfo.h"
|
||||||
|
#include "base/global.h"
|
||||||
|
#include "base/preferences.h"
|
||||||
|
#include "base/utils/fs.h"
|
||||||
|
|
||||||
const int WATCH_INTERVAL = 10000; // 10 sec
|
namespace
|
||||||
const int MAX_PARTIAL_RETRIES = 5;
|
{
|
||||||
|
const int WATCH_INTERVAL = 10000; // 10 sec
|
||||||
|
const int MAX_PARTIAL_RETRIES = 5;
|
||||||
|
}
|
||||||
|
|
||||||
FileSystemWatcher::FileSystemWatcher(QObject *parent)
|
FileSystemWatcher::FileSystemWatcher(QObject *parent)
|
||||||
: QFileSystemWatcher(parent)
|
: QFileSystemWatcher(parent)
|
||||||
{
|
{
|
||||||
m_filters << "*.torrent" << "*.magnet";
|
connect(this, &QFileSystemWatcher::directoryChanged, this, &FileSystemWatcher::scanLocalFolder);
|
||||||
connect(this, SIGNAL(directoryChanged(QString)), SLOT(scanLocalFolder(QString)));
|
|
||||||
}
|
m_partialTorrentTimer.setSingleShot(true);
|
||||||
|
connect(&m_partialTorrentTimer, &QTimer::timeout, this, &FileSystemWatcher::processPartialTorrents);
|
||||||
|
|
||||||
FileSystemWatcher::~FileSystemWatcher()
|
|
||||||
{
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
if (m_watchTimer)
|
connect(&m_watchTimer, &QTimer::timeout, this, &FileSystemWatcher::scanNetworkFolders);
|
||||||
delete m_watchTimer;
|
|
||||||
#endif
|
#endif
|
||||||
if (m_partialTorrentTimer)
|
|
||||||
delete m_partialTorrentTimer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList FileSystemWatcher::directories() const
|
QStringList FileSystemWatcher::directories() const
|
||||||
{
|
{
|
||||||
QStringList dirs;
|
QStringList dirs = QFileSystemWatcher::directories();
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
if (m_watchTimer) {
|
for (const QDir &dir : qAsConst(m_watchedFolders))
|
||||||
foreach (const QDir &dir, m_watchedFolders)
|
dirs << dir.canonicalPath();
|
||||||
dirs << dir.canonicalPath();
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
dirs << QFileSystemWatcher::directories();
|
|
||||||
return dirs;
|
return dirs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemWatcher::addPath(const QString &path)
|
void FileSystemWatcher::addPath(const QString &path)
|
||||||
{
|
{
|
||||||
|
if (path.isEmpty()) return;
|
||||||
|
|
||||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||||
QDir dir(path);
|
const QDir dir(path);
|
||||||
if (!dir.exists()) return;
|
if (!dir.exists()) return;
|
||||||
|
|
||||||
// Check if the path points to a network file system or not
|
// Check if the path points to a network file system or not
|
||||||
if (isNetworkFileSystem(path)) {
|
if (Utils::Fs::isNetworkFileSystem(path)) {
|
||||||
// Network mode
|
// Network mode
|
||||||
qDebug("Network folder detected: %s", qUtf8Printable(path));
|
qDebug("Network folder detected: %s", qUtf8Printable(path));
|
||||||
qDebug("Using file polling mode instead of inotify...");
|
qDebug("Using file polling mode instead of inotify...");
|
||||||
m_watchedFolders << dir;
|
m_watchedFolders << dir;
|
||||||
// Set up the watch timer
|
|
||||||
if (!m_watchTimer) {
|
m_watchTimer.start(WATCH_INTERVAL);
|
||||||
m_watchTimer = new QTimer(this);
|
return;
|
||||||
connect(m_watchTimer, SIGNAL(timeout()), SLOT(scanNetworkFolders()));
|
|
||||||
m_watchTimer->start(WATCH_INTERVAL); // 5 sec
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Normal mode
|
||||||
|
qDebug("FS Watcher is watching %s in normal mode", qUtf8Printable(path));
|
||||||
|
QFileSystemWatcher::addPath(path);
|
||||||
|
scanLocalFolder(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemWatcher::removePath(const QString &path)
|
void FileSystemWatcher::removePath(const QString &path)
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
QDir dir(path);
|
if (m_watchedFolders.removeOne(path)) {
|
||||||
for (int i = 0; i < m_watchedFolders.count(); ++i) {
|
if (m_watchedFolders.isEmpty())
|
||||||
if (QDir(m_watchedFolders.at(i)) == dir) {
|
m_watchTimer.stop();
|
||||||
m_watchedFolders.removeAt(i);
|
return;
|
||||||
if (m_watchedFolders.isEmpty())
|
|
||||||
delete m_watchTimer;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
// Normal mode
|
// Normal mode
|
||||||
QFileSystemWatcher::removePath(path);
|
QFileSystemWatcher::removePath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemWatcher::scanLocalFolder(QString path)
|
void FileSystemWatcher::scanLocalFolder(const QString &path)
|
||||||
{
|
{
|
||||||
qDebug("scanLocalFolder(%s) called", qUtf8Printable(path));
|
QTimer::singleShot(2000, this, [this, path]() { processTorrentsInDir(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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
void FileSystemWatcher::scanNetworkFolders()
|
void FileSystemWatcher::scanNetworkFolders()
|
||||||
{
|
{
|
||||||
#ifndef Q_OS_WIN
|
for (const QDir &dir : qAsConst(m_watchedFolders))
|
||||||
qDebug("scanNetworkFolders() called");
|
processTorrentsInDir(dir);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void FileSystemWatcher::processPartialTorrents()
|
void FileSystemWatcher::processPartialTorrents()
|
||||||
{
|
{
|
||||||
@ -157,7 +140,7 @@ void FileSystemWatcher::processPartialTorrents()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (value >= MAX_PARTIAL_RETRIES) {
|
if (value >= MAX_PARTIAL_RETRIES) {
|
||||||
QFile::rename(torrentPath, torrentPath + ".invalid");
|
QFile::rename(torrentPath, torrentPath + ".qbt_rejected");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,13 +150,12 @@ void FileSystemWatcher::processPartialTorrents()
|
|||||||
|
|
||||||
// Stop the partial timer if necessary
|
// Stop the partial timer if necessary
|
||||||
if (m_partialTorrents.empty()) {
|
if (m_partialTorrents.empty()) {
|
||||||
m_partialTorrentTimer->stop();
|
m_partialTorrentTimer.stop();
|
||||||
m_partialTorrentTimer->deleteLater();
|
|
||||||
qDebug("No longer any partial torrent.");
|
qDebug("No longer any partial torrent.");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
qDebug("Still %d partial torrents after delayed processing.", m_partialTorrents.count());
|
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
|
// Notify of new torrents
|
||||||
@ -181,99 +163,23 @@ void FileSystemWatcher::processPartialTorrents()
|
|||||||
emit torrentsAdded(noLongerPartial);
|
emit torrentsAdded(noLongerPartial);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemWatcher::startPartialTorrentTimer()
|
void FileSystemWatcher::processTorrentsInDir(const QDir &dir)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!m_partialTorrents.isEmpty());
|
QStringList torrents;
|
||||||
if (!m_partialTorrentTimer) {
|
const QStringList files = dir.entryList({"*.torrent", "*.magnet"}, QDir::Files);
|
||||||
m_partialTorrentTimer = new QTimer();
|
for (const QString &file : files) {
|
||||||
connect(m_partialTorrentTimer, SIGNAL(timeout()), SLOT(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) {
|
|
||||||
const QString fileAbsPath = dir.absoluteFilePath(file);
|
const QString fileAbsPath = dir.absoluteFilePath(file);
|
||||||
if (fileAbsPath.endsWith(".magnet")) {
|
if (file.endsWith(".magnet"))
|
||||||
torrents << fileAbsPath;
|
torrents << fileAbsPath;
|
||||||
}
|
else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid())
|
||||||
else if (BitTorrent::TorrentInfo::loadFromFile(fileAbsPath).isValid()) {
|
|
||||||
torrents << fileAbsPath;
|
torrents << fileAbsPath;
|
||||||
}
|
else if (!m_partialTorrents.contains(fileAbsPath))
|
||||||
else if (!m_partialTorrents.contains(fileAbsPath)) {
|
m_partialTorrents[fileAbsPath] = 0;
|
||||||
qDebug("Partial torrent detected at: %s", qUtf8Printable(fileAbsPath));
|
|
||||||
qDebug("Delay the file's processing...");
|
|
||||||
m_partialTorrents.insert(fileAbsPath, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_partialTorrents.empty())
|
if (!torrents.empty())
|
||||||
startPartialTorrentTimer();
|
emit torrentsAdded(torrents);
|
||||||
|
|
||||||
|
if (!m_partialTorrents.empty() && !m_partialTorrentTimer.isActive())
|
||||||
|
m_partialTorrentTimer.start(WATCH_INTERVAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
|
||||||
bool FileSystemWatcher::isNetworkFileSystem(QString path)
|
|
||||||
{
|
|
||||||
QString file = path;
|
|
||||||
if (!file.endsWith("/"))
|
|
||||||
file += "/";
|
|
||||||
file += ".";
|
|
||||||
struct statfs buf;
|
|
||||||
if (!statfs(file.toLocal8Bit().constData(), &buf)) {
|
|
||||||
#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));
|
|
||||||
#else
|
|
||||||
return ((buf.f_type == static_cast<long>(CIFS_MAGIC_NUMBER))
|
|
||||||
|| (buf.f_type == static_cast<long>(NFS_SUPER_MAGIC))
|
|
||||||
|| (buf.f_type == static_cast<long>(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
|
|
||||||
|
@ -1,10 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* 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
|
#ifndef FILESYSTEMWATCHER_H
|
||||||
#define FILESYSTEMWATCHER_H
|
#define FILESYSTEMWATCHER_H
|
||||||
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
#include <QHash>
|
#include <QHash>
|
||||||
#include <QPointer>
|
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
@ -18,7 +45,6 @@ class FileSystemWatcher : public QFileSystemWatcher
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FileSystemWatcher(QObject *parent = nullptr);
|
explicit FileSystemWatcher(QObject *parent = nullptr);
|
||||||
~FileSystemWatcher();
|
|
||||||
|
|
||||||
QStringList directories() const;
|
QStringList directories() const;
|
||||||
void addPath(const QString &path);
|
void addPath(const QString &path);
|
||||||
@ -28,25 +54,23 @@ signals:
|
|||||||
void torrentsAdded(const QStringList &pathList);
|
void torrentsAdded(const QStringList &pathList);
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void scanLocalFolder(QString path);
|
void scanLocalFolder(const QString &path);
|
||||||
void scanNetworkFolders();
|
|
||||||
void processPartialTorrents();
|
void processPartialTorrents();
|
||||||
|
#ifndef Q_OS_WIN
|
||||||
|
void scanNetworkFolders();
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void startPartialTorrentTimer();
|
void processTorrentsInDir(const QDir &dir);
|
||||||
void addTorrentsFromDir(const QDir &dir, QStringList &torrents);
|
|
||||||
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
// Partial torrents
|
||||||
static bool isNetworkFileSystem(QString path);
|
QHash<QString, int> m_partialTorrents;
|
||||||
#endif
|
QTimer m_partialTorrentTimer;
|
||||||
|
|
||||||
#ifndef Q_OS_WIN
|
#ifndef Q_OS_WIN
|
||||||
QList<QDir> m_watchedFolders;
|
QList<QDir> m_watchedFolders;
|
||||||
QPointer<QTimer> m_watchTimer;
|
QTimer m_watchTimer;
|
||||||
#endif
|
#endif
|
||||||
QStringList m_filters;
|
|
||||||
// Partial torrents
|
|
||||||
QHash<QString, int> m_partialTorrents;
|
|
||||||
QPointer<QTimer> m_partialTorrentTimer;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FILESYSTEMWATCHER_H
|
#endif // FILESYSTEMWATCHER_H
|
||||||
|
@ -31,8 +31,6 @@
|
|||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
@ -42,6 +40,9 @@
|
|||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QStorageInfo>
|
#include <QStorageInfo>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
#elif defined(Q_OS_MAC) || defined(Q_OS_FREEBSD)
|
#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;
|
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
|
||||||
|
@ -63,6 +63,10 @@ namespace Utils
|
|||||||
void removeDirRecursive(const QString &path);
|
void removeDirRecursive(const QString &path);
|
||||||
|
|
||||||
QString tempPath();
|
QString tempPath();
|
||||||
|
|
||||||
|
#if !defined Q_OS_WIN && !defined Q_OS_HAIKU
|
||||||
|
bool isNetworkFileSystem(const QString &path);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user