39 #include <sys/types.h>
43 #elif defined(Q_OS_MACOS) || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD)
44 #include <sys/param.h>
45 #include <sys/mount.h>
46 #elif defined(Q_OS_HAIKU)
47 #include <kernel/fs_info.h>
55 #include <QDirIterator>
58 #include <QMimeDatabase>
59 #include <QStorageInfo>
60 #include <QRegularExpression>
66 return QDir::toNativeSeparators(path);
71 return QDir::fromNativeSeparators(path);
76 Q_ASSERT(QDir::isRelativePath(relativePath));
77 Q_ASSERT(QDir::isAbsolutePath(basePath));
79 return (relativePath.isEmpty() ? basePath : QDir(basePath).absoluteFilePath(relativePath));
84 return QMimeDatabase().suffixForFileName(filename);
90 const int slashIndex = path.lastIndexOf(
'/');
93 return path.mid(slashIndex + 1);
99 const int slashIndex = path.lastIndexOf(
'/');
100 if (slashIndex == -1)
102 return path.left(slashIndex);
116 if (path.isEmpty() || !QDir(path).exists())
119 const QStringList deleteFilesList =
122 QLatin1String(
"Thumbs.db"),
123 QLatin1String(
"desktop.ini"),
125 QLatin1String(
".directory"),
127 QLatin1String(
".DS_Store")
131 QStringList dirList(path +
'/');
132 QDirIterator iter(path, (QDir::AllDirs | QDir::NoDotAndDotDot), QDirIterator::Subdirectories);
133 while (iter.hasNext())
134 dirList << iter.next() +
'/';
136 std::sort(dirList.begin(), dirList.end()
137 , [](
const QString &l,
const QString &r) { return l.count(
'/') > r.count(
'/'); });
139 for (
const QString &p :
asConst(dirList))
144 if (!dir.isEmpty(QDir::Dirs | QDir::NoDotAndDotDot))
147 const QStringList tmpFileList = dir.entryList(QDir::Files);
151 const bool hasOtherFiles = std::any_of(tmpFileList.cbegin(), tmpFileList.cend(), [&deleteFilesList](
const QString &
f)
153 return (!f.endsWith(
'~') && !deleteFilesList.contains(f, Qt::CaseInsensitive));
158 for (
const QString &
f : tmpFileList)
165 return QDir(path).exists();
179 f.setPermissions(
f.permissions() | QFile::ReadOwner | QFile::WriteOwner | QFile::ReadUser | QFile::WriteUser);
190 QDir(path).removeRecursively();
202 const QFileInfo fi(path);
203 if (!fi.exists())
return -1;
204 if (fi.isFile())
return fi.size();
208 QDirIterator iter(path, QDir::Files | QDir::Hidden | QDir::NoSymLinks, QDirIterator::Subdirectories);
209 while (iter.hasNext())
212 size += iter.fileInfo().size();
222 QFile
f1(path1),
f2(path2);
223 if (!
f1.exists() || !
f2.exists())
return false;
224 if (
f1.size() !=
f2.size())
return false;
225 if (!
f1.open(QIODevice::ReadOnly))
return false;
226 if (!
f2.open(QIODevice::ReadOnly))
return false;
228 const int readSize = 1024 * 1024;
229 while (!
f1.atEnd() && !
f2.atEnd())
231 if (
f1.read(readSize) !=
f2.read(readSize))
239 const QRegularExpression regex(allowSeparators ?
"[:?\"*<>|]+" :
"[\\\\/:?\"*<>|]+");
241 QString validName = name.trimmed();
242 validName.replace(regex, pad);
243 qDebug() <<
"toValidFileSystemName:" << name <<
"=>" << validName;
250 if (name.isEmpty())
return false;
252 #if defined(Q_OS_WIN)
253 const QRegularExpression regex
255 ? QLatin1String(
"[:?\"*<>|]")
256 : QLatin1String(
"[\\\\/:?\"*<>|]")};
257 #elif defined(Q_OS_MACOS)
258 const QRegularExpression regex
260 ? QLatin1String(
"[\\0:]")
261 : QLatin1String(
"[\\0/:]")};
263 const QRegularExpression regex
265 ? QLatin1String(
"[\\0]")
266 : QLatin1String(
"[\\0/]")};
268 return !name.contains(regex);
273 return QStorageInfo(path).bytesAvailable();
279 if (ret.endsWith(
'/'))
281 const int slashIndex = ret.lastIndexOf(
'/');
285 *removed = ret.mid(slashIndex + 1);
286 ret = ret.left(slashIndex);
293 #if defined(Q_OS_UNIX) || defined(Q_WS_QWS)
294 return QString::compare(first, second, Qt::CaseSensitive) == 0;
296 return QString::compare(first, second, Qt::CaseInsensitive) == 0;
302 const QString ret = path.trimmed();
306 return QDir::cleanPath(ret);
324 if (::stat(path.toUtf8().constData(), &st) != 0)
327 const auto err = errno;
328 qDebug(
"Could not get file stats for path '%s'. Error: %s"
329 , qUtf8Printable(path), qUtf8Printable(strerror(err)));
333 return (st.st_mode & S_IFMT) == S_IFREG;
336 #if !defined Q_OS_HAIKU
339 #if defined(Q_OS_WIN)
340 const std::wstring pathW {path.toStdWString()};
341 auto volumePath = std::make_unique<wchar_t[]>(path.length() + 1);
342 if (!::GetVolumePathNameW(pathW.c_str(), volumePath.get(), (path.length() + 1)))
344 return (::GetDriveTypeW(volumePath.get()) == DRIVE_REMOTE);
347 if (!
file.endsWith(
'/'))
351 struct statfs buf {};
352 if (statfs(
file.toLocal8Bit().constData(), &buf) != 0)
355 #if defined(Q_OS_OPENBSD)
356 return ((strncmp(buf.f_fstypename,
"cifs",
sizeof(buf.f_fstypename)) == 0)
357 || (strncmp(buf.f_fstypename,
"nfs",
sizeof(buf.f_fstypename)) == 0)
358 || (strncmp(buf.f_fstypename,
"smbfs",
sizeof(buf.f_fstypename)) == 0));
362 switch (
static_cast<quint32
>(buf.f_type))
406 for (
const QString &filePath : filePaths)
408 const auto filePathElements = QStringView(filePath).split(u
'/');
410 if (filePathElements.count() <= 1)
413 if (rootFolder.isEmpty())
414 rootFolder = filePathElements.at(0).toString();
415 else if (rootFolder != filePathElements.at(0))
425 if (commonRootFolder.isEmpty())
428 for (QString &filePath : filePaths)
429 filePath = filePath.mid(commonRootFolder.size() + 1);
434 Q_ASSERT(!rootFolder.isEmpty());
436 for (QString &filePath : filePaths)
437 filePath = rootFolder + QLatin1Char(
'/') + filePath;
void f1(struct fred_t *p)
constexpr std::add_const_t< T > & asConst(T &t) noexcept
bool isRegularFile(const QString &path)
bool sameFiles(const QString &path1, const QString &path2)
bool isNetworkFileSystem(const QString &path)
qint64 freeDiskSpaceOnPath(const QString &path)
QString folderName(const QString &filePath)
bool sameFileNames(const QString &first, const QString &second)
QString fileName(const QString &filePath)
QString toValidFileSystemName(const QString &name, bool allowSeparators=false, const QString &pad=QLatin1String(" "))
void stripRootFolder(QStringList &filePaths)
QString resolvePath(const QString &relativePath, const QString &basePath)
void removeDirRecursive(const QString &path)
qint64 computePathSize(const QString &path)
QString fileExtension(const QString &filename)
QString findRootFolder(const QStringList &filePaths)
void addRootFolder(QStringList &filePaths, const QString &name)
bool isValidFileSystemName(const QString &name, bool allowSeparators=false)
QString toUniformPath(const QString &path)
QString branchPath(const QString &filePath, QString *removed=nullptr)
QString expandPathAbs(const QString &path)
bool smartRemoveEmptyFolderTree(const QString &path)
bool forceRemove(const QString &filePath)
QString expandPath(const QString &path)
QString toNativePath(const QString &path)
file(GLOB QBT_TS_FILES "${qBittorrent_SOURCE_DIR}/src/lang/*.ts") set_source_files_properties($