From 727d20cc929dcc8d5a897d853aa1c3ca8c87bfa5 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Fri, 22 Jul 2022 18:36:52 +0800 Subject: [PATCH 1/4] Simplify implementation This also enable each platform to provide its own optimal implementation of it. --- src/base/path.cpp | 9 +++++++++ src/base/path.h | 3 +++ src/base/utils/fs.cpp | 16 ++++------------ 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/base/path.cpp b/src/base/path.cpp index dee1c50c4..66270154c 100644 --- a/src/base/path.cpp +++ b/src/base/path.cpp @@ -218,6 +218,15 @@ QString Path::toString() const return QDir::toNativeSeparators(m_pathStr); } +std::filesystem::path Path::toStdFsPath() const +{ +#ifdef Q_OS_WIN + return {data().toStdWString(), std::filesystem::path::format::generic_format}; +#else + return {data().toStdString(), std::filesystem::path::format::generic_format}; +#endif +} + Path &Path::operator/=(const Path &other) { *this = *this / other; diff --git a/src/base/path.h b/src/base/path.h index 6fbb94604..1b9e95198 100644 --- a/src/base/path.h +++ b/src/base/path.h @@ -29,6 +29,8 @@ #pragma once +#include + #include #include #include @@ -69,6 +71,7 @@ public: QString data() const; QString toString() const override; + std::filesystem::path toStdFsPath() const; Path &operator/=(const Path &other); Path &operator+=(QStringView str); diff --git a/src/base/utils/fs.cpp b/src/base/utils/fs.cpp index 044b7d54d..ac99e40fe 100644 --- a/src/base/utils/fs.cpp +++ b/src/base/utils/fs.cpp @@ -31,6 +31,7 @@ #include #include +#include #if defined(Q_OS_WIN) #include @@ -57,8 +58,8 @@ #include #include #include -#include #include +#include #include "base/global.h" #include "base/path.h" @@ -214,17 +215,8 @@ Path Utils::Fs::tempPath() bool Utils::Fs::isRegularFile(const Path &path) { - struct ::stat st; - if (::stat(path.toString().toUtf8().constData(), &st) != 0) - { - // analyse erno and log the error - const auto err = errno; - qDebug("Could not get file stats for path '%s'. Error: %s" - , qUtf8Printable(path.toString()), strerror(err)); - return false; - } - - return (st.st_mode & S_IFMT) == S_IFREG; + std::error_code ec; + return std::filesystem::is_regular_file(path.toStdFsPath(), ec); } bool Utils::Fs::isNetworkFileSystem(const Path &path) From 50b01ed45d6d680f8bafc7d396a5f2bc980da4c7 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Fri, 22 Jul 2022 20:33:52 +0800 Subject: [PATCH 2/4] Revise function for checking "same file" --- src/base/utils/fs.cpp | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/base/utils/fs.cpp b/src/base/utils/fs.cpp index ac99e40fe..ae0ed75ee 100644 --- a/src/base/utils/fs.cpp +++ b/src/base/utils/fs.cpp @@ -162,15 +162,23 @@ qint64 Utils::Fs::computePathSize(const Path &path) /** * Makes deep comparison of two files to make sure they are identical. + * The point is about the file contents. If the files do not exist then + * the paths refers to nothing and therefore we cannot say the files are same + * (because there are no files!) */ bool Utils::Fs::sameFiles(const Path &path1, const Path &path2) { QFile f1 {path1.data()}; QFile f2 {path2.data()}; - if (!f1.exists() || !f2.exists()) return false; - if (f1.size() != f2.size()) return false; - if (!f1.open(QIODevice::ReadOnly)) return false; - if (!f2.open(QIODevice::ReadOnly)) return false; + + if (!f1.exists() || !f2.exists()) + return false; + if (path1 == path2) + return true; + if (f1.size() != f2.size()) + return false; + if (!f1.open(QIODevice::ReadOnly) || !f2.open(QIODevice::ReadOnly)) + return false; const int readSize = 1024 * 1024; // 1 MiB while (!f1.atEnd() && !f2.atEnd()) From 88d9e82fc9d857b9738f217e42b10c7c4adb3c0e Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sat, 23 Jul 2022 12:27:00 +0800 Subject: [PATCH 3/4] Improve free disk space reporting For non-existent directories (which will be created on demand) `Utils::Fs::freeDiskSpaceOnPath` will return invalid value so instead query its parent path. --- src/gui/addnewtorrentdialog.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/gui/addnewtorrentdialog.cpp b/src/gui/addnewtorrentdialog.cpp index bf300e987..5d682e28a 100644 --- a/src/gui/addnewtorrentdialog.cpp +++ b/src/gui/addnewtorrentdialog.cpp @@ -135,6 +135,22 @@ namespace return -1; } + qint64 queryFreeDiskSpace(const Path &path) + { + const Path root = path.rootItem(); + Path current = path; + qint64 freeSpace = Utils::Fs::freeDiskSpaceOnPath(current); + + // for non-existent directories (which will be created on demand) `Utils::Fs::freeDiskSpaceOnPath` + // will return invalid value so instead query its parent/ancestor paths + while ((freeSpace < 0) && (current != root)) + { + current = current.parentPath(); + freeSpace = Utils::Fs::freeDiskSpaceOnPath(current); + } + return freeSpace; + } + void setPath(FileSystemPathComboEdit *fsPathEdit, const Path &newPath) { int existingIndex = indexOfPath(fsPathEdit, newPath); @@ -530,9 +546,10 @@ void AddNewTorrentDialog::updateDiskSpaceLabel() } } + const QString freeSpace = Utils::Misc::friendlyUnit(queryFreeDiskSpace(m_ui->savePath->selectedPath())); const QString sizeString = tr("%1 (Free space on disk: %2)").arg( ((torrentSize > 0) ? Utils::Misc::friendlyUnit(torrentSize) : tr("Not available", "This size is unavailable.")) - , Utils::Misc::friendlyUnit(Utils::Fs::freeDiskSpaceOnPath(m_ui->savePath->selectedPath()))); + , freeSpace); m_ui->labelSizeData->setText(sizeString); } From 5d1115f5910814c62f4e561ea496fdb70196c9d6 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Sat, 23 Jul 2022 13:18:18 +0800 Subject: [PATCH 4/4] Remove compile-time conditional This checking should be universally applied and not limited to certain OS. --- src/webui/webapplication.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index af2bee65a..bc161e17e 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -165,14 +165,12 @@ void WebApplication::sendWebUIFile() if (m_isAltUIUsed) { -#ifdef Q_OS_UNIX if (!Utils::Fs::isRegularFile(localPath)) { status(500, u"Internal Server Error"_qs); print(tr("Unacceptable file type, only regular file is allowed."), Http::CONTENT_TYPE_TXT); return; } -#endif QFileInfo fileInfo {localPath.data()}; while (Path(fileInfo.filePath()) != m_rootFolder)