From 54d1273fbeff297be194d41c157a706f1cf749d5 Mon Sep 17 00:00:00 2001 From: kh1 Date: Mon, 30 Jan 2012 15:22:03 +0100 Subject: Improve volume information. - Remove some superfluous functions. - Store and compare the drive identifier only. - Rename some functions to better reflect there purpose. OSX/Linux: - Store mounted device instead of volume label. Windows: - Remove dead code. - Take mounted volumes into account. - Store a unique name as drive identifier. - Use the first parameter from GetDiskFreeSpaceEx, as that one considers possible quota values per-user as well. If per-user quotas are being used, this value may be less than the total number of free bytes on a disk retrieved with the third parameter. - Make sure we properly check the path. In case of mounted volumes, a "\" might be the last character on the volume info path. If we just check for starts with, we might not notice that e.g. c:\test == c:\test\. Change-Id: Ib04e7ccf3a7a3d3d156753fcd18785201fe87c25 Reviewed-by: Tim Jenssen --- .../libinstaller/3rdparty/kdtools/kdsysinfo.cpp | 106 ++++++----- .../libinstaller/3rdparty/kdtools/kdsysinfo.h | 28 +-- .../3rdparty/kdtools/kdsysinfo_mac.cpp | 20 +-- .../3rdparty/kdtools/kdsysinfo_win.cpp | 193 ++++++++------------- .../3rdparty/kdtools/kdsysinfo_x11.cpp | 19 +- 5 files changed, 160 insertions(+), 206 deletions(-) (limited to 'installerbuilder/libinstaller/3rdparty') diff --git a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.cpp b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.cpp index 7c722a73d..253c32f5b 100644 --- a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.cpp +++ b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.cpp @@ -22,105 +22,103 @@ #include "kdsysinfo.h" -#include -#include - -#include +#include +#include using namespace KDUpdater; -QDebug operator<<(QDebug dbg, VolumeInfo volume) +struct PathLongerThan { - return dbg << "KDUpdater::Volume(" << volume.path() << ")"; -} - -//QPair volumeSpace(const QString &volume); - -//QString volumeName(const QString &volume); + bool operator()(const VolumeInfo &lhs, const VolumeInfo &rhs) const + { + return lhs.mountPath().length() > rhs.mountPath().length(); + } +}; VolumeInfo::VolumeInfo() + : m_size(0) + , m_availableSize(0) { - m_size = 0; - m_availableSpace = 0; } -void VolumeInfo::setPath(const QString &path) +VolumeInfo VolumeInfo::fromPath(const QString &path) { - m_path = path; + QDir targetPath(path); + QList volumes = mountedVolumes(); + // sort by length to get the longest mount point (not just "/") first + qSort(volumes.begin(), volumes.end(), PathLongerThan()); + foreach (const VolumeInfo &volume, volumes) { + QDir volumePath(volume.mountPath()); + if (targetPath == volumePath) + return volume; +#ifdef Q_OS_WIN + if (QDir::toNativeSeparators(path).toLower().startsWith(volume.mountPath().toLower())) +#else + if (targetPath.canonicalPath().startsWith(volume.mountPath())) +#endif + return volume; + } + return VolumeInfo(); } -bool VolumeInfo::operator==(const VolumeInfo &other) const +QString VolumeInfo::mountPath() const { - return m_name == other.m_name && m_path == other.m_path; + return m_mountPath; } -void VolumeInfo::setName(const QString &name) +void VolumeInfo::setMountPath(const QString &path) { - m_name = name; + m_mountPath = path; } -QString VolumeInfo::name() const +QString VolumeInfo::fileSystemType() const { - return m_name; + return m_fileSystemType; } -QString VolumeInfo::path() const +void VolumeInfo::setFileSystemType(const QString &type) { - return m_path; + m_fileSystemType = type; } -quint64 VolumeInfo::size() const +QString VolumeInfo::volumeDescriptor() const { - return m_size; + return m_volumeDescriptor; } -void VolumeInfo::setSize(const quint64 &size) +void VolumeInfo::setVolumeDescriptor(const QString &descriptor) { - m_size = size; + m_volumeDescriptor = descriptor; } -QString VolumeInfo::fileSystemType() const +quint64 VolumeInfo::size() const { - return m_fileSystemType; + return m_size; } -void VolumeInfo::setFileSystemType(const QString &type) +void VolumeInfo::setSize(const quint64 &size) { - m_fileSystemType = type; + m_size = size; } -quint64 VolumeInfo::availableSpace() const +quint64 VolumeInfo::availableSize() const { - return m_availableSpace; + return m_availableSize; } -void VolumeInfo::setAvailableSpace(const quint64 &available) +void VolumeInfo::setAvailableSize(const quint64 &available) { - m_availableSpace = available; + m_availableSize = available; } -struct PathLongerThan +bool VolumeInfo::operator==(const VolumeInfo &other) const { - bool operator()(const VolumeInfo &lhs, const VolumeInfo &rhs) const - { - return lhs.path().length() > rhs.path().length(); - } -}; + return m_volumeDescriptor == other.m_volumeDescriptor; +} -VolumeInfo VolumeInfo::fromPath(const QString &path) +QDebug operator<<(QDebug dbg, VolumeInfo volume) { - QList volumes = mountedVolumes(); - // sort by length to get the longest mount point (not just "/") first - std::sort(volumes.begin(), volumes.end(), PathLongerThan()); - for (QList< VolumeInfo >::const_iterator it = volumes.constBegin(); it != volumes.constEnd(); ++it) { -#ifdef Q_WS_WIN - if (QDir::toNativeSeparators(path).toLower().startsWith(it->path().toLower())) -#else - if (QDir(path).canonicalPath().startsWith(it->path())) -#endif - return *it; - } - return VolumeInfo(); + return dbg << "KDUpdater::Volume(" << volume.mountPath() << ")"; } QDebug operator<<(QDebug dbg, ProcessInfo process) diff --git a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.h b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.h index a4dc45345..6c8079fcd 100644 --- a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.h +++ b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo.h @@ -35,26 +35,30 @@ public: VolumeInfo(); static VolumeInfo fromPath(const QString &path); - QString name() const; - QString path() const; - quint64 size() const; + QString mountPath() const; + void setMountPath(const QString &path); + QString fileSystemType() const; - quint64 availableSpace() const; + void setFileSystemType(const QString &type); - bool operator==(const VolumeInfo &other) const; + QString volumeDescriptor() const; + void setVolumeDescriptor(const QString &descriptor); - void setPath(const QString &path); - void setName(const QString &name); + quint64 size() const; void setSize(const quint64 &size); - void setFileSystemType(const QString &type); - void setAvailableSpace(const quint64 &available); + + quint64 availableSize() const; + void setAvailableSize(const quint64 &available); + + bool operator==(const VolumeInfo &other) const; private: - QString m_path; - QString m_name; + QString m_mountPath; QString m_fileSystemType; + QString m_volumeDescriptor; + quint64 m_size; - quint64 m_availableSpace; + quint64 m_availableSize; }; struct ProcessInfo diff --git a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_mac.cpp b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_mac.cpp index 19d16d6da..3d8dcc8da 100644 --- a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_mac.cpp +++ b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_mac.cpp @@ -30,12 +30,6 @@ namespace KDUpdater { -static QString qt_mac_hfsunistr_to_qstring(const HFSUniStr255 *hfs) -{ - const QChar *charPointer = reinterpret_cast(hfs->unicode); - return QString(charPointer, hfs->length); -} - quint64 installedMemory() { SInt32 mb = 0; @@ -55,18 +49,18 @@ QList mountedVolumes() while (FSGetVolumeInfo(kFSInvalidVolumeRefNum, ++i, &volume, kFSVolInfoFSInfo, &info, &volName, &ref) == 0) { UInt8 path[PATH_MAX + 1]; if (FSRefMakePath(&ref, path, PATH_MAX) == 0) { - VolumeInfo v; - v.setName(qt_mac_hfsunistr_to_qstring(&volName)); - v.setPath(QString::fromLocal8Bit(reinterpret_cast< char* >(path))); - FSGetVolumeInfo(volume, 0, 0, kFSVolInfoSizes, &info, 0, 0); + + VolumeInfo v; v.setSize(quint64(info.totalBytes)); - v.setAvailableSpace(quint64(info.freeBytes)); + v.setAvailableSize(quint64(info.freeBytes)); + v.setMountPath(QString::fromLocal8Bit(reinterpret_cast< char* >(path))); struct statfs data; - if (statfs(qPrintable(v.path()), &data) == 0) + if (statfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { v.setFileSystemType(QLatin1String(data.f_fstypename)); - + v.setVolumeDescriptor(QLatin1String(data.f_mntfromname)); + } result.append(v); } } diff --git a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_win.cpp b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_win.cpp index 45148695d..45342aee5 100644 --- a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_win.cpp +++ b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_win.cpp @@ -23,12 +23,13 @@ #include "kdsysinfo.h" #include -#include #include +#include -#include -#include +#include +#pragma comment(lib, "mpr.lib") +#include #include const int KDSYSINFO_PROCESS_QUERY_LIMITED_INFORMATION = 0x1000; @@ -43,72 +44,90 @@ quint64 installedMemory() return quint64(status.ullTotalPhys); } -QPair volumeSpace(const QString &volume) +VolumeInfo updateVolumeSizeInformation(const VolumeInfo &info) { - QPair result; - ULARGE_INTEGER bytes; - ULARGE_INTEGER freebytes; - if (GetDiskFreeSpaceExA(qPrintable(volume), 0, &bytes, &freebytes) != 0) { - result.first = quint64(bytes.QuadPart); - result.second = quint64(freebytes.QuadPart); + ULARGE_INTEGER bytesTotal; + ULARGE_INTEGER freeBytesPerUser; + + VolumeInfo update = info; + if (GetDiskFreeSpaceExA(qPrintable(info.volumeDescriptor()), &freeBytesPerUser, &bytesTotal, NULL)) { + update.setSize(bytesTotal.QuadPart); + update.setAvailableSize(freeBytesPerUser.QuadPart); } - return result; + return update; } -QString volumeName(const QString &volume) +/*! + Returns a list of volume info objects that are mounted as network drive shares. +*/ +QList networkVolumeInfosFromMountPoints() { - char name[MAX_PATH + 1] = ""; - DWORD dummy; - char dummy2[MAX_PATH + 1] = ""; - GetVolumeInformationA(qPrintable(volume), name, MAX_PATH + 1, &dummy, &dummy, &dummy, dummy2, MAX_PATH + 1); - QString vName = QString::fromLatin1(name); - if (vName.isEmpty()) { - const uint driveType = GetDriveTypeA(qPrintable(volume)); + QList volumes; + QFileInfoList drives = QDir::drives(); + foreach (const QFileInfo &drive, drives) { + const QString driveLetter = QDir::toNativeSeparators(drive.canonicalPath()); + const uint driveType = GetDriveTypeA(qPrintable(driveLetter)); switch (driveType) { - case DRIVE_REMOVABLE: - vName = QObject::tr("Removable Disk"); - break; - case DRIVE_CDROM: - vName = QObject::tr("CD Drive"); - break; - case DRIVE_FIXED: - vName = QObject::tr("Local Disk"); - break; - default: - return volume.left(2); + case DRIVE_REMOTE: { + char buffer[1024] = ""; + DWORD bufferLength = 1024; + UNIVERSAL_NAME_INFOA *universalNameInfo = (UNIVERSAL_NAME_INFOA*) &buffer; + if (WNetGetUniversalNameA(qPrintable(driveLetter), UNIVERSAL_NAME_INFO_LEVEL, + LPVOID(universalNameInfo), &bufferLength) == NO_ERROR) { + VolumeInfo info; + info.setMountPath(driveLetter); + info.setVolumeDescriptor(QLatin1String(universalNameInfo->lpUniversalName)); + volumes.append(info); + } + } break; + + default: + break; } } - return QString::fromLatin1("%2 (%1)").arg(volume.left(2), vName); + return volumes; } -QString fileSystemType(const QString &path) +/*! + Returns a list of volume info objects based on the given \a volumeGUID. The function also solves mounted + volume folder paths. It does not return any network drive shares. +*/ +QList localVolumeInfosFromMountPoints(const QByteArray &volumeGUID) { - char name[MAX_PATH + 1] = ""; - DWORD dummy; - char fileSystem[MAX_PATH + 1] = ""; - BOOL result = GetVolumeInformationA(qPrintable(path), name, MAX_PATH + 1, &dummy, &dummy, &dummy, - fileSystem, MAX_PATH + 1); - if (result) - return QLatin1String(fileSystem); - return QLatin1String("unknown"); + QList volumes; + DWORD bufferSize; + char volumeNames[1024] = ""; + if (GetVolumePathNamesForVolumeNameA(volumeGUID, volumeNames, ARRAYSIZE(volumeNames), &bufferSize)) { + QStringList mountedPaths = QString::fromLatin1(volumeNames, bufferSize).split(QLatin1Char(char(0)), + QString::SkipEmptyParts); + foreach (const QString &mountedPath, mountedPaths) { + VolumeInfo info; + info.setMountPath(mountedPath); + info.setVolumeDescriptor(QString::fromLatin1(volumeGUID)); + volumes.append(info); + } + } + return volumes; } QList mountedVolumes() { - QList result; - const QFileInfoList drives = QDir::drives(); - for (QFileInfoList::const_iterator it = drives.constBegin(); it != drives.constEnd(); ++it) { - VolumeInfo volume; - const QString path = QDir::toNativeSeparators(it->path()); - volume.setPath(path); - volume.setName(volumeName(path)); - volume.setFileSystemType(fileSystemType(path)); - const QPair sizes = volumeSpace(path); - volume.setSize(sizes.first); - volume.setAvailableSpace(sizes.second); - result.push_back(volume); + QList tmp; + char volumeGUID[MAX_PATH] = ""; + HANDLE handle = FindFirstVolumeA(volumeGUID, ARRAYSIZE(volumeGUID)); + if (handle != INVALID_HANDLE_VALUE) { + tmp += localVolumeInfosFromMountPoints(volumeGUID); + while (FindNextVolumeA(handle, volumeGUID, ARRAYSIZE(volumeGUID))) { + tmp += localVolumeInfosFromMountPoints(volumeGUID); + } + FindVolumeClose(handle); } - return result; + tmp += networkVolumeInfosFromMountPoints(); + + QList volumes; + while (!tmp.isEmpty()) // update volume size information + volumes.append(updateVolumeSizeInformation(tmp.takeFirst())); + return volumes; } struct EnumWindowsProcParam @@ -117,68 +136,6 @@ struct EnumWindowsProcParam QList seenIDs; }; -//BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam) -//{ -// EnumWindowsProcParam* const list = reinterpret_cast< EnumWindowsProcParam* >( lParam ); -// ProcessInfo info; - -// // process id -// DWORD procID = 0; -// GetWindowThreadProcessId( hWnd, &procID ); -// info.id = procID; - -// if( list->seenIDs.contains( info.id ) ) -// return TRUE; -// list->seenIDs.push_back( info.id ); - -// HINSTANCE inst = (HINSTANCE)GetWindowLongA( hWnd, GWL_HINSTANCE ); -// // process name -// HANDLE process = OpenProcess( PROCESS_ALL_ACCESS, FALSE, procID ); - -// static char buffer[ 1024 ]; -// if( GetModuleFileNameExA( process, inst, buffer, sizeof( buffer ) ) ) -// info.name = QString::fromLocal8Bit( buffer ); -// CloseHandle( process ); - -// list->processes.push_back( info ); -// return TRUE; -//} - -//QList runningProcesses() -//{ -// EnumWindowsProcParam param; -// HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); -// if (!snapshot) -// return param.processes; -// PROCESSENTRY32 processStruct; -// processStruct.dwSize = sizeof(PROCESSENTRY32); -// bool foundProcess = Process32First(snapshot, &processStruct); -// while (foundProcess) { -// //const QString executableName = QString::fromWCharArray( processStruct.szExeFile ); -// ProcessInfo info; -// HANDLE procHandle = OpenProcess( PROCESS_QUERY_LIMITED_INFORMATION, false, processStruct.th32ProcessID ); -// char buffer[ 1024 ]; -// DWORD bufferSize = 1024; -// const bool succ = QueryFullProcessImageNameA( procHandle, 0, buffer, &bufferSize ); -// if (succ) { -// const QString executablepath = QString::fromLatin1( buffer ); -// const quint32 pid = processStruct.th32ProcessID; -// param.seenIDs.append( pid ); - -// info.id = pid; -// info.name = executablepath; -// param.processes.append( info ); -// } -// CloseHandle( procHandle ); - -// foundProcess = Process32Next( snapshot, &processStruct ); -// } -// if (snapshot) -// CloseHandle( snapshot ); -//// EnumDesktopWindows( 0, &EnumWindowsProc, reinterpret_cast< LPARAM >( ¶m ) ); -// return param.processes; -//} - typedef BOOL (WINAPI *QueryFullProcessImageNamePtr)(HANDLE, DWORD, char *, PDWORD); typedef DWORD (WINAPI *GetProcessImageFileNamePtr)(HANDLE, char *, DWORD); @@ -227,8 +184,10 @@ QList runningProcesses() } else if (pGetProcessImageFileNamePtr) { succ = callPtrXp(procHandle, buffer, bufferSize); executablePath = QString::fromLatin1(buffer); - for (int i = 0; i < deviceList.count(); ++i) - executablePath.replace(QString::fromLatin1( "\\Device\\HarddiskVolume%1\\" ).arg(i + 1), deviceList.at(i)); + for (int i = 0; i < deviceList.count(); ++i) { + executablePath.replace(QString::fromLatin1( "\\Device\\HarddiskVolume%1\\" ).arg(i + 1), + deviceList.at(i)); + } } if (succ) { diff --git a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_x11.cpp b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_x11.cpp index 7225e996d..f6e2c8ced 100644 --- a/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_x11.cpp +++ b/installerbuilder/libinstaller/3rdparty/kdtools/kdsysinfo_x11.cpp @@ -65,7 +65,7 @@ QList mountedVolumes() QFile f(QLatin1String("/etc/mtab")); if (!f.open(QIODevice::ReadOnly)) { qCritical("%s: Could not open %s: %s", Q_FUNC_INFO, qPrintable(f.fileName()), qPrintable(f.errorString())); - return QList(); //better error-handling? + return result; //better error-handling? } QTextStream stream(&f); @@ -73,25 +73,24 @@ QList mountedVolumes() const QString s = stream.readLine(); if (s.isNull()) return result; - + if (!s.startsWith(QLatin1Char('/'))) continue; - const QStringList parts = s.split( QLatin1Char(' '), QString::SkipEmptyParts); + const QStringList parts = s.split(QLatin1Char(' '), QString::SkipEmptyParts); VolumeInfo v; - v.setName(parts.at(1)); - v.setPath(parts.at(1)); + v.setMountPath(parts.at(1)); + v.setVolumeDescriptor(parts.at(0)); + v.setFileSystemType(parts.value(2)); struct statvfs data; - if (statvfs(qPrintable(v.name()), &data) == 0) { + if (statvfs(qPrintable(v.mountPath() + QLatin1String("/.")), &data) == 0) { v.setSize(quint64(static_cast(data.f_blocks) * data.f_bsize)); - v.setAvailableSpace(quint64(static_cast(data.f_bavail) * data.f_bsize)); + v.setAvailableSize(quint64(static_cast(data.f_bavail) * data.f_bsize)); } - - result.push_back(v); + result.append(v); } - return result; } -- cgit v1.2.3