QStorageInfo/Linux: resolve non-existent devices via /dev/block
On systems with very simple boot sequences, the kernel will create a device called /dev/root and use that to mount the root filesystem. However, that doesn't actually exist in /dev and could cause confusion. So we try to resolve using /dev/block if the /dev entry does not exist but udev is in use (udevd has the string "/dev/%s/%u:%u"). [ChangeLog][QtCore][QStorageInfo] Improved discovery of device nodes on Linux if the /dev entry was renamed after the filesystem was mounted and udev is in use. Fixes: QTBUG-81464 Change-Id: If79a52e476594446baccfffd15eec573ae3deb0d Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
6b9a1824a4
commit
23d42a6a30
@ -60,6 +60,7 @@
|
|||||||
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
|
#elif defined(Q_OS_LINUX) || defined(Q_OS_HURD)
|
||||||
# include <mntent.h>
|
# include <mntent.h>
|
||||||
# include <sys/statvfs.h>
|
# include <sys/statvfs.h>
|
||||||
|
# include <sys/sysmacros.h>
|
||||||
#elif defined(Q_OS_SOLARIS)
|
#elif defined(Q_OS_SOLARIS)
|
||||||
# include <sys/mnttab.h>
|
# include <sys/mnttab.h>
|
||||||
# include <sys/statvfs.h>
|
# include <sys/statvfs.h>
|
||||||
@ -152,7 +153,7 @@ private:
|
|||||||
//(2) parent ID: the ID of the parent mount (or of self for the top of the mount tree).
|
//(2) parent ID: the ID of the parent mount (or of self for the top of the mount tree).
|
||||||
// int parent_id;
|
// int parent_id;
|
||||||
//(3) major:minor: the value of st_dev for files on this filesystem (see stat(2)).
|
//(3) major:minor: the value of st_dev for files on this filesystem (see stat(2)).
|
||||||
// dev_t rdev;
|
dev_t rdev;
|
||||||
//(4) root: the pathname of the directory in the filesystem which forms the root of this mount.
|
//(4) root: the pathname of the directory in the filesystem which forms the root of this mount.
|
||||||
char *subvolume;
|
char *subvolume;
|
||||||
//(5) mount point: the pathname of the mount point relative to the process's root directory.
|
//(5) mount point: the pathname of the mount point relative to the process's root directory.
|
||||||
@ -503,8 +504,7 @@ inline bool QStorageIterator::next()
|
|||||||
int rdevminor = qstrtoll(ptr + 1, const_cast<const char **>(&ptr), 10, &ok);
|
int rdevminor = qstrtoll(ptr + 1, const_cast<const char **>(&ptr), 10, &ok);
|
||||||
if (!ptr || !ok)
|
if (!ptr || !ok)
|
||||||
return false;
|
return false;
|
||||||
Q_UNUSED(rdevmajor);
|
mnt.rdev = makedev(rdevmajor, rdevminor);
|
||||||
Q_UNUSED(rdevminor);
|
|
||||||
|
|
||||||
if (*ptr != ' ')
|
if (*ptr != ' ')
|
||||||
return false;
|
return false;
|
||||||
@ -566,6 +566,21 @@ inline QByteArray QStorageIterator::fileSystemType() const
|
|||||||
|
|
||||||
inline QByteArray QStorageIterator::device() const
|
inline QByteArray QStorageIterator::device() const
|
||||||
{
|
{
|
||||||
|
// check that the device exists
|
||||||
|
if (mnt.mnt_fsname[0] == '/' && access(mnt.mnt_fsname, F_OK) != 0) {
|
||||||
|
// It doesn't, so let's try to resolve the dev_t from /dev/block.
|
||||||
|
// Note how strlen("4294967295") == digits10 + 1, so we need to add 1
|
||||||
|
// for each number, plus the ':'.
|
||||||
|
char buf[sizeof("/dev/block/") + 2 * std::numeric_limits<unsigned>::digits10 + 3];
|
||||||
|
QByteArray dev(PATH_MAX, Qt::Uninitialized);
|
||||||
|
char *devdata = dev.data();
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "/dev/block/%u:%u", major(mnt.rdev), minor(mnt.rdev));
|
||||||
|
if (realpath(buf, devdata)) {
|
||||||
|
dev.truncate(strlen(devdata));
|
||||||
|
return dev;
|
||||||
|
}
|
||||||
|
}
|
||||||
return QByteArray(mnt.mnt_fsname);
|
return QByteArray(mnt.mnt_fsname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user