QStorageInfo: split Linux specific code to a separate source file
Much less crowded. Inline QStorageInfoPrivate::root() to ease the split; the Windows specific code is one extra line. Change-Id: Icec6822cf436e2b4aa1b3a04184fbfa40e508078 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
4fe704eff9
commit
536696196c
@ -988,7 +988,7 @@ qt_internal_extend_target(Core CONDITION APPLE AND NOT MACOS
|
|||||||
qt_internal_extend_target(Core CONDITION ANDROID
|
qt_internal_extend_target(Core CONDITION ANDROID
|
||||||
SOURCES
|
SOURCES
|
||||||
io/qstandardpaths_android.cpp
|
io/qstandardpaths_android.cpp
|
||||||
io/qstorageinfo_unix.cpp
|
io/qstorageinfo_linux.cpp
|
||||||
kernel/qjnitypes.h
|
kernel/qjnitypes.h
|
||||||
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
|
kernel/qjnienvironment.cpp kernel/qjnienvironment.h
|
||||||
kernel/qjniobject.cpp kernel/qjniobject.h
|
kernel/qjniobject.cpp kernel/qjniobject.h
|
||||||
@ -1018,12 +1018,19 @@ qt_internal_extend_target(Core CONDITION HAIKU AND NOT ANDROID
|
|||||||
be
|
be
|
||||||
)
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION UNIX AND NOT APPLE AND NOT HAIKU AND NOT ANDROID
|
qt_internal_extend_target(Core
|
||||||
|
CONDITION UNIX AND NOT LINUX AND NOT APPLE AND NOT HAIKU AND NOT ANDROID
|
||||||
SOURCES
|
SOURCES
|
||||||
io/qstandardpaths_unix.cpp
|
io/qstandardpaths_unix.cpp
|
||||||
io/qstorageinfo_unix.cpp
|
io/qstorageinfo_unix.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
qt_internal_extend_target(Core CONDITION LINUX AND NOT ANDROID
|
||||||
|
SOURCES
|
||||||
|
io/qstandardpaths_unix.cpp
|
||||||
|
io/qstorageinfo_linux.cpp
|
||||||
|
)
|
||||||
|
|
||||||
qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
|
qt_internal_extend_target(Core CONDITION QT_FEATURE_itemmodel
|
||||||
SOURCES
|
SOURCES
|
||||||
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
itemmodels/qabstractitemmodel.cpp itemmodels/qabstractitemmodel.h itemmodels/qabstractitemmodel_p.h
|
||||||
|
172
src/corelib/io/qstorageinfo_linux.cpp
Normal file
172
src/corelib/io/qstorageinfo_linux.cpp
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
// Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
// Copyright (C) 2014 Ivan Komissarov <ABBAPOH@gmail.com>
|
||||||
|
// Copyright (C) 2016 Intel Corporation.
|
||||||
|
// Copyright (C) 2023 Ahmad Samir <a.samirh78@gmail.com>
|
||||||
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
#include "qstorageinfo_linux_p.h"
|
||||||
|
|
||||||
|
#include "qdiriterator.h"
|
||||||
|
#include <private/qcore_unix_p.h>
|
||||||
|
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
# include <sys/mount.h>
|
||||||
|
# include <sys/vfs.h>
|
||||||
|
# define QT_STATFS ::statfs
|
||||||
|
# define QT_STATFSBUF struct statfs
|
||||||
|
# if !defined(ST_RDONLY)
|
||||||
|
# define ST_RDONLY 1 // hack for missing define on Android
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# include <sys/statvfs.h>
|
||||||
|
# if defined(QT_LARGEFILE_SUPPORT)
|
||||||
|
# define QT_STATFSBUF struct statvfs64
|
||||||
|
# define QT_STATFS ::statvfs64
|
||||||
|
# else
|
||||||
|
# define QT_STATFSBUF struct statvfs
|
||||||
|
# define QT_STATFS ::statvfs
|
||||||
|
# endif // QT_LARGEFILE_SUPPORT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
using namespace Qt::StringLiterals;
|
||||||
|
|
||||||
|
// udev encodes the labels with ID_LABEL_FS_ENC which is done with
|
||||||
|
// blkid_encode_string(). Within this function some 1-byte utf-8
|
||||||
|
// characters not considered safe (e.g. '\' or ' ') are encoded as hex
|
||||||
|
static QString decodeFsEncString(const QString &str)
|
||||||
|
{
|
||||||
|
QString decoded;
|
||||||
|
decoded.reserve(str.size());
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
while (i < str.size()) {
|
||||||
|
if (i <= str.size() - 4) { // we need at least four characters \xAB
|
||||||
|
if (QStringView{str}.sliced(i).startsWith("\\x"_L1)) {
|
||||||
|
bool bOk;
|
||||||
|
const int code = QStringView{str}.mid(i+2, 2).toInt(&bOk, 16);
|
||||||
|
if (bOk && code >= 0x20 && code < 0x80) {
|
||||||
|
decoded += QChar(code);
|
||||||
|
i += 4;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoded += str.at(i);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
return decoded;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline QString retrieveLabel(const QByteArray &device)
|
||||||
|
{
|
||||||
|
static const char pathDiskByLabel[] = "/dev/disk/by-label";
|
||||||
|
|
||||||
|
QFileInfo devinfo(QFile::decodeName(device));
|
||||||
|
QString devicePath = devinfo.canonicalFilePath();
|
||||||
|
|
||||||
|
QDirIterator it(QLatin1StringView(pathDiskByLabel), QDir::NoDotAndDotDot);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
QFileInfo fileInfo = it.nextFileInfo();
|
||||||
|
if (fileInfo.isSymLink() && fileInfo.symLinkTarget() == devicePath)
|
||||||
|
return decodeFsEncString(fileInfo.fileName());
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QStorageInfoPrivate::doStat()
|
||||||
|
{
|
||||||
|
initRootPath();
|
||||||
|
if (rootPath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
retrieveVolumeInfo();
|
||||||
|
name = retrieveLabel(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QStorageInfoPrivate::retrieveVolumeInfo()
|
||||||
|
{
|
||||||
|
QT_STATFSBUF statfs_buf;
|
||||||
|
int result;
|
||||||
|
EINTR_LOOP(result, QT_STATFS(QFile::encodeName(rootPath).constData(), &statfs_buf));
|
||||||
|
if (result == 0) {
|
||||||
|
valid = true;
|
||||||
|
ready = true;
|
||||||
|
|
||||||
|
bytesTotal = statfs_buf.f_blocks * statfs_buf.f_frsize;
|
||||||
|
bytesFree = statfs_buf.f_bfree * statfs_buf.f_frsize;
|
||||||
|
bytesAvailable = statfs_buf.f_bavail * statfs_buf.f_frsize;
|
||||||
|
blockSize = statfs_buf.f_bsize;
|
||||||
|
|
||||||
|
#if defined(Q_OS_ANDROID)
|
||||||
|
#if defined(_STATFS_F_FLAGS)
|
||||||
|
readOnly = (statfs_buf.f_flags & ST_RDONLY) != 0;
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
readOnly = (statfs_buf.f_flag & ST_RDONLY) != 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<MountInfo> parseMountInfo(FilterMountInfo filter = FilterMountInfo::All)
|
||||||
|
{
|
||||||
|
QFile file(u"/proc/self/mountinfo"_s);
|
||||||
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
QByteArray mountinfo = file.readAll();
|
||||||
|
file.close();
|
||||||
|
|
||||||
|
return doParseMountInfo(mountinfo, filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QStorageInfoPrivate::initRootPath()
|
||||||
|
{
|
||||||
|
rootPath = QFileInfo(rootPath).canonicalFilePath();
|
||||||
|
if (rootPath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::vector<MountInfo> infos = parseMountInfo();
|
||||||
|
if (infos.empty()) {
|
||||||
|
rootPath = u'/';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsizetype maxLength = 0;
|
||||||
|
const QString oldRootPath = rootPath;
|
||||||
|
rootPath.clear();
|
||||||
|
|
||||||
|
for (auto &info : infos) {
|
||||||
|
// we try to find most suitable entry
|
||||||
|
qsizetype mpSize = info.mountPoint.size();
|
||||||
|
if (isParentOf(info.mountPoint, oldRootPath) && maxLength < mpSize) {
|
||||||
|
maxLength = mpSize;
|
||||||
|
rootPath = info.mountPoint;
|
||||||
|
device = info.device;
|
||||||
|
fileSystemType = info.fsType;
|
||||||
|
subvolume = info.fsRoot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
||||||
|
{
|
||||||
|
std::vector<MountInfo> infos = parseMountInfo(FilterMountInfo::Filtered);
|
||||||
|
if (infos.empty())
|
||||||
|
return QList{root()};
|
||||||
|
|
||||||
|
QList<QStorageInfo> volumes;
|
||||||
|
for (MountInfo &info : infos) {
|
||||||
|
QStorageInfo storage(info.mountPoint);
|
||||||
|
storage.d->device = info.device;
|
||||||
|
storage.d->fileSystemType = info.fsType;
|
||||||
|
storage.d->subvolume = info.fsRoot;
|
||||||
|
if (storage.bytesTotal() == 0 && storage != root())
|
||||||
|
continue;
|
||||||
|
volumes.push_back(storage);
|
||||||
|
}
|
||||||
|
return volumes;
|
||||||
|
}
|
||||||
|
|
||||||
|
QT_END_NAMESPACE
|
@ -160,9 +160,4 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
|||||||
return volumes;
|
return volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStorageInfo QStorageInfoPrivate::root()
|
|
||||||
{
|
|
||||||
return QStorageInfo(QStringLiteral("/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#include <QtCore/qloggingcategory.h>
|
#include <QtCore/qloggingcategory.h>
|
||||||
|
#include <QtCore/qsystemdetection.h>
|
||||||
|
#include <QtCore/qtenvironmentvariables.h>
|
||||||
#include <QtCore/private/qglobal_p.h>
|
#include <QtCore/private/qglobal_p.h>
|
||||||
#include "qstorageinfo.h"
|
#include "qstorageinfo.h"
|
||||||
|
|
||||||
@ -35,7 +37,15 @@ public:
|
|||||||
void doStat();
|
void doStat();
|
||||||
|
|
||||||
static QList<QStorageInfo> mountedVolumes();
|
static QList<QStorageInfo> mountedVolumes();
|
||||||
static QStorageInfo root();
|
|
||||||
|
static QStorageInfo root()
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
return QStorageInfo(QDir::fromNativeSeparators(QFile::decodeName(qgetenv("SystemDrive"))));
|
||||||
|
#else
|
||||||
|
return QStorageInfo(QStringLiteral("/"));
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
|
@ -15,18 +15,9 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
|
||||||
# include "qstorageinfo_linux_p.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(Q_OS_BSD4)
|
#if defined(Q_OS_BSD4)
|
||||||
# include <sys/mount.h>
|
# include <sys/mount.h>
|
||||||
# include <sys/statvfs.h>
|
# include <sys/statvfs.h>
|
||||||
#elif defined(Q_OS_ANDROID)
|
|
||||||
# include <sys/mount.h>
|
|
||||||
# include <sys/vfs.h>
|
|
||||||
#elif defined(Q_OS_LINUX)
|
|
||||||
# include <sys/statvfs.h>
|
|
||||||
#elif defined(Q_OS_HURD)
|
#elif defined(Q_OS_HURD)
|
||||||
# include <mntent.h>
|
# include <mntent.h>
|
||||||
# include <sys/statvfs.h>
|
# include <sys/statvfs.h>
|
||||||
@ -60,12 +51,6 @@
|
|||||||
# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
|
# if !defined(_STATFS_F_FLAGS) && !defined(Q_OS_NETBSD)
|
||||||
# define _STATFS_F_FLAGS 1
|
# define _STATFS_F_FLAGS 1
|
||||||
# endif
|
# endif
|
||||||
#elif defined(Q_OS_ANDROID)
|
|
||||||
# define QT_STATFS ::statfs
|
|
||||||
# define QT_STATFSBUF struct statfs
|
|
||||||
# if !defined(ST_RDONLY)
|
|
||||||
# define ST_RDONLY 1 // hack for missing define on Android
|
|
||||||
# endif
|
|
||||||
#elif defined(Q_OS_HAIKU)
|
#elif defined(Q_OS_HAIKU)
|
||||||
# define QT_STATFSBUF struct statvfs
|
# define QT_STATFSBUF struct statvfs
|
||||||
# define QT_STATFS ::statvfs
|
# define QT_STATFS ::statvfs
|
||||||
@ -382,50 +367,9 @@ inline QByteArray QStorageIterator::subvolume() const
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
|
||||||
// udev encodes the labels with ID_LABEL_FS_ENC which is done with
|
|
||||||
// blkid_encode_string(). Within this function some 1-byte utf-8
|
|
||||||
// characters not considered safe (e.g. '\' or ' ') are encoded as hex
|
|
||||||
static QString decodeFsEncString(const QString &str)
|
|
||||||
{
|
|
||||||
QString decoded;
|
|
||||||
decoded.reserve(str.size());
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
while (i < str.size()) {
|
|
||||||
if (i <= str.size() - 4) { // we need at least four characters \xAB
|
|
||||||
if (QStringView{str}.sliced(i).startsWith("\\x"_L1)) {
|
|
||||||
bool bOk;
|
|
||||||
const int code = QStringView{str}.mid(i+2, 2).toInt(&bOk, 16);
|
|
||||||
if (bOk && code >= 0x20 && code < 0x80) {
|
|
||||||
decoded += QChar(code);
|
|
||||||
i += 4;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
decoded += str.at(i);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
return decoded;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline QString retrieveLabel(const QByteArray &device)
|
static inline QString retrieveLabel(const QByteArray &device)
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_LINUX
|
#if defined Q_OS_HAIKU
|
||||||
static const char pathDiskByLabel[] = "/dev/disk/by-label";
|
|
||||||
|
|
||||||
QFileInfo devinfo(QFile::decodeName(device));
|
|
||||||
QString devicePath = devinfo.canonicalFilePath();
|
|
||||||
|
|
||||||
QDirIterator it(QLatin1StringView(pathDiskByLabel), QDir::NoDotAndDotDot);
|
|
||||||
while (it.hasNext()) {
|
|
||||||
QFileInfo fileInfo = it.nextFileInfo();
|
|
||||||
if (fileInfo.isSymLink() && fileInfo.symLinkTarget() == devicePath)
|
|
||||||
return decodeFsEncString(fileInfo.fileName());
|
|
||||||
}
|
|
||||||
#elif defined Q_OS_HAIKU
|
|
||||||
fs_info fsInfo;
|
fs_info fsInfo;
|
||||||
memset(&fsInfo, 0, sizeof(fsInfo));
|
memset(&fsInfo, 0, sizeof(fsInfo));
|
||||||
|
|
||||||
@ -484,67 +428,6 @@ void QStorageInfoPrivate::retrieveVolumeInfo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_LINUX)
|
|
||||||
static std::vector<MountInfo> parseMountInfo(FilterMountInfo filter = FilterMountInfo::All)
|
|
||||||
{
|
|
||||||
QFile file(u"/proc/self/mountinfo"_s);
|
|
||||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text))
|
|
||||||
return {};
|
|
||||||
|
|
||||||
QByteArray mountinfo = file.readAll();
|
|
||||||
file.close();
|
|
||||||
|
|
||||||
return doParseMountInfo(mountinfo, filter);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QStorageInfoPrivate::initRootPath()
|
|
||||||
{
|
|
||||||
rootPath = QFileInfo(rootPath).canonicalFilePath();
|
|
||||||
if (rootPath.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::vector<MountInfo> infos = parseMountInfo();
|
|
||||||
if (infos.empty()) {
|
|
||||||
rootPath = u'/';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsizetype maxLength = 0;
|
|
||||||
const QString oldRootPath = rootPath;
|
|
||||||
rootPath.clear();
|
|
||||||
|
|
||||||
for (auto &info : infos) {
|
|
||||||
// we try to find most suitable entry
|
|
||||||
qsizetype mpSize = info.mountPoint.size();
|
|
||||||
if (isParentOf(info.mountPoint, oldRootPath) && maxLength < mpSize) {
|
|
||||||
maxLength = mpSize;
|
|
||||||
rootPath = info.mountPoint;
|
|
||||||
device = info.device;
|
|
||||||
fileSystemType = info.fsType;
|
|
||||||
subvolume = info.fsRoot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
|
||||||
{
|
|
||||||
std::vector<MountInfo> infos = parseMountInfo(FilterMountInfo::Filtered);
|
|
||||||
if (infos.empty())
|
|
||||||
return QList{root()};
|
|
||||||
|
|
||||||
QList<QStorageInfo> volumes;
|
|
||||||
for (MountInfo &info : infos) {
|
|
||||||
QStorageInfo storage(info.mountPoint);
|
|
||||||
storage.d->device = info.device;
|
|
||||||
storage.d->fileSystemType = info.fsType;
|
|
||||||
storage.d->subvolume = info.fsRoot;
|
|
||||||
if (storage.bytesTotal() == 0 && storage != root())
|
|
||||||
continue;
|
|
||||||
volumes.push_back(storage);
|
|
||||||
}
|
|
||||||
return volumes;
|
|
||||||
}
|
|
||||||
#else // defined(Q_OS_LINUX)
|
|
||||||
void QStorageInfoPrivate::initRootPath()
|
void QStorageInfoPrivate::initRootPath()
|
||||||
{
|
{
|
||||||
rootPath = QFileInfo(rootPath).canonicalFilePath();
|
rootPath = QFileInfo(rootPath).canonicalFilePath();
|
||||||
@ -600,11 +483,5 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
|||||||
|
|
||||||
return volumes;
|
return volumes;
|
||||||
}
|
}
|
||||||
#endif // defined(Q_OS_LINUX)
|
|
||||||
|
|
||||||
QStorageInfo QStorageInfoPrivate::root()
|
|
||||||
{
|
|
||||||
return QStorageInfo(QStringLiteral("/"));
|
|
||||||
}
|
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -170,11 +170,6 @@ QList<QStorageInfo> QStorageInfoPrivate::mountedVolumes()
|
|||||||
return volumes;
|
return volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStorageInfo QStorageInfoPrivate::root()
|
|
||||||
{
|
|
||||||
return QStorageInfo(QDir::fromNativeSeparators(QFile::decodeName(qgetenv("SystemDrive"))));
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QStorageInfoPrivate::queryStorageProperty()
|
bool QStorageInfoPrivate::queryStorageProperty()
|
||||||
{
|
{
|
||||||
QString path = QDir::toNativeSeparators(uR"(\\.\)" + rootPath);
|
QString path = QDir::toNativeSeparators(uR"(\\.\)" + rootPath);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user