QFileSystemEngine/Unix: implement getting the size of block devices
Implemented for Linux, macOS, and FreeBSD. This works only on open files because of the need to ioctl(). Before: "/dev/system/stuff2" : 0 After: "/dev/system/stuff2" : 68719476736 [Linux] "/dev/ada1" : 42949672960 [FreeBSD] "/dev/disk0" : 500277792768 [macOS] "/dev/disk2" : 39306240 [macOS] With: if (f.open(QIODevice::ReadOnly | QIODevice::Unbuffered)) qDebug() << f.fileName() << ':' << f.size(); [ChangeLog][QtCore][QFile] For open block devices on Unix systems, size() now returns the size of the underlying device. Previously, it would always return 0. Change-Id: I8a96935cf6c742259c9dfffd17e9402bdbd6b963 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
731b1159f9
commit
3b9f5c82f5
@ -36,6 +36,11 @@
|
||||
# define _PATH_TMP "/tmp"
|
||||
#endif
|
||||
|
||||
#if __has_include(<sys/disk.h>)
|
||||
// BSDs (including Apple Darwin)
|
||||
# include <sys/disk.h>
|
||||
#endif
|
||||
|
||||
#if defined(Q_OS_DARWIN)
|
||||
# include <QtCore/private/qcore_mac_p.h>
|
||||
# include <CoreFoundation/CFBundle.h>
|
||||
@ -362,6 +367,33 @@ inline void QFileSystemMetaData::fillFromStatxBuf(const struct statx &)
|
||||
//static
|
||||
bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
|
||||
{
|
||||
auto getSizeForBlockDev = [&](mode_t st_mode) {
|
||||
#ifdef BLKGETSIZE64
|
||||
// Linux
|
||||
if (quint64 sz; (st_mode & S_IFMT) == S_IFBLK && ioctl(fd, BLKGETSIZE64, &sz) == 0)
|
||||
data.size_ = sz; // returns byte count
|
||||
#elif defined(BLKGETSIZE)
|
||||
// older Linux
|
||||
if (ulong sz; (st_mode & S_IFMT) == S_IFBLK && ioctl(fd, BLKGETSIZE, &sz) == 0)
|
||||
data.size_ = sz * 512; // returns 512-byte sector count
|
||||
#elif defined(DKIOCGETBLOCKCOUNT)
|
||||
// Apple Darwin
|
||||
qint32 blksz;
|
||||
if (quint64 count; (st_mode & S_IFMT) == S_IFBLK
|
||||
&& ioctl(fd, DKIOCGETBLOCKCOUNT, &count) == 0
|
||||
&& ioctl(fd, DKIOCGETBLOCKSIZE, &blksz) == 0)
|
||||
data.size_ = count * blksz;
|
||||
#elif defined(DIOCGMEDIASIZE)
|
||||
// FreeBSD
|
||||
// see Linux-compat implementation in
|
||||
// http://fxr.watson.org/fxr/source/compat/linux/linux_ioctl.c?v=FREEBSD-13-STABLE#L282
|
||||
// S_IFCHR is correct: FreeBSD doesn't have block devices any more
|
||||
if (QT_OFF_T sz; (st_mode & S_IFMT) == S_IFCHR && ioctl(fd, DIOCGMEDIASIZE, &sz) == 0)
|
||||
data.size_ = sz; // returns byte count
|
||||
#else
|
||||
Q_UNUSED(st_mode);
|
||||
#endif
|
||||
};
|
||||
data.entryFlags &= ~QFileSystemMetaData::PosixStatFlags;
|
||||
data.knownFlagsMask |= QFileSystemMetaData::PosixStatFlags;
|
||||
|
||||
@ -371,6 +403,7 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
|
||||
if (ret != -ENOSYS) {
|
||||
if (ret == 0) {
|
||||
data.fillFromStatxBuf(statxBuffer);
|
||||
getSizeForBlockDev(statxBuffer.stx_mode);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -380,6 +413,7 @@ bool QFileSystemEngine::fillMetaData(int fd, QFileSystemMetaData &data)
|
||||
|
||||
if (QT_FSTAT(fd, &statBuffer) == 0) {
|
||||
data.fillFromStatBuf(statBuffer);
|
||||
getSizeForBlockDev(statBuffer.st_mode);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user