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..ae0ed75ee 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" @@ -161,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()) @@ -214,17 +223,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) 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); } 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)