/* This file is part of the TDE libraries Copyright (C) 2012 Timothy Pearson (C) 2013 Golubev Alexander This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "tdestoragedevice.h" #include #include #include #include #include #include #include #include #include "kdebug.h" #include "tdelocale.h" #include "tdeglobal.h" #include "kiconloader.h" #include "tdetempfile.h" #include "kstandarddirs.h" #include "tdehardwaredevices.h" #include "disksHelper.h" #include "config.h" #if defined(WITH_CRYPTSETUP) #ifdef CRYPTSETUP_OLD_API #define class cryptsetup_class #define CRYPT_SLOT_INVALID INVALID #define CRYPT_SLOT_INACTIVE INACTIVE #define CRYPT_SLOT_ACTIVE ACTIVE #define CRYPT_SLOT_BUSY BUSY #define CRYPT_SLOT_ACTIVE_LAST ACTIVE #include #undef class #else #include #endif #endif TDEStorageDevice::TDEStorageDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn), m_mediaInserted(true), m_cryptDevice(NULL) { m_diskType = TDEDiskDeviceType::Null; m_diskStatus = TDEDiskDeviceStatus::Null; } TDEStorageDevice::~TDEStorageDevice() { #if defined(WITH_CRYPTSETUP) if (m_cryptDevice) { crypt_free(m_cryptDevice); m_cryptDevice = NULL; } #endif } TQString TDEStorageDevice::mappedName() { return m_mappedName; } void TDEStorageDevice::updateMappedName() { // Get the device mapped name if present m_mappedName = TQString::null; TQString dmnodename = systemPath(); dmnodename.append("/dm/name"); TQFile dmnamefile(dmnodename); if (dmnamefile.open(IO_ReadOnly)) { TQTextStream stream(&dmnamefile); m_mappedName = stream.readLine(); dmnamefile.close(); } if (!m_mappedName.isEmpty()) { m_mappedName.prepend("/dev/mapper/"); } } TDEDiskDeviceType::TDEDiskDeviceType TDEStorageDevice::diskType() { return m_diskType; } void TDEStorageDevice::internalGetLUKSKeySlotStatus() { #if defined(WITH_CRYPTSETUP) unsigned int i; crypt_keyslot_info keyslot_status; TDELUKSKeySlotStatus::TDELUKSKeySlotStatus tde_keyslot_status; m_cryptKeyslotStatus.clear(); for (i = 0; i < m_cryptKeySlotCount; i++) { keyslot_status = crypt_keyslot_status(m_cryptDevice, i); tde_keyslot_status = TDELUKSKeySlotStatus::Invalid; if (keyslot_status == CRYPT_SLOT_INACTIVE) { tde_keyslot_status = TDELUKSKeySlotStatus::Inactive; } else if (keyslot_status == CRYPT_SLOT_ACTIVE) { tde_keyslot_status = TDELUKSKeySlotStatus::Active; } else if (keyslot_status == CRYPT_SLOT_ACTIVE_LAST) { tde_keyslot_status = TDELUKSKeySlotStatus::Active | TDELUKSKeySlotStatus::Last; } m_cryptKeyslotStatus.append(tde_keyslot_status); } #endif } void TDEStorageDevice::internalInitializeLUKSIfNeeded() { #if defined(WITH_CRYPTSETUP) int ret; if (m_diskType & TDEDiskDeviceType::LUKS) { if (!m_cryptDevice) { TQString node = deviceNode(); if (node != "") { ret = crypt_init(&m_cryptDevice, node.ascii()); if (ret == 0) { ret = crypt_load(m_cryptDevice, NULL, NULL); if (ret == 0) { int keyslot_count; #if defined(CRYPTSETUP_OLD_API) || !defined(HAVE_CRYPTSETUP_GET_TYPE) kdWarning() << "TDEStorageDevice: The version of libcryptsetup that TDE was compiled against was too old! Most LUKS features will not function" << endl; m_cryptDeviceType = TQString::null; keyslot_count = 0; #else m_cryptDeviceType = crypt_get_type(m_cryptDevice); keyslot_count = crypt_keyslot_max(m_cryptDeviceType.ascii()); #endif if (keyslot_count < 0) { m_cryptKeySlotCount = 0; } else { m_cryptKeySlotCount = keyslot_count; } internalGetLUKSKeySlotStatus(); } } else { m_cryptDevice = NULL; } } } } else { if (m_cryptDevice) { crypt_free(m_cryptDevice); m_cryptDevice = NULL; } } #endif } void TDEStorageDevice::cryptSetOperationsUnlockPassword(TQByteArray password) { #if defined(WITH_CRYPTSETUP) crypt_memory_lock(NULL, 1); m_cryptDevicePassword = password; #endif } void TDEStorageDevice::cryptClearOperationsUnlockPassword() { m_cryptDevicePassword.fill(0); m_cryptDevicePassword.resize(0); #if defined(WITH_CRYPTSETUP) crypt_memory_lock(NULL, 0); #endif } bool TDEStorageDevice::cryptOperationsUnlockPasswordSet() { if (m_cryptDevicePassword.size() > 0) { return true; } else { return false; } } TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptCheckKey(unsigned int keyslot) { #if defined(WITH_CRYPTSETUP) int ret; if (m_cryptDevice) { if (keyslot < m_cryptKeySlotCount) { ret = crypt_activate_by_passphrase(m_cryptDevice, NULL, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), 0); if (ret < 0) { return TDELUKSResult::KeyslotOpFailed; } else { return TDELUKSResult::Success; } } else { return TDELUKSResult::InvalidKeyslot; } } else { return TDELUKSResult::LUKSNotFound; } #else return TDELUKSResult::LUKSNotSupported; #endif } TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptAddKey(unsigned int keyslot, TQByteArray password) { #if defined(WITH_CRYPTSETUP) int ret; if (m_cryptDevice) { if (keyslot < m_cryptKeySlotCount) { ret = crypt_keyslot_add_by_passphrase(m_cryptDevice, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), password.data(), password.size()); if (ret < 0) { return TDELUKSResult::KeyslotOpFailed; } else { internalGetLUKSKeySlotStatus(); return TDELUKSResult::Success; } } else { return TDELUKSResult::InvalidKeyslot; } } else { return TDELUKSResult::LUKSNotFound; } #else return TDELUKSResult::LUKSNotSupported; #endif } TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptDelKey(unsigned int keyslot) { #if defined(WITH_CRYPTSETUP) int ret; if (m_cryptDevice) { if (keyslot < m_cryptKeySlotCount) { ret = crypt_keyslot_destroy(m_cryptDevice, keyslot); if (ret < 0) { return TDELUKSResult::KeyslotOpFailed; } else { internalGetLUKSKeySlotStatus(); return TDELUKSResult::Success; } } else { return TDELUKSResult::InvalidKeyslot; } } else { return TDELUKSResult::LUKSNotFound; } #else return TDELUKSResult::LUKSNotSupported; #endif } unsigned int TDEStorageDevice::cryptKeySlotCount() { return m_cryptKeySlotCount; } TDELUKSKeySlotStatusList TDEStorageDevice::cryptKeySlotStatus() { return m_cryptKeyslotStatus; } TQString TDEStorageDevice::cryptKeySlotFriendlyName(TDELUKSKeySlotStatus::TDELUKSKeySlotStatus status) { if (status & TDELUKSKeySlotStatus::Inactive) { return i18n("Inactive"); } else if (status & TDELUKSKeySlotStatus::Active) { return i18n("Active"); } else { return i18n("Unknown"); } } void TDEStorageDevice::internalSetDeviceNode(TQString dn) { TDEGenericDevice::internalSetDeviceNode(dn); internalInitializeLUKSIfNeeded(); } void TDEStorageDevice::internalSetDiskType(TDEDiskDeviceType::TDEDiskDeviceType dt) { m_diskType = dt; internalInitializeLUKSIfNeeded(); } bool TDEStorageDevice::isDiskOfType(TDEDiskDeviceType::TDEDiskDeviceType tf) { return ((m_diskType&tf)!=TDEDiskDeviceType::Null); } TDEDiskDeviceStatus::TDEDiskDeviceStatus TDEStorageDevice::diskStatus() { return m_diskStatus; } void TDEStorageDevice::internalSetDiskStatus(TDEDiskDeviceStatus::TDEDiskDeviceStatus st) { m_diskStatus = st; } bool TDEStorageDevice::checkDiskStatus(TDEDiskDeviceStatus::TDEDiskDeviceStatus sf) { return ((m_diskStatus&sf)!=(TDEDiskDeviceStatus::TDEDiskDeviceStatus)0); } bool TDEStorageDevice::lockDriveMedia(bool lock) { int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK); if (fd < 0) { return false; } if (ioctl(fd, CDROM_LOCKDOOR, (lock)?1:0) != 0) { close(fd); return false; } else { close(fd); return true; } } TQStringVariantMap TDEStorageDevice::ejectDrive() { TQStringVariantMap result; TQStringVariantMap ejectResult; #ifdef WITH_UDISKS2 if (!(TDEGlobal::dirs()->findExe("udisksctl").isEmpty())) { ejectResult = udisks2EjectDrive(this); if (ejectResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = ejectResult["errStr"]; result["result"] = false; return result; } } #endif #ifdef WITH_UDISKS if (!(TDEGlobal::dirs()->findExe("udisks").isEmpty())) { ejectResult = udisksEjectDrive(this); if (ejectResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = ejectResult["errStr"]; result["result"] = false; return result; } } #endif if (!(TDEGlobal::dirs()->findExe("eject").isEmpty())) { TQString command = TQString("eject -v '%1' 2>&1").arg(deviceNode()); FILE *exepipe = popen(command.ascii(), "r"); if (exepipe) { TQString eject_output; TQTextStream ts(exepipe, IO_ReadOnly); eject_output = ts.read(); int retcode = pclose(exepipe); if (retcode == 0) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else { result["errStr"] = eject_output; result["retCode"] = retcode; } } } // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = false; return result; } bool TDEStorageDevice::ejectDriveMedia() { int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK); if (fd < 0) { return false; } if (ioctl(fd, CDROMEJECT) != 0) { close(fd); return false; } else { close(fd); return true; } } TQString TDEStorageDevice::diskLabel() { return m_diskName; } void TDEStorageDevice::internalSetDiskLabel(TQString dn) { m_diskName = dn; } bool TDEStorageDevice::mediaInserted() { return m_mediaInserted; } void TDEStorageDevice::internalSetMediaInserted(bool inserted) { m_mediaInserted = inserted; } TQString TDEStorageDevice::fileSystemName() { return m_fileSystemName; } void TDEStorageDevice::internalSetFileSystemName(TQString fn) { m_fileSystemName = fn; } TQString TDEStorageDevice::fileSystemUsage() { return m_fileSystemUsage; } void TDEStorageDevice::internalSetFileSystemUsage(TQString fu) { m_fileSystemUsage = fu; } TQString TDEStorageDevice::diskUUID() { return m_diskUUID; } void TDEStorageDevice::internalSetDiskUUID(TQString id) { m_diskUUID = id; } TQStringList TDEStorageDevice::holdingDevices() { return m_holdingDevices; } void TDEStorageDevice::internalSetHoldingDevices(TQStringList hd) { m_holdingDevices = hd; } TQStringList TDEStorageDevice::slaveDevices() { return m_slaveDevices; } void TDEStorageDevice::internalSetSlaveDevices(TQStringList sd) { m_slaveDevices = sd; } TQString decodeHexEncoding(TQString str) { TQRegExp hexEncRegExp("\\\\x[0-9A-Fa-f]{1,2}"); hexEncRegExp.setMinimal(false); hexEncRegExp.setCaseSensitive(true); int s = -1; while((s = hexEncRegExp.search(str, s+1))>=0){ str.replace(s, hexEncRegExp.cap(0).length(), TQChar((char)strtol(hexEncRegExp.cap(0).mid(2).ascii(), NULL, 16))); } return str; } TQString TDEStorageDevice::friendlyName() { // Return the actual storage device name TQString devicevendorid = vendorEncoded(); TQString devicemodelid = modelEncoded(); devicevendorid = decodeHexEncoding(devicevendorid); devicemodelid = decodeHexEncoding(devicemodelid); devicevendorid = devicevendorid.stripWhiteSpace(); devicemodelid = devicemodelid.stripWhiteSpace(); devicevendorid = devicevendorid.simplifyWhiteSpace(); devicemodelid = devicemodelid.simplifyWhiteSpace(); TQString devicename = devicevendorid + " " + devicemodelid; devicename = devicename.stripWhiteSpace(); devicename = devicename.simplifyWhiteSpace(); if (devicename != "") { return devicename; } if (isDiskOfType(TDEDiskDeviceType::Camera)) { return TDEGenericDevice::friendlyName(); } if (isDiskOfType(TDEDiskDeviceType::Floppy)) { return friendlyDeviceType(); } TQString label = diskLabel(); if (label.isNull()) { if (deviceSize() > 0) { if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) { label = i18n("%1 Removable Device").arg(deviceFriendlySize()); } else { label = i18n("%1 Fixed Storage Device").arg(deviceFriendlySize()); } } } if (!label.isNull()) { return label; } return friendlyDeviceType(); } TQString TDEStorageDevice::detailedFriendlyName() { return TQString("%1 [%2]").arg(friendlyName()).arg(deviceNode()); } TQString TDEStorageDevice::friendlyDeviceType() { TQString ret = i18n("Hard Disk Drive"); // Keep this in sync with TDEStorageDevice::icon(TDEIcon::StdSizes size) below if (isDiskOfType(TDEDiskDeviceType::Floppy)) { ret = i18n("Floppy Drive"); } if (isDiskOfType(TDEDiskDeviceType::Optical)) { ret = i18n("Optical Drive"); } if (isDiskOfType(TDEDiskDeviceType::CDROM)) { ret = i18n("CDROM Drive"); } if (isDiskOfType(TDEDiskDeviceType::CDRW)) { ret = i18n("CDRW Drive"); } if (isDiskOfType(TDEDiskDeviceType::DVDROM)) { ret = i18n("DVD Drive"); } if (isDiskOfType(TDEDiskDeviceType::DVDRW)) { ret = i18n("DVDRW Drive"); } if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) { ret = i18n("DVDRAM Drive"); } if (isDiskOfType(TDEDiskDeviceType::Zip)) { ret = i18n("Zip Drive"); } if (isDiskOfType(TDEDiskDeviceType::Tape)) { ret = i18n("Tape Drive"); } if (isDiskOfType(TDEDiskDeviceType::Camera)) { ret = i18n("Digital Camera"); } if (isDiskOfType(TDEDiskDeviceType::HDD)) { ret = i18n("Hard Disk Drive"); if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) { ret = i18n("Removable Storage"); } if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) { ret = i18n("Compact Flash"); } if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) { ret = i18n("Memory Stick"); } if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) { ret = i18n("Smart Media"); } if (isDiskOfType(TDEDiskDeviceType::SDMMC)) { ret = i18n("Secure Digital"); } } if (isDiskOfType(TDEDiskDeviceType::RAM)) { ret = i18n("Random Access Memory"); } if (isDiskOfType(TDEDiskDeviceType::Loop)) { ret = i18n("Loop Device"); } return ret; } TQPixmap TDEStorageDevice::icon(TDEIcon::StdSizes size) { TQString mountString; if (mountPath() != TQString::null) { mountString = "-mounted"; } else { mountString = "-unmounted"; } TQPixmap ret = DesktopIcon("drive-harddisk" + mountString, size); if (isDiskOfType(TDEDiskDeviceType::Floppy)) { ret = DesktopIcon("media-floppy-3_5" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::Optical)) { ret = DesktopIcon("media-optical-cdrom" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::CDROM)) { ret = DesktopIcon("media-optical-cdrom" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::CDRW)) { ret = DesktopIcon("cd-rw" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::DVDROM)) { ret = DesktopIcon("media-optical-dvd" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::DVDRW)) { ret = DesktopIcon("media-optical-dvd" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) { ret = DesktopIcon("media-optical-dvd" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::Zip)) { ret = DesktopIcon("media-floppy-zip" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::Tape)) { ret = DesktopIcon("media-tape" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::Camera)) { ret = DesktopIcon("camera" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::HDD)) { ret = DesktopIcon("drive-harddisk" + mountString, size); if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) { ret = DesktopIcon("media-flash-usb" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) { ret = DesktopIcon("media-flash-compact_flash" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) { ret = DesktopIcon("media-flash-memory_stick" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) { ret = DesktopIcon("media-flash-smart_media" + mountString, size); } if (isDiskOfType(TDEDiskDeviceType::SDMMC)) { ret = DesktopIcon("media-flash-sd_mmc" + mountString, size); } } if (isDiskOfType(TDEDiskDeviceType::RAM)) { ret = DesktopIcon("memory", size); // FIXME there is only a single icon available for this device } if (isDiskOfType(TDEDiskDeviceType::Loop)) { ret = DesktopIcon("blockdevice", size); // FIXME there is only a single icon available for this device } return ret; } unsigned long long TDEStorageDevice::deviceSize() { TQString bsnodename = systemPath(); // While at first glance it would seem that checking /queue/physical_block_size would be needed to get an accurate device size, in reality Linux // appears to only ever report the device size in 512 byte units. This does not appear to be documented anywhere! TQString blocksize = "512"; TQString dsnodename = systemPath(); dsnodename.append("/size"); TQFile dsfile( dsnodename ); TQString devicesize; if ( dsfile.open( IO_ReadOnly ) ) { TQTextStream stream( &dsfile ); devicesize = stream.readLine(); dsfile.close(); } return ((unsigned long long)blocksize.toULong()*(unsigned long long)devicesize.toULong()); } TQString TDEStorageDevice::deviceFriendlySize() { return TDEHardwareDevices::bytesToFriendlySizeString(deviceSize()); } TQString TDEStorageDevice::mountPath() { // See if this device node is mounted // This requires parsing /proc/mounts, looking for deviceNode() // 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 TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TQStringList lines; TQFile file( "/proc/mounts" ); if ( file.open( IO_ReadOnly ) ) { TQTextStream stream( &file ); TQString line; while ( !stream.atEnd() ) { line = stream.readLine(); TQStringList mountInfo = TQStringList::split(" ", line, true); TQString testNode = *mountInfo.at(0); // Check for match if ((testNode == deviceNode()) || (testNode == mappedName()) || (testNode == ("/dev/disk/by-uuid/" + diskUUID()))) { TQString ret = *mountInfo.at(1); ret.replace("\\040", " "); return ret; } lines += line; } file.close(); } // 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 = holdingDevices(); for ( TQStringList::Iterator slavedevit = slaveDeviceList.begin(); slavedevit != slaveDeviceList.end(); ++slavedevit ) { // Try to locate this device path in the TDE device tree TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices(); TDEGenericDevice *hwdevice = hwdevices->findBySystemPath(*slavedevit); if ((hwdevice) && (hwdevice->type() == TDEGenericDeviceType::Disk)) { TDEStorageDevice* sdevice = static_cast(hwdevice); return sdevice->mountPath(); } } return TQString::null; } TQStringVariantMap TDEStorageDevice::mountDevice(TQString mediaName, TDEStorageMountOptions mountOptions) { TQStringVariantMap result; // Check if device is already mounted TQString mountpath = mountPath(); if (!mountpath.isEmpty()) { result["mountPath"] = mountpath; result["result"] = true; return result; } TQString devNode = deviceNode(); devNode.replace("'", "'\\''"); mediaName.replace("'", "'\\''"); TQString command = TQString::null; #if defined(WITH_UDISKS2) || defined(WITH_UDISKS) || defined(WITH_UDEVIL) // Prepare filesystem options for mount TQStringList udisksOptions; if (mountOptions["ro"] == "true") { udisksOptions.append("ro"); } if (mountOptions["atime"] != "true") { udisksOptions.append("noatime"); } if (mountOptions["sync"] == "true") { udisksOptions.append("sync"); } if ((mountOptions["filesystem"] == "fat") || (mountOptions["filesystem"] == "vfat") || (mountOptions["filesystem"] == "msdos") || (mountOptions["filesystem"] == "umsdos")) { if (mountOptions.contains("shortname")) { udisksOptions.append(TQString("shortname=%1").arg(mountOptions["shortname"])); } } if ((mountOptions["filesystem"] == "jfs")) { if (mountOptions["utf8"] == "true") { // udisks/udisks2 for now does not support option iocharset= for jfs // udisksOptions.append("iocharset=utf8"); } } if ((mountOptions["filesystem"] == "ntfs-3g")) { if (mountOptions.contains("locale")) { udisksOptions.append(TQString("locale=%1").arg(mountOptions["locale"])); } } if ((mountOptions["filesystem"] == "ext3") || (mountOptions["filesystem"] == "ext4")) { if (mountOptions.contains("journaling")) { // udisks/udisks2 for now does not support option data= for ext3/ext4 // udisksOptions.append(TQString("data=%1").arg(mountOptions["journaling"])); } } TQString optionString; for (TQStringList::Iterator it = udisksOptions.begin(); it != udisksOptions.end(); ++it) { optionString.append(","); optionString.append(*it); } if (!optionString.isEmpty()) { optionString.remove(0, 1); } TQString fileSystemType; if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { fileSystemType = mountOptions["filesystem"]; } TQStringVariantMap mountResult; #endif #if defined(WITH_UDISKS2) // Try to use UDISKS v2 via DBUS, if available mountResult = udisks2MountDrive(devNode, fileSystemType, optionString); if (mountResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["mountPath"] = mountPath(); result["result"] = true; return result; } else if (mountResult["retcode"].toInt() == -1) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = mountResult["errStr"]; result["result"] = false; return result; } #endif #if defined(WITH_UDISKS) // The UDISKS v2 DBUS service was either not available or was unusable // Try to use UDISKS v1 via DBUS, if available mountResult = udisksMountDrive(devNode, fileSystemType, udisksOptions); if (mountResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["mountPath"] = mountPath(); result["result"] = true; return result; } else if (mountResult["retcode"].toInt() == -1) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = mountResult["errStr"]; result["result"] = false; return result; } #endif #if defined(WITH_UDEVIL) // The UDISKS v1 DBUS service was either not available or was unusable // Use 'udevil' command, if available if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) { if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { fileSystemType = TQString("-t %1").arg(mountOptions["filesystem"]); } TQString mountpoint; if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() && (mountOptions["mountpoint"] != "/media/")) { mountpoint = mountOptions["mountpoint"]; mountpoint.replace("'", "'\\''"); } else { mountpoint = TQString("/media/%1").arg(mediaName); } command = TQString("udevil mount %1 -o '%2' '%3' '%4' 2>&1") .arg(fileSystemType).arg(optionString).arg(devNode).arg(mountpoint); } #endif // If no other method was found, use 'pmount' command if available if(command.isEmpty()) { if (!TDEGlobal::dirs()->findExe("pmount").isEmpty()) { TQString optionString; if (mountOptions["ro"] == "true") { optionString.append(" -r"); } if (mountOptions["atime"] != "true") { optionString.append(" -A"); } if (mountOptions["utf8"] == "true") { optionString.append(" -c utf8"); } if (mountOptions["sync"] == "true") { optionString.append(" -s"); } if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"])); } if (mountOptions.contains("locale")) { optionString.append(TQString(" -c %1").arg(mountOptions["locale"])); } TQString mountpoint; if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() && (mountOptions["mountpoint"] != "/media/")) { mountpoint = mountOptions["mountpoint"]; mountpoint.replace("'", "'\\''"); } else { mountpoint = mediaName; } // %1 (option string) without quotes, otherwise pmount fails command = TQString("pmount %1 '%2' '%3' 2>&1") .arg(optionString).arg(devNode).arg(mountpoint); } } if(command.isEmpty()) { result["errStr"] = i18n("No supported mounting methods were detected on your system"); result["result"] = false; return result; } FILE *exepipe = popen(command.local8Bit(), "r"); if (exepipe) { TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); TQString mount_output = ts->read(); delete ts; int retcode = pclose(exepipe); result["errStr"] = mount_output; result["retCode"] = retcode; } // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["mountPath"] = mountPath(); result["result"] = !mountPath().isEmpty(); return result; } TQStringVariantMap TDEStorageDevice::unmountDevice() { TQStringVariantMap result; // Check if device is already unmounted TQString mountpoint = mountPath(); if (mountpoint.isEmpty()) { result["result"] = true; return result; } mountpoint.replace("'", "'\\''"); TQString devNode = deviceNode(); TQString command = TQString::null; TQStringVariantMap unmountResult; #if defined(WITH_UDISKS2) // Try to use UDISKS v2 via DBUS, if available unmountResult = udisks2UnmountDrive(devNode, TQString::null); if (unmountResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else if (unmountResult["retcode"].toInt() == -1) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = unmountResult["errStr"]; result["result"] = false; return result; } #endif #if defined(WITH_UDISKS) // The UDISKS v2 DBUS service was either not available or was unusable // Try to use UDISKS v1 via DBUS, if available unmountResult = udisksUnmountDrive(devNode, TQStringList()); if (unmountResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else if (unmountResult["retcode"].toInt() == -1) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = unmountResult["errStr"]; result["result"] = false; return result; } #endif #if defined(WITH_UDEVIL) // The UDISKS v1 DBUS service was either not available or was unusable // Use 'udevil' command, if available if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) { command = TQString("udevil umount '%1' 2>&1").arg(mountpoint); } #endif // If no other method was found, use 'pmount' command if available if(command.isEmpty() && !TDEGlobal::dirs()->findExe("pumount").isEmpty()) { command = TQString("pumount '%1' 2>&1").arg(mountpoint); } if(command.isEmpty()) { result["errStr"] = i18n("No supported unmounting methods were detected on your system"); result["result"] = false; return result; } FILE *exepipe = popen(command.local8Bit(), "r"); if (exepipe) { TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); TQString umount_output = ts->read(); delete ts; int retcode = pclose(exepipe); if (retcode == 0) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else { result["errStr"] = umount_output; result["retCode"] = retcode; } } // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = false; return result; } TQStringVariantMap TDEStorageDevice::unlockDevice(const TQString &passphrase) { TQStringVariantMap result; // Check if device is already mounted TQString mountpath = mountPath(); if (!mountpath.isEmpty()) { result["unlockedDevice"] = mountpath; result["result"] = true; return result; } TQString devNode = deviceNode(); devNode.replace("'", "'\\''"); TQStringVariantMap unlockResult; #if defined(WITH_UDISKS2) // Try to use UDISKS v2 via DBUS, if available unlockResult = udisks2UnlockDrive(devNode, passphrase); if (unlockResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["unlockedDevice"] = unlockResult["unlockedDevice"]; result["result"] = true; return result; } else if (unlockResult["retcode"].toInt() == -1) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = unlockResult["errStr"]; result["result"] = false; return result; } #endif // If no other method was found, use 'pmount' command if available if (!TDEGlobal::dirs()->findExe("pmount").isEmpty()) { // Create dummy password file KTempFile passwordFile(TQString::null, "tmp", 0600); passwordFile.setAutoDelete(true); TQFile *pwFile = passwordFile.file(); if (!pwFile) { result["errStr"] = i18n("Cannot create temporary password file"); result["result"] = false; return result; } pwFile->writeBlock(passphrase.local8Bit(), passphrase.length()); pwFile->flush(); TQString passFileName = passwordFile.name(); passFileName.replace("'", "'\\''"); TQString command = TQString("pmount -p '%1' '%2'").arg(passFileName).arg(devNode); FILE *exepipe = popen(command.local8Bit(), "r"); if (exepipe) { TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); TQString unlock_output = ts->read(); delete ts; int retcode = pclose(exepipe); if (retcode == 0) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; } else { result["errStr"] = unlock_output; result["retCode"] = retcode; result["result"] = false; } return result; } } // No supported methods found for unlocking the device result["errStr"] = i18n("No supported unlocking methods were detected on your system."); result["result"] = false; return result; } TQStringVariantMap TDEStorageDevice::lockDevice() { TQStringVariantMap result; // Check if device is mounted TQString mountpath = mountPath(); if (!mountpath.isEmpty()) { result["errStr"] = i18n("The device is currently mounted and cannot be locked."); result["result"] = false; return result; } TQString devNode = deviceNode(); devNode.replace("'", "'\\''"); TQStringVariantMap lockResult; #if defined(WITH_UDISKS2) // Try to use UDISKS v2 via DBUS, if available lockResult = udisks2LockDrive(devNode); if (lockResult["result"].toBool()) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; return result; } else if (lockResult["retcode"].toInt() == -1) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["errStr"] = lockResult["errStr"]; result["result"] = false; return result; } #endif // If no other method was found, use 'pumount' command if available if (!TDEGlobal::dirs()->findExe("pumount").isEmpty()) { TQString command = TQString("pumount '%1'").arg(devNode); FILE *exepipe = popen(command.local8Bit(), "r"); if (exepipe) { TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); TQString lock_output = ts->read(); delete ts; int retcode = pclose(exepipe); if (retcode == 0) { // Update internal mount data TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); TDEGlobal::hardwareDevices()->processModifiedMounts(); result["result"] = true; } else { result["errStr"] = lock_output; result["retCode"] = retcode; result["result"] = false; } return result; } } // No supported methods found for locking the device result["errStr"] = i18n("No supported locking methods were detected on your system."); result["result"] = false; return result; } TQString TDEStorageDevice::determineFileSystemType(TQString path) { TQStringList mountTable; TQString prevPath = path; dev_t prevDev = 0; int pos; struct stat directory_info; if (path.startsWith("/")) { stat(path.local8Bit(), &directory_info); prevDev = directory_info.st_dev; // Walk the directory tree up to the root, checking for any change in st_dev // If a change is found, the previous value of path is the mount point itself while (path != "/") { pos = path.findRev("/", -1, true); if (pos < 0) { break; } path = path.mid(0, pos); if (path == "") { path = "/"; } stat(path.local8Bit(), &directory_info); if (directory_info.st_dev != prevDev) { break; } prevPath = path; prevDev = directory_info.st_dev; } } // Read in mount table mountTable.clear(); TQFile file( "/proc/mounts" ); if ( file.open( IO_ReadOnly ) ) { TQTextStream stream( &file ); while ( !stream.atEnd() ) { mountTable.append(stream.readLine()); } file.close(); } // Parse mount table TQStringList::Iterator it; for ( it = mountTable.begin(); it != mountTable.end(); ++it ) { TQStringList mountInfo = TQStringList::split(" ", (*it), true); if ((*mountInfo.at(1)) == prevPath) { return (*mountInfo.at(2)); } } // Unknown file system type return TQString::null; } #include "tdestoragedevice.moc"