QStorageInfo: Add support for obtaining subvolume names
[ChangeLog][QtCore][QStorageInfo] Added QStorageInfo::subvolume(), which returns the name of the subvolume of a volume that was mounted, if one was detected. This is currently implemented only for btrfs on Linux. Change-Id: Ib57b52598e2f452985e9fffd1459f3145d733ce5 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
6cabb18bc2
commit
590ca43603
@ -260,13 +260,33 @@ QByteArray QStorageInfo::fileSystemType() const
|
||||
devpath like \c /dev/sda0 for local storages. On Windows, it returns the UNC
|
||||
path starting with \c \\\\?\\ for local storages (in other words, the volume GUID).
|
||||
|
||||
\sa rootPath()
|
||||
\sa rootPath(), subvolume()
|
||||
*/
|
||||
QByteArray QStorageInfo::device() const
|
||||
{
|
||||
return d->device;
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.8
|
||||
Returns the subvolume name for this volume.
|
||||
|
||||
Some filesystem types allow multiple subvolumes inside one device, which
|
||||
may be mounted in different paths. If the subvolume could be detected, it
|
||||
is returned here. The format of the subvolume name is specific to each
|
||||
filesystem type.
|
||||
|
||||
If this volume was not mounted from a subvolume of a larger filesystem or
|
||||
if the subvolume could not be detected, this function returns an empty byte
|
||||
array.
|
||||
|
||||
\sa device()
|
||||
*/
|
||||
QByteArray QStorageInfo::subvolume() const
|
||||
{
|
||||
return d->subvolume;
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the human-readable name of a filesystem, usually called \c label.
|
||||
|
||||
|
@ -71,6 +71,7 @@ public:
|
||||
|
||||
QString rootPath() const;
|
||||
QByteArray device() const;
|
||||
QByteArray subvolume() const;
|
||||
QByteArray fileSystemType() const;
|
||||
QString name() const;
|
||||
QString displayName() const;
|
||||
@ -100,7 +101,7 @@ inline bool operator==(const QStorageInfo &first, const QStorageInfo &second)
|
||||
{
|
||||
if (first.d == second.d)
|
||||
return true;
|
||||
return first.device() == second.device();
|
||||
return first.device() == second.device() && first.rootPath() == second.rootPath();
|
||||
}
|
||||
|
||||
inline bool operator!=(const QStorageInfo &first, const QStorageInfo &second)
|
||||
|
@ -85,6 +85,7 @@ protected:
|
||||
public:
|
||||
QString rootPath;
|
||||
QByteArray device;
|
||||
QByteArray subvolume;
|
||||
QByteArray fileSystemType;
|
||||
QString name;
|
||||
|
||||
|
@ -120,6 +120,7 @@ public:
|
||||
inline QString rootPath() const;
|
||||
inline QByteArray fileSystemType() const;
|
||||
inline QByteArray device() const;
|
||||
inline QByteArray options() const;
|
||||
private:
|
||||
#if defined(Q_OS_BSD4)
|
||||
QT_STATFSBUF *stat_buf;
|
||||
@ -133,6 +134,7 @@ private:
|
||||
QByteArray m_rootPath;
|
||||
QByteArray m_fileSystemType;
|
||||
QByteArray m_device;
|
||||
QByteArray m_options;
|
||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
|
||||
FILE *fp;
|
||||
mntent mnt;
|
||||
@ -228,6 +230,11 @@ inline QByteArray QStorageIterator::device() const
|
||||
return QByteArray(stat_buf[currentIndex].f_mntfromname);
|
||||
}
|
||||
|
||||
inline QByteArray QStorageIterator::options() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_SOLARIS)
|
||||
|
||||
static const char pathMounted[] = "/etc/mnttab";
|
||||
@ -301,6 +308,7 @@ inline bool QStorageIterator::next()
|
||||
m_device = data.at(0);
|
||||
m_rootPath = data.at(1);
|
||||
m_fileSystemType = data.at(2);
|
||||
m_options = data.at(3);
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -320,6 +328,11 @@ inline QByteArray QStorageIterator::device() const
|
||||
return m_device;
|
||||
}
|
||||
|
||||
inline QByteArray QStorageIterator::options() const
|
||||
{
|
||||
return m_options;
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
|
||||
|
||||
static const char pathMounted[] = "/etc/mtab";
|
||||
@ -363,6 +376,11 @@ inline QByteArray QStorageIterator::device() const
|
||||
return QByteArray(mnt.mnt_fsname);
|
||||
}
|
||||
|
||||
inline QByteArray QStorageIterator::options() const
|
||||
{
|
||||
return QByteArray(mnt.mnt_opts);
|
||||
}
|
||||
|
||||
#elif defined(Q_OS_HAIKU)
|
||||
inline QStorageIterator::QStorageIterator()
|
||||
{
|
||||
@ -420,6 +438,11 @@ inline QByteArray QStorageIterator::device() const
|
||||
return m_device;
|
||||
}
|
||||
|
||||
inline QByteArray QStorageIterator::options() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline QStorageIterator::QStorageIterator()
|
||||
@ -455,8 +478,35 @@ inline QByteArray QStorageIterator::device() const
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
inline QByteArray QStorageIterator::options() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static QByteArray extractSubvolume(const QStorageIterator &it)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
if (it.fileSystemType() == "btrfs") {
|
||||
const QByteArrayList opts = it.options().split(',');
|
||||
QByteArray id;
|
||||
for (const QByteArray &opt : opts) {
|
||||
static const char subvol[] = "subvol=";
|
||||
static const char subvolid[] = "subvolid=";
|
||||
if (opt.startsWith(subvol))
|
||||
return std::move(opt).mid(strlen(subvol));
|
||||
if (opt.startsWith(subvolid))
|
||||
id = std::move(opt).mid(strlen(subvolid));
|
||||
}
|
||||
|
||||
// if we didn't find the subvolume name, return the subvolume ID
|
||||
return id;
|
||||
}
|
||||
#endif
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
void QStorageInfoPrivate::initRootPath()
|
||||
{
|
||||
rootPath = QFileInfo(rootPath).canonicalFilePath();
|
||||
@ -483,6 +533,7 @@ void QStorageInfoPrivate::initRootPath()
|
||||
rootPath = mountDir;
|
||||
device = it.device();
|
||||
fileSystemType = fsName;
|
||||
subvolume = extractSubvolume(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,11 +48,15 @@ void printVolumes(const QList<QStorageInfo> &volumes, int (*printer)(const char
|
||||
if (info.fileSystemType() != fsAndType)
|
||||
fsAndType += " (" + info.fileSystemType() + ')';
|
||||
|
||||
printf("%-19s R%c ", fsAndType.constData(), info.isReadOnly() ? 'O' : 'W');
|
||||
printer("%-19s R%c ", fsAndType.constData(), info.isReadOnly() ? 'O' : 'W');
|
||||
if (fsAndType.size() > 19)
|
||||
printf("\n%23s", "");
|
||||
printer("\n%23s", "");
|
||||
|
||||
printf("%10llu %10llu %5u ", info.bytesTotal() / 1024, info.bytesFree() / 1024, info.blockSize());
|
||||
printf("%-16s %s\n", qPrintable(info.name()), qPrintable(info.rootPath()));
|
||||
printer("%10llu %10llu %5u ", info.bytesTotal() / 1024, info.bytesFree() / 1024, info.blockSize());
|
||||
if (!info.subvolume().isEmpty())
|
||||
printer("subvol=%-18s ", qPrintable(info.subvolume()));
|
||||
else
|
||||
printer("%-25s ", qPrintable(info.name()));
|
||||
printer("%s\n", qPrintable(info.rootPath()));
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user