From 4e0646cb8c0d1c4888f99f5128dbe439ea70067a Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sun, 1 Apr 2012 18:58:24 -0500 Subject: Fix a number of bugs in the TDE hardware library and stabilize device mapper device detection --- tdecore/tdehardwaredevices.cpp | 112 ++++++++++++++++++++++++++++++++--------- tdecore/tdehardwaredevices.h | 5 ++ 2 files changed, 94 insertions(+), 23 deletions(-) (limited to 'tdecore') diff --git a/tdecore/tdehardwaredevices.cpp b/tdecore/tdehardwaredevices.cpp index b8d8d7e6f..e1337d8e1 100644 --- a/tdecore/tdehardwaredevices.cpp +++ b/tdecore/tdehardwaredevices.cpp @@ -178,7 +178,7 @@ TQStringList &TDEStorageDevice::holdingDevices() { } void TDEStorageDevice::setHoldingDevices(TQStringList hd) { - m_slaveDevices = hd; + m_holdingDevices = hd; } TQStringList &TDEStorageDevice::slaveDevices() { @@ -258,6 +258,10 @@ TQString TDEStorageDevice::mountPath() { // The Device Mapper throws a monkey wrench into this // It likes to advertise mounts as /dev/mapper/, // where is listed in /dm/name + + // First, ensure that all device information (mainly holders/slaves) is accurate + KGlobal::hardwareDevices()->rescanDeviceInformation(this); + TQString dmnodename = systemPath(); dmnodename.append("/dm/name"); TQFile namefile( dmnodename ); @@ -279,7 +283,9 @@ TQString TDEStorageDevice::mountPath() { while ( !stream.atEnd() ) { line = stream.readLine(); TQStringList mountInfo = TQStringList::split(" ", line, true); - if ((*mountInfo.at(0) == deviceNode()) || (*mountInfo.at(0) == dmaltname)) { + TQString testNode = *mountInfo.at(0); + // Check for match + if ((testNode == deviceNode()) || (testNode == dmaltname)) { return *mountInfo.at(1); } lines += line; @@ -289,7 +295,7 @@ TQString TDEStorageDevice::mountPath() { // While this device is not directly mounted, it could concievably be mounted via the Device Mapper // If so, try to retrieve the mount path... - TQStringList slaveDeviceList = slaveDevices(); + TQStringList slaveDeviceList = holdingDevices(); for ( TQStringList::Iterator slavedevit = slaveDeviceList.begin(); slavedevit != slaveDeviceList.end(); ++slavedevit ) { // Try to locate this device path in the TDE device tree TDEHardwareDevices *hwdevices = KGlobal::hardwareDevices(); @@ -330,16 +336,16 @@ TQString TDEStorageDevice::mountDevice(TQString mediaName, TQString mountOptions char buffer[8092]; pmount_output = fgets(buffer, sizeof(buffer), exepipe); *retcode = pclose(exepipe); - if (*retcode == 0) { - ret = mountPath(); - } - else { - if (errRet) { - *errRet = pmount_output; - } + if (errRet) { + *errRet = pmount_output; } } + // Update internal mount data + KGlobal::hardwareDevices()->processModifiedMounts(); + + ret = mountPath(); + return ret; } @@ -377,16 +383,16 @@ TQString TDEStorageDevice::mountEncryptedDevice(TQString passphrase, TQString me char buffer[8092]; pmount_output = fgets(buffer, sizeof(buffer), exepipe); *retcode = pclose(exepipe); - if (*retcode == 0) { - ret = mountPath(); - } - else { - if (errRet) { - *errRet = pmount_output; - } + if (errRet) { + *errRet = pmount_output; } } + // Update internal mount data + KGlobal::hardwareDevices()->processModifiedMounts(); + + ret = mountPath(); + return ret; } @@ -419,6 +425,9 @@ bool TDEStorageDevice::unmountDevice(TQString* errRet, int* retcode) { } } + // Update internal mount data + KGlobal::hardwareDevices()->processModifiedMounts(); + return false; } @@ -471,6 +480,13 @@ TDEHardwareDevices::~TDEHardwareDevices() { udev_unref(m_udevStruct); } +void TDEHardwareDevices::rescanDeviceInformation(TDEGenericDevice* hwdevice) { + struct udev_device *dev; + dev = udev_device_new_from_syspath(m_udevStruct, hwdevice->systemPath().ascii()); + classifyUnknownDevice(dev, hwdevice); + udev_device_unref(dev); +} + TDEGenericDevice* TDEHardwareDevices::findBySystemPath(TQString syspath) { TDEGenericDevice *hwdevice; for ( hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next() ) { @@ -536,7 +552,24 @@ void TDEHardwareDevices::processHotPluggedHardware() { for (hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next()) { if (hwdevice->systemPath() == systempath) { emit hardwareRemoved(hwdevice); - m_deviceList.remove(hwdevice); + + // If the device is a storage device and has a slave, update it as well + if (hwdevice->type() == TDEGenericDeviceType::Disk) { + TDEStorageDevice* sdevice = static_cast(hwdevice); + TQStringList slavedevices = sdevice->slaveDevices(); + m_deviceList.remove(hwdevice); + for ( TQStringList::Iterator slaveit = slavedevices.begin(); slaveit != slavedevices.end(); ++slaveit ) { + TDEGenericDevice* slavedevice = findBySystemPath(*slaveit); + if (slavedevice) { + rescanDeviceInformation(slavedevice); + emit hardwareUpdated(slavedevice); + } + } + } + else { + m_deviceList.remove(hwdevice); + } + break; } } @@ -547,8 +580,20 @@ void TDEHardwareDevices::processHotPluggedHardware() { TDEGenericDevice *hwdevice; for (hwdevice = m_deviceList.first(); hwdevice; hwdevice = m_deviceList.next()) { if (hwdevice->systemPath() == systempath) { - classifyUnknownDevice(dev, hwdevice); -// emit hardwareUpdated(hwdevice); // FIXME certain devices (***cough U3 system fake CD cough*** spam this quite badly, locking up anything monitoring hardwareUpdated() + // HACK + // I am lucky enough to have a Flash drive that spams udev continually with device change events + // I imagine I am not the only one, so here is a section in which specific devices can be blacklisted! + bool blacklisted = false; + + // For "U3 System" fake CD + if ((TQString(udev_device_get_property_value(dev, "ID_VENDOR_ID")) == "08ec") && (TQString(udev_device_get_property_value(dev, "ID_MODEL_ID")) == "0020") && (TQString(udev_device_get_property_value(dev, "ID_TYPE")) == "cd")); { + blacklisted = true; + } + + if (!blacklisted) { + classifyUnknownDevice(dev, hwdevice); + emit hardwareUpdated(hwdevice); + } break; } } @@ -557,7 +602,6 @@ void TDEHardwareDevices::processHotPluggedHardware() { } void TDEHardwareDevices::processModifiedMounts() { - // FIXME // Detect what changed between the old mount table and the new one, // and emit appropriate events @@ -602,7 +646,7 @@ void TDEHardwareDevices::processModifiedMounts() { if (hwdevice->type() == TDEGenericDeviceType::Disk) { TDEStorageDevice* sdevice = static_cast(hwdevice); TQStringList slavedevices = sdevice->slaveDevices(); - for ( TQStringList::Iterator slaveit = addedEntries.begin(); slaveit != addedEntries.end(); ++slaveit ) { + for ( TQStringList::Iterator slaveit = slavedevices.begin(); slaveit != slavedevices.end(); ++slaveit ) { TDEGenericDevice* slavedevice = findBySystemPath(*slaveit); if (slavedevice) { emit hardwareUpdated(slavedevice); @@ -621,7 +665,7 @@ void TDEHardwareDevices::processModifiedMounts() { if (hwdevice->type() == TDEGenericDeviceType::Disk) { TDEStorageDevice* sdevice = static_cast(hwdevice); TQStringList slavedevices = sdevice->slaveDevices(); - for ( TQStringList::Iterator slaveit = addedEntries.begin(); slaveit != addedEntries.end(); ++slaveit ) { + for ( TQStringList::Iterator slaveit = slavedevices.begin(); slaveit != slavedevices.end(); ++slaveit ) { TDEGenericDevice* slavedevice = findBySystemPath(*slaveit); if (slavedevice) { emit hardwareUpdated(slavedevice); @@ -701,6 +745,12 @@ TDEDiskDeviceType::TDEDiskDeviceType classifyDiskType(udev_device* dev, const TQ disktype = disktype | TDEDiskDeviceType::HDD; } + // Certain combinations of media flags should never be set at the same time as they don't make sense + // This block is needed as udev is more than happy to provide inconsistent data to us + if ((disktype & TDEDiskDeviceType::Zip) || (disktype & TDEDiskDeviceType::Floppy) || (disktype & TDEDiskDeviceType::Jaz)) { + disktype = disktype & ~TDEDiskDeviceType::HDD; + } + if (disktypestring.upper() == "CD") { if (TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA")) == "1") { disktype = disktype | TDEDiskDeviceType::CDROM; @@ -867,6 +917,22 @@ TDEGenericDevice* TDEHardwareDevices::classifyUnknownDevice(udev_device* dev, TD sdevice->setMediaInserted(!(TQString(udev_device_get_property_value(dev, "ID_CDROM_MEDIA")) == "0")); } + if (disktype & TDEDiskDeviceType::Zip) { + // A Zip drive does not advertise its status via udev, but it can be guessed from the size parameter + TQString zipnodename = systempath; + zipnodename.append("/size"); + TQFile namefile( zipnodename ); + TQString zipsize; + if ( namefile.open( IO_ReadOnly ) ) { + TQTextStream stream( &namefile ); + zipsize = stream.readLine(); + namefile.close(); + } + if (!zipsize.isNull()) { + sdevice->setMediaInserted((zipsize.toInt() != 0)); + } + } + if (removable) { diskstatus = diskstatus | TDEDiskDeviceStatus::Removable; } diff --git a/tdecore/tdehardwaredevices.h b/tdecore/tdehardwaredevices.h index 0da239663..c6cf43cac 100644 --- a/tdecore/tdehardwaredevices.h +++ b/tdecore/tdehardwaredevices.h @@ -493,6 +493,9 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject void processHotPluggedHardware(); void processModifiedMounts(); + private: + void rescanDeviceInformation(TDEGenericDevice* hwdevice); + private: TDEGenericDevice *classifyUnknownDevice(udev_device* dev, TDEGenericDevice* existingdevice=0); @@ -505,6 +508,8 @@ class TDECORE_EXPORT TDEHardwareDevices : public TQObject TQSocketNotifier* m_mountScanNotifier; TQStringList m_mountTable; + + friend class TDEStorageDevice; }; #endif \ No newline at end of file -- cgit v1.2.1