tdestoragedevice.cpp
00001 /* This file is part of the TDE libraries 00002 Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net> 00003 (C) 2013 Golubev Alexander <fatzer2@gmail.com> 00004 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License version 2 as published by the Free Software Foundation. 00008 00009 This library is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 Library General Public License for more details. 00013 00014 You should have received a copy of the GNU Library General Public License 00015 along with this library; see the file COPYING.LIB. If not, write to 00016 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00017 Boston, MA 02110-1301, USA. 00018 */ 00019 00020 #include "tdestoragedevice.h" 00021 00022 #include <unistd.h> 00023 #include <fcntl.h> 00024 #include <sys/stat.h> 00025 #include <sys/ioctl.h> 00026 #include <linux/cdrom.h> 00027 00028 #include <tqregexp.h> 00029 #include <tqpixmap.h> 00030 #include <tqfile.h> 00031 00032 #include "kdebug.h" 00033 #include "tdelocale.h" 00034 #include "tdeglobal.h" 00035 #include "kiconloader.h" 00036 #include "tdetempfile.h" 00037 #include "kstandarddirs.h" 00038 #include "tdehardwaredevices.h" 00039 #include "disksHelper.h" 00040 00041 #include "config.h" 00042 00043 #if defined(WITH_CRYPTSETUP) 00044 #ifdef CRYPTSETUP_OLD_API 00045 #define class cryptsetup_class 00046 #define CRYPT_SLOT_INVALID INVALID 00047 #define CRYPT_SLOT_INACTIVE INACTIVE 00048 #define CRYPT_SLOT_ACTIVE ACTIVE 00049 #define CRYPT_SLOT_BUSY BUSY 00050 #define CRYPT_SLOT_ACTIVE_LAST ACTIVE 00051 #include <libcryptsetup.h> 00052 #undef class 00053 #else 00054 #include <libcryptsetup.h> 00055 #endif 00056 #endif 00057 00058 TDEStorageDevice::TDEStorageDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn), m_mediaInserted(true), m_cryptDevice(NULL) { 00059 m_diskType = TDEDiskDeviceType::Null; 00060 m_diskStatus = TDEDiskDeviceStatus::Null; 00061 } 00062 00063 TDEStorageDevice::~TDEStorageDevice() { 00064 #if defined(WITH_CRYPTSETUP) 00065 if (m_cryptDevice) { 00066 crypt_free(m_cryptDevice); 00067 m_cryptDevice = NULL; 00068 } 00069 #endif 00070 } 00071 00072 TDEDiskDeviceType::TDEDiskDeviceType TDEStorageDevice::diskType() { 00073 return m_diskType; 00074 } 00075 00076 void TDEStorageDevice::internalGetLUKSKeySlotStatus() { 00077 #if defined(WITH_CRYPTSETUP) 00078 unsigned int i; 00079 crypt_keyslot_info keyslot_status; 00080 TDELUKSKeySlotStatus::TDELUKSKeySlotStatus tde_keyslot_status; 00081 00082 m_cryptKeyslotStatus.clear(); 00083 for (i = 0; i < m_cryptKeySlotCount; i++) { 00084 keyslot_status = crypt_keyslot_status(m_cryptDevice, i); 00085 tde_keyslot_status = TDELUKSKeySlotStatus::Invalid; 00086 if (keyslot_status == CRYPT_SLOT_INACTIVE) { 00087 tde_keyslot_status = TDELUKSKeySlotStatus::Inactive; 00088 } 00089 else if (keyslot_status == CRYPT_SLOT_ACTIVE) { 00090 tde_keyslot_status = TDELUKSKeySlotStatus::Active; 00091 } 00092 else if (keyslot_status == CRYPT_SLOT_ACTIVE_LAST) { 00093 tde_keyslot_status = TDELUKSKeySlotStatus::Active | TDELUKSKeySlotStatus::Last; 00094 } 00095 m_cryptKeyslotStatus.append(tde_keyslot_status); 00096 } 00097 #endif 00098 } 00099 00100 void TDEStorageDevice::internalInitializeLUKSIfNeeded() { 00101 #if defined(WITH_CRYPTSETUP) 00102 int ret; 00103 00104 if (m_diskType & TDEDiskDeviceType::LUKS) { 00105 if (!m_cryptDevice) { 00106 TQString node = deviceNode(); 00107 if (node != "") { 00108 ret = crypt_init(&m_cryptDevice, node.ascii()); 00109 if (ret == 0) { 00110 ret = crypt_load(m_cryptDevice, NULL, NULL); 00111 if (ret == 0) { 00112 int keyslot_count; 00113 #if defined(CRYPTSETUP_OLD_API) || !defined(HAVE_CRYPTSETUP_GET_TYPE) 00114 kdWarning() << "TDEStorageDevice: The version of libcryptsetup that TDE was compiled against was too old! Most LUKS features will not function" << endl; 00115 m_cryptDeviceType = TQString::null; 00116 keyslot_count = 0; 00117 #else 00118 m_cryptDeviceType = crypt_get_type(m_cryptDevice); 00119 keyslot_count = crypt_keyslot_max(m_cryptDeviceType.ascii()); 00120 #endif 00121 if (keyslot_count < 0) { 00122 m_cryptKeySlotCount = 0; 00123 } 00124 else { 00125 m_cryptKeySlotCount = keyslot_count; 00126 } 00127 internalGetLUKSKeySlotStatus(); 00128 } 00129 } 00130 else { 00131 m_cryptDevice = NULL; 00132 } 00133 } 00134 } 00135 } 00136 else { 00137 if (m_cryptDevice) { 00138 crypt_free(m_cryptDevice); 00139 m_cryptDevice = NULL; 00140 } 00141 } 00142 #endif 00143 } 00144 00145 void TDEStorageDevice::cryptSetOperationsUnlockPassword(TQByteArray password) { 00146 #if defined(WITH_CRYPTSETUP) 00147 crypt_memory_lock(NULL, 1); 00148 m_cryptDevicePassword = password; 00149 #endif 00150 } 00151 00152 void TDEStorageDevice::cryptClearOperationsUnlockPassword() { 00153 m_cryptDevicePassword.fill(0); 00154 m_cryptDevicePassword.resize(0); 00155 #if defined(WITH_CRYPTSETUP) 00156 crypt_memory_lock(NULL, 0); 00157 #endif 00158 } 00159 00160 bool TDEStorageDevice::cryptOperationsUnlockPasswordSet() { 00161 if (m_cryptDevicePassword.size() > 0) { 00162 return true; 00163 } 00164 else { 00165 return false; 00166 } 00167 } 00168 00169 TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptCheckKey(unsigned int keyslot) { 00170 #if defined(WITH_CRYPTSETUP) 00171 int ret; 00172 00173 if (m_cryptDevice) { 00174 if (keyslot < m_cryptKeySlotCount) { 00175 ret = crypt_activate_by_passphrase(m_cryptDevice, NULL, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), 0); 00176 if (ret < 0) { 00177 return TDELUKSResult::KeyslotOpFailed; 00178 } 00179 else { 00180 return TDELUKSResult::Success; 00181 } 00182 } 00183 else { 00184 return TDELUKSResult::InvalidKeyslot; 00185 } 00186 } 00187 else { 00188 return TDELUKSResult::LUKSNotFound; 00189 } 00190 #else 00191 return TDELUKSResult::LUKSNotSupported; 00192 #endif 00193 } 00194 00195 TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptAddKey(unsigned int keyslot, TQByteArray password) { 00196 #if defined(WITH_CRYPTSETUP) 00197 int ret; 00198 00199 if (m_cryptDevice) { 00200 if (keyslot < m_cryptKeySlotCount) { 00201 ret = crypt_keyslot_add_by_passphrase(m_cryptDevice, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), password.data(), password.size()); 00202 if (ret < 0) { 00203 return TDELUKSResult::KeyslotOpFailed; 00204 } 00205 else { 00206 internalGetLUKSKeySlotStatus(); 00207 return TDELUKSResult::Success; 00208 } 00209 } 00210 else { 00211 return TDELUKSResult::InvalidKeyslot; 00212 } 00213 } 00214 else { 00215 return TDELUKSResult::LUKSNotFound; 00216 } 00217 #else 00218 return TDELUKSResult::LUKSNotSupported; 00219 #endif 00220 } 00221 00222 TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptDelKey(unsigned int keyslot) { 00223 #if defined(WITH_CRYPTSETUP) 00224 int ret; 00225 00226 if (m_cryptDevice) { 00227 if (keyslot < m_cryptKeySlotCount) { 00228 ret = crypt_keyslot_destroy(m_cryptDevice, keyslot); 00229 if (ret < 0) { 00230 return TDELUKSResult::KeyslotOpFailed; 00231 } 00232 else { 00233 internalGetLUKSKeySlotStatus(); 00234 return TDELUKSResult::Success; 00235 } 00236 } 00237 else { 00238 return TDELUKSResult::InvalidKeyslot; 00239 } 00240 } 00241 else { 00242 return TDELUKSResult::LUKSNotFound; 00243 } 00244 #else 00245 return TDELUKSResult::LUKSNotSupported; 00246 #endif 00247 } 00248 00249 unsigned int TDEStorageDevice::cryptKeySlotCount() { 00250 return m_cryptKeySlotCount; 00251 } 00252 00253 TDELUKSKeySlotStatusList TDEStorageDevice::cryptKeySlotStatus() { 00254 return m_cryptKeyslotStatus; 00255 } 00256 00257 TQString TDEStorageDevice::cryptKeySlotFriendlyName(TDELUKSKeySlotStatus::TDELUKSKeySlotStatus status) { 00258 if (status & TDELUKSKeySlotStatus::Inactive) { 00259 return i18n("Inactive"); 00260 } 00261 else if (status & TDELUKSKeySlotStatus::Active) { 00262 return i18n("Active"); 00263 } 00264 else { 00265 return i18n("Unknown"); 00266 } 00267 } 00268 00269 void TDEStorageDevice::internalSetDeviceNode(TQString sn) { 00270 TDEGenericDevice::internalSetDeviceNode(sn); 00271 internalInitializeLUKSIfNeeded(); 00272 } 00273 00274 void TDEStorageDevice::internalSetDiskType(TDEDiskDeviceType::TDEDiskDeviceType dt) { 00275 m_diskType = dt; 00276 internalInitializeLUKSIfNeeded(); 00277 } 00278 00279 bool TDEStorageDevice::isDiskOfType(TDEDiskDeviceType::TDEDiskDeviceType tf) { 00280 return ((m_diskType&tf)!=TDEDiskDeviceType::Null); 00281 } 00282 00283 TDEDiskDeviceStatus::TDEDiskDeviceStatus TDEStorageDevice::diskStatus() { 00284 return m_diskStatus; 00285 } 00286 00287 void TDEStorageDevice::internalSetDiskStatus(TDEDiskDeviceStatus::TDEDiskDeviceStatus st) { 00288 m_diskStatus = st; 00289 } 00290 00291 bool TDEStorageDevice::checkDiskStatus(TDEDiskDeviceStatus::TDEDiskDeviceStatus sf) { 00292 return ((m_diskStatus&sf)!=(TDEDiskDeviceStatus::TDEDiskDeviceStatus)0); 00293 } 00294 00295 bool TDEStorageDevice::lockDriveMedia(bool lock) { 00296 int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK); 00297 if (fd < 0) { 00298 return false; 00299 } 00300 if (ioctl(fd, CDROM_LOCKDOOR, (lock)?1:0) != 0) { 00301 close(fd); 00302 return false; 00303 } 00304 else { 00305 close(fd); 00306 return true; 00307 } 00308 } 00309 00310 bool TDEStorageDevice::ejectDrive() { 00311 #ifdef WITH_UDISKS2 00312 if (!(TDEGlobal::dirs()->findExe("udisksctl").isEmpty())) { 00313 TQStringVariantMap ejectResult = UDisks2EjectDrive(this); 00314 if (ejectResult["result"].toBool()) { 00315 return true; 00316 } 00317 else { 00318 printf("[tdehwlib] Failed to eject drive '%s' via udisks2, falling back to alternate mechanism\n", deviceNode().ascii()); 00319 fflush(stdout); 00320 } 00321 } 00322 #endif 00323 #ifdef WITH_UDISKS 00324 if (!(TDEGlobal::dirs()->findExe("udisks").isEmpty())) { 00325 TQStringVariantMap ejectResult = UDisksEjectDrive(this); 00326 if (ejectResult["result"].toBool()) { 00327 return true; 00328 } 00329 else { 00330 printf("[tdehwlib] Failed to eject drive '%s' via udisks, falling back to alternate mechanism\n", deviceNode().ascii()); 00331 fflush(stdout); 00332 } 00333 } 00334 #endif 00335 00336 if (!(TDEGlobal::dirs()->findExe("eject").isEmpty())) { 00337 TQString command = TQString("eject -v '%1' 2>&1").arg(deviceNode()); 00338 00339 FILE *exepipe = popen(command.ascii(), "r"); 00340 if (exepipe) { 00341 TQString eject_output; 00342 TQTextStream ts(exepipe, IO_ReadOnly); 00343 eject_output = ts.read(); 00344 int retcode = pclose(exepipe); 00345 if (retcode == 0) { 00346 return true; 00347 } 00348 } 00349 printf("[tdehwlib] Failed to eject drive '%s' via 'eject' command\n", deviceNode().ascii()); 00350 fflush(stdout); 00351 } 00352 00353 return false; 00354 } 00355 00356 bool TDEStorageDevice::ejectDriveMedia() { 00357 int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK); 00358 if (fd < 0) { 00359 return false; 00360 } 00361 if (ioctl(fd, CDROMEJECT) != 0) { 00362 close(fd); 00363 return false; 00364 } 00365 else { 00366 close(fd); 00367 return true; 00368 } 00369 } 00370 00371 TQString TDEStorageDevice::diskLabel() { 00372 return m_diskName; 00373 } 00374 00375 void TDEStorageDevice::internalSetDiskLabel(TQString dn) { 00376 m_diskName = dn; 00377 } 00378 00379 bool TDEStorageDevice::mediaInserted() { 00380 return m_mediaInserted; 00381 } 00382 00383 void TDEStorageDevice::internalSetMediaInserted(bool inserted) { 00384 m_mediaInserted = inserted; 00385 } 00386 00387 TQString TDEStorageDevice::fileSystemName() { 00388 return m_fileSystemName; 00389 } 00390 00391 void TDEStorageDevice::internalSetFileSystemName(TQString fn) { 00392 m_fileSystemName = fn; 00393 } 00394 00395 TQString TDEStorageDevice::fileSystemUsage() { 00396 return m_fileSystemUsage; 00397 } 00398 00399 void TDEStorageDevice::internalSetFileSystemUsage(TQString fu) { 00400 m_fileSystemUsage = fu; 00401 } 00402 00403 TQString TDEStorageDevice::diskUUID() { 00404 return m_diskUUID; 00405 } 00406 00407 void TDEStorageDevice::internalSetDiskUUID(TQString id) { 00408 m_diskUUID = id; 00409 } 00410 00411 TQStringList TDEStorageDevice::holdingDevices() { 00412 return m_holdingDevices; 00413 } 00414 00415 void TDEStorageDevice::internalSetHoldingDevices(TQStringList hd) { 00416 m_holdingDevices = hd; 00417 } 00418 00419 TQStringList TDEStorageDevice::slaveDevices() { 00420 return m_slaveDevices; 00421 } 00422 00423 void TDEStorageDevice::internalSetSlaveDevices(TQStringList sd) { 00424 m_slaveDevices = sd; 00425 } 00426 00427 TQString decodeHexEncoding(TQString str) { 00428 TQRegExp hexEncRegExp("\\\\x[0-9A-Fa-f]{1,2}"); 00429 hexEncRegExp.setMinimal(false); 00430 hexEncRegExp.setCaseSensitive(true); 00431 int s = -1; 00432 00433 while((s = hexEncRegExp.search(str, s+1))>=0){ 00434 str.replace(s, hexEncRegExp.cap(0).length(), TQChar((char)strtol(hexEncRegExp.cap(0).mid(2).ascii(), NULL, 16))); 00435 } 00436 00437 return str; 00438 } 00439 00440 TQString TDEStorageDevice::friendlyName() { 00441 // Return the actual storage device name 00442 TQString devicevendorid = vendorEncoded(); 00443 TQString devicemodelid = modelEncoded(); 00444 00445 devicevendorid = decodeHexEncoding(devicevendorid); 00446 devicemodelid = decodeHexEncoding(devicemodelid); 00447 00448 devicevendorid = devicevendorid.stripWhiteSpace(); 00449 devicemodelid = devicemodelid.stripWhiteSpace(); 00450 devicevendorid = devicevendorid.simplifyWhiteSpace(); 00451 devicemodelid = devicemodelid.simplifyWhiteSpace(); 00452 00453 TQString devicename = devicevendorid + " " + devicemodelid; 00454 00455 devicename = devicename.stripWhiteSpace(); 00456 devicename = devicename.simplifyWhiteSpace(); 00457 00458 if (devicename != "") { 00459 return devicename; 00460 } 00461 00462 if (isDiskOfType(TDEDiskDeviceType::Camera)) { 00463 return TDEGenericDevice::friendlyName(); 00464 } 00465 00466 if (isDiskOfType(TDEDiskDeviceType::Floppy)) { 00467 return friendlyDeviceType(); 00468 } 00469 00470 TQString label = diskLabel(); 00471 if (label.isNull()) { 00472 if (deviceSize() > 0) { 00473 if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) { 00474 label = i18n("%1 Removable Device").arg(deviceFriendlySize()); 00475 } 00476 else { 00477 label = i18n("%1 Fixed Storage Device").arg(deviceFriendlySize()); 00478 } 00479 } 00480 } 00481 00482 if (!label.isNull()) { 00483 return label; 00484 } 00485 00486 return friendlyDeviceType(); 00487 } 00488 00489 TQString TDEStorageDevice::detailedFriendlyName() { 00490 return TQString("%1 [%2]").arg(friendlyName()).arg(deviceNode()); 00491 } 00492 00493 TQString TDEStorageDevice::friendlyDeviceType() { 00494 TQString ret = i18n("Hard Disk Drive"); 00495 00496 // Keep this in sync with TDEStorageDevice::icon(TDEIcon::StdSizes size) below 00497 if (isDiskOfType(TDEDiskDeviceType::Floppy)) { 00498 ret = i18n("Floppy Drive"); 00499 } 00500 if (isDiskOfType(TDEDiskDeviceType::Optical)) { 00501 ret = i18n("Optical Drive"); 00502 } 00503 if (isDiskOfType(TDEDiskDeviceType::CDROM)) { 00504 ret = i18n("CDROM Drive"); 00505 } 00506 if (isDiskOfType(TDEDiskDeviceType::CDRW)) { 00507 ret = i18n("CDRW Drive"); 00508 } 00509 if (isDiskOfType(TDEDiskDeviceType::DVDROM)) { 00510 ret = i18n("DVD Drive"); 00511 } 00512 if (isDiskOfType(TDEDiskDeviceType::DVDRW)) { 00513 ret = i18n("DVDRW Drive"); 00514 } 00515 if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) { 00516 ret = i18n("DVDRAM Drive"); 00517 } 00518 if (isDiskOfType(TDEDiskDeviceType::Zip)) { 00519 ret = i18n("Zip Drive"); 00520 } 00521 if (isDiskOfType(TDEDiskDeviceType::Tape)) { 00522 ret = i18n("Tape Drive"); 00523 } 00524 if (isDiskOfType(TDEDiskDeviceType::Camera)) { 00525 ret = i18n("Digital Camera"); 00526 } 00527 00528 if (isDiskOfType(TDEDiskDeviceType::HDD)) { 00529 ret = i18n("Hard Disk Drive"); 00530 if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) { 00531 ret = i18n("Removable Storage"); 00532 } 00533 if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) { 00534 ret = i18n("Compact Flash"); 00535 } 00536 if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) { 00537 ret = i18n("Memory Stick"); 00538 } 00539 if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) { 00540 ret = i18n("Smart Media"); 00541 } 00542 if (isDiskOfType(TDEDiskDeviceType::SDMMC)) { 00543 ret = i18n("Secure Digital"); 00544 } 00545 } 00546 00547 if (isDiskOfType(TDEDiskDeviceType::RAM)) { 00548 ret = i18n("Random Access Memory"); 00549 } 00550 if (isDiskOfType(TDEDiskDeviceType::Loop)) { 00551 ret = i18n("Loop Device"); 00552 } 00553 00554 return ret; 00555 } 00556 00557 TQPixmap TDEStorageDevice::icon(TDEIcon::StdSizes size) { 00558 TQString mountString; 00559 if (mountPath() != TQString::null) { 00560 mountString = "-mounted"; 00561 } 00562 else { 00563 mountString = "-unmounted"; 00564 } 00565 00566 TQPixmap ret = DesktopIcon("drive-harddisk" + mountString, size); 00567 00568 if (isDiskOfType(TDEDiskDeviceType::Floppy)) { 00569 ret = DesktopIcon("media-floppy-3_5" + mountString, size); 00570 } 00571 if (isDiskOfType(TDEDiskDeviceType::Optical)) { 00572 ret = DesktopIcon("media-optical-cdrom" + mountString, size); 00573 } 00574 if (isDiskOfType(TDEDiskDeviceType::CDROM)) { 00575 ret = DesktopIcon("media-optical-cdrom" + mountString, size); 00576 } 00577 if (isDiskOfType(TDEDiskDeviceType::CDRW)) { 00578 ret = DesktopIcon("cd-rw" + mountString, size); 00579 } 00580 if (isDiskOfType(TDEDiskDeviceType::DVDROM)) { 00581 ret = DesktopIcon("media-optical-dvd" + mountString, size); 00582 } 00583 if (isDiskOfType(TDEDiskDeviceType::DVDRW)) { 00584 ret = DesktopIcon("media-optical-dvd" + mountString, size); 00585 } 00586 if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) { 00587 ret = DesktopIcon("media-optical-dvd" + mountString, size); 00588 } 00589 if (isDiskOfType(TDEDiskDeviceType::Zip)) { 00590 ret = DesktopIcon("media-floppy-zip" + mountString, size); 00591 } 00592 if (isDiskOfType(TDEDiskDeviceType::Tape)) { 00593 ret = DesktopIcon("media-tape" + mountString, size); 00594 } 00595 if (isDiskOfType(TDEDiskDeviceType::Camera)) { 00596 ret = DesktopIcon("camera" + mountString, size); 00597 } 00598 00599 if (isDiskOfType(TDEDiskDeviceType::HDD)) { 00600 ret = DesktopIcon("drive-harddisk" + mountString, size); 00601 if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) { 00602 ret = DesktopIcon("media-flash-usb" + mountString, size); 00603 } 00604 if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) { 00605 ret = DesktopIcon("media-flash-compact_flash" + mountString, size); 00606 } 00607 if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) { 00608 ret = DesktopIcon("media-flash-memory_stick" + mountString, size); 00609 } 00610 if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) { 00611 ret = DesktopIcon("media-flash-smart_media" + mountString, size); 00612 } 00613 if (isDiskOfType(TDEDiskDeviceType::SDMMC)) { 00614 ret = DesktopIcon("media-flash-sd_mmc" + mountString, size); 00615 } 00616 } 00617 00618 if (isDiskOfType(TDEDiskDeviceType::RAM)) { 00619 ret = DesktopIcon("memory", size); // FIXME there is only a single icon available for this device 00620 } 00621 if (isDiskOfType(TDEDiskDeviceType::Loop)) { 00622 ret = DesktopIcon("blockdevice", size); // FIXME there is only a single icon available for this device 00623 } 00624 00625 return ret; 00626 } 00627 00628 unsigned long long TDEStorageDevice::deviceSize() { 00629 TQString bsnodename = systemPath(); 00630 // 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 00631 // appears to only ever report the device size in 512 byte units. This does not appear to be documented anywhere! 00632 TQString blocksize = "512"; 00633 00634 TQString dsnodename = systemPath(); 00635 dsnodename.append("/size"); 00636 TQFile dsfile( dsnodename ); 00637 TQString devicesize; 00638 if ( dsfile.open( IO_ReadOnly ) ) { 00639 TQTextStream stream( &dsfile ); 00640 devicesize = stream.readLine(); 00641 dsfile.close(); 00642 } 00643 00644 return ((unsigned long long)blocksize.toULong()*(unsigned long long)devicesize.toULong()); 00645 } 00646 00647 TQString TDEStorageDevice::deviceFriendlySize() { 00648 return TDEHardwareDevices::bytesToFriendlySizeString(deviceSize()); 00649 } 00650 00651 TQString TDEStorageDevice::mountPath() { 00652 // See if this device node is mounted 00653 // This requires parsing /proc/mounts, looking for deviceNode() 00654 00655 // The Device Mapper throws a monkey wrench into this 00656 // It likes to advertise mounts as /dev/mapper/<something>, 00657 // where <something> is listed in <system path>/dm/name 00658 00659 // First, ensure that all device information (mainly holders/slaves) is accurate 00660 TDEGlobal::hardwareDevices()->rescanDeviceInformation(this); 00661 00662 TQString dmnodename = systemPath(); 00663 dmnodename.append("/dm/name"); 00664 TQFile namefile( dmnodename ); 00665 TQString dmaltname; 00666 if ( namefile.open( IO_ReadOnly ) ) { 00667 TQTextStream stream( &namefile ); 00668 dmaltname = stream.readLine(); 00669 namefile.close(); 00670 } 00671 if (!dmaltname.isNull()) { 00672 dmaltname.prepend("/dev/mapper/"); 00673 } 00674 00675 TQStringList lines; 00676 TQFile file( "/proc/mounts" ); 00677 if ( file.open( IO_ReadOnly ) ) { 00678 TQTextStream stream( &file ); 00679 TQString line; 00680 while ( !stream.atEnd() ) { 00681 line = stream.readLine(); 00682 TQStringList mountInfo = TQStringList::split(" ", line, true); 00683 TQString testNode = *mountInfo.at(0); 00684 // Check for match 00685 if ((testNode == deviceNode()) || (testNode == dmaltname) || (testNode == ("/dev/disk/by-uuid/" + diskUUID()))) { 00686 TQString ret = *mountInfo.at(1); 00687 ret.replace("\\040", " "); 00688 return ret; 00689 } 00690 lines += line; 00691 } 00692 file.close(); 00693 } 00694 00695 // While this device is not directly mounted, it could concievably be mounted via the Device Mapper 00696 // If so, try to retrieve the mount path... 00697 TQStringList slaveDeviceList = holdingDevices(); 00698 for ( TQStringList::Iterator slavedevit = slaveDeviceList.begin(); slavedevit != slaveDeviceList.end(); ++slavedevit ) { 00699 // Try to locate this device path in the TDE device tree 00700 TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices(); 00701 TDEGenericDevice *hwdevice = hwdevices->findBySystemPath(*slavedevit); 00702 if ((hwdevice) && (hwdevice->type() == TDEGenericDeviceType::Disk)) { 00703 TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice); 00704 return sdevice->mountPath(); 00705 } 00706 } 00707 00708 return TQString::null; 00709 } 00710 00711 TQStringVariantMap TDEStorageDevice::mountDevice(TQString mediaName, TDEStorageMountOptions mountOptions) { 00712 TQStringVariantMap result; 00713 00714 // Check if device is already mounted 00715 TQString mountpath = mountPath(); 00716 if (!mountpath.isEmpty()) { 00717 result["mountPath"] = mountpath; 00718 result["result"] = true; 00719 return result; 00720 } 00721 00722 TQString devNode = deviceNode(); 00723 devNode.replace("'", "'\\''"); 00724 mediaName.replace("'", "'\\''"); 00725 TQString command = TQString::null; 00726 00727 #if defined(WITH_UDISKS2) || defined(WITH_UDISKS) || defined(WITH_UDEVIL) 00728 // Prepare filesystem options for mount 00729 TQStringList udisksOptions; 00730 if (mountOptions["ro"] == "true") { 00731 udisksOptions.append("ro"); 00732 } 00733 00734 if (mountOptions["atime"] != "true") { 00735 udisksOptions.append("noatime"); 00736 } 00737 00738 if (mountOptions["sync"] == "true") { 00739 udisksOptions.append("sync"); 00740 } 00741 00742 if ((mountOptions["filesystem"] == "fat") || (mountOptions["filesystem"] == "vfat") || 00743 (mountOptions["filesystem"] == "msdos") || (mountOptions["filesystem"] == "umsdos")) { 00744 if (mountOptions.contains("shortname")) { 00745 udisksOptions.append(TQString("shortname=%1").arg(mountOptions["shortname"])); 00746 } 00747 } 00748 00749 if ((mountOptions["filesystem"] == "jfs")) { 00750 if (mountOptions["utf8"] == "true") { 00751 // udisks/udisks2 for now does not support option iocharset= for jfs 00752 // udisksOptions.append("iocharset=utf8"); 00753 } 00754 } 00755 00756 if ((mountOptions["filesystem"] == "ntfs-3g")) { 00757 if (mountOptions.contains("locale")) { 00758 udisksOptions.append(TQString("locale=%1").arg(mountOptions["locale"])); 00759 } 00760 } 00761 00762 if ((mountOptions["filesystem"] == "ext3") || (mountOptions["filesystem"] == "ext4")) { 00763 if (mountOptions.contains("journaling")) { 00764 // udisks/udisks2 for now does not support option data= for ext3/ext4 00765 // udisksOptions.append(TQString("data=%1").arg(mountOptions["journaling"])); 00766 } 00767 } 00768 00769 TQString optionString; 00770 for (TQStringList::Iterator it = udisksOptions.begin(); it != udisksOptions.end(); ++it) { 00771 optionString.append(","); 00772 optionString.append(*it); 00773 } 00774 00775 if (!optionString.isEmpty()) { 00776 optionString.remove(0, 1); 00777 } 00778 00779 TQString fileSystemType; 00780 if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { 00781 fileSystemType = mountOptions["filesystem"]; 00782 } 00783 00784 TQStringVariantMap mountResult; 00785 #endif 00786 00787 #if defined(WITH_UDISKS2) 00788 // Try to use UDISKS v2 via DBUS, if available 00789 mountResult = UDisks2MountDrive(devNode, fileSystemType, optionString); 00790 if (mountResult["result"].toBool()) { 00791 // Update internal mount data 00792 TDEGlobal::hardwareDevices()->processModifiedMounts(); 00793 result["mountPath"] = mountPath(); 00794 result["result"] = true; 00795 return result; 00796 } 00797 else if (mountResult["retcode"].toInt() == -1) { 00798 // Update internal mount data 00799 TDEGlobal::hardwareDevices()->processModifiedMounts(); 00800 result["errStr"] = mountResult["errStr"]; 00801 result["result"] = false; 00802 return result; 00803 } 00804 #endif 00805 00806 #if defined(WITH_UDISKS) 00807 // The UDISKS v2 DBUS service was either not available or was unusable 00808 // Try to use UDISKS v1 via DBUS, if available 00809 mountResult = UDisksMountDrive(devNode, fileSystemType, udisksOptions); 00810 if (mountResult["result"].toBool()) { 00811 // Update internal mount data 00812 TDEGlobal::hardwareDevices()->processModifiedMounts(); 00813 result["mountPath"] = mountPath(); 00814 result["result"] = true; 00815 return result; 00816 } 00817 else if (mountResult["retcode"].toInt() == -1) { 00818 // Update internal mount data 00819 TDEGlobal::hardwareDevices()->processModifiedMounts(); 00820 result["errStr"] = mountResult["errStr"]; 00821 result["result"] = false; 00822 return result; 00823 } 00824 #endif 00825 00826 #if defined(WITH_UDEVIL) 00827 // The UDISKS v1 DBUS service was either not available or was unusable 00828 // Use 'udevil' command, if available 00829 if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) { 00830 if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { 00831 fileSystemType = TQString("-t %1").arg(mountOptions["filesystem"]); 00832 } 00833 TQString mountpoint; 00834 if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() && 00835 (mountOptions["mountpoint"] != "/media/")) { 00836 mountpoint = mountOptions["mountpoint"]; 00837 mountpoint.replace("'", "'\\''"); 00838 } 00839 else { 00840 mountpoint = TQString("/media/%1").arg(mediaName); 00841 } 00842 command = TQString("udevil mount %1 -o '%2' '%3' '%4' 2>&1") 00843 .arg(fileSystemType).arg(optionString).arg(devNode).arg(mountpoint); 00844 } 00845 #endif 00846 00847 // If no other method was found, use 'pmount' command if available 00848 if(command.isEmpty()) { 00849 if (!TDEGlobal::dirs()->findExe("pmount").isEmpty()) { 00850 // Create dummy password file 00851 KTempFile passwordFile(TQString::null, "tmp", 0600); 00852 passwordFile.setAutoDelete(true); 00853 00854 TQString optionString; 00855 if (mountOptions["ro"] == "true") { 00856 optionString.append(" -r"); 00857 } 00858 00859 if (mountOptions["atime"] != "true") { 00860 optionString.append(" -A"); 00861 } 00862 00863 if (mountOptions["utf8"] == "true") { 00864 optionString.append(" -c utf8"); 00865 } 00866 00867 if (mountOptions["sync"] == "true") { 00868 optionString.append(" -s"); 00869 } 00870 00871 if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { 00872 optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"])); 00873 } 00874 00875 if (mountOptions.contains("locale")) { 00876 optionString.append(TQString(" -c %1").arg(mountOptions["locale"])); 00877 } 00878 00879 TQString mountpoint; 00880 if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() && 00881 (mountOptions["mountpoint"] != "/media/")) { 00882 mountpoint = mountOptions["mountpoint"]; 00883 mountpoint.replace("'", "'\\''"); 00884 } 00885 else { 00886 mountpoint = mediaName; 00887 } 00888 00889 TQString passFileName = passwordFile.name(); 00890 passFileName.replace("'", "'\\''"); 00891 00892 command = TQString("pmount -p '%1' %2 '%3' '%4' 2>&1") 00893 .arg(passFileName).arg(optionString).arg(devNode).arg(mountpoint); 00894 } 00895 } 00896 00897 if(command.isEmpty()) { 00898 result["errStr"] = i18n("No supported mounting methods were detected on your system"); 00899 result["result"] = false; 00900 return result; 00901 } 00902 00903 FILE *exepipe = popen(command.local8Bit(), "r"); 00904 if (exepipe) { 00905 TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); 00906 TQString mount_output = ts->read(); 00907 delete ts; 00908 int retcode = pclose(exepipe); 00909 result["errStr"] = mount_output; 00910 result["retCode"] = retcode; 00911 } 00912 00913 // Update internal mount data 00914 TDEGlobal::hardwareDevices()->processModifiedMounts(); 00915 result["mountPath"] = mountPath(); 00916 result["result"] = !mountPath().isEmpty(); 00917 return result; 00918 } 00919 00920 TQStringVariantMap TDEStorageDevice::mountEncryptedDevice(TQString passphrase, TQString mediaName, 00921 TDEStorageMountOptions mountOptions) { 00922 TQStringVariantMap result; 00923 00924 // Check if device is already mounted 00925 TQString mountpath = mountPath(); 00926 if (!mountpath.isEmpty()) { 00927 result["mountPath"] = mountpath; 00928 result["result"] = true; 00929 return result; 00930 } 00931 00932 // Create dummy password file 00933 KTempFile passwordFile(TQString::null, "tmp", 0600); 00934 passwordFile.setAutoDelete(true); 00935 TQFile* pwFile = passwordFile.file(); 00936 if (!pwFile) { 00937 result["errStr"] = i18n("Cannot create temporary password file"); 00938 result["result"] = false; 00939 return result; 00940 } 00941 00942 pwFile->writeBlock(passphrase.ascii(), passphrase.length()); 00943 pwFile->flush(); 00944 00945 TQString optionString; 00946 if (mountOptions["ro"] == "true") { 00947 optionString.append(" -r"); 00948 } 00949 00950 if (mountOptions["atime"] != "true") { 00951 optionString.append(" -A"); 00952 } 00953 00954 if (mountOptions["utf8"] == "true") { 00955 optionString.append(" -c utf8"); 00956 } 00957 00958 if (mountOptions["sync"] == "true") { 00959 optionString.append(" -s"); 00960 } 00961 00962 if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) { 00963 optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"])); 00964 } 00965 00966 if (mountOptions.contains("locale")) { 00967 optionString.append(TQString(" -c %1").arg(mountOptions["locale"])); 00968 } 00969 00970 TQString passFileName = passwordFile.name(); 00971 TQString devNode = deviceNode(); 00972 passFileName.replace("'", "'\\''"); 00973 devNode.replace("'", "'\\''"); 00974 mediaName.replace("'", "'\\''"); 00975 TQString command = TQString("pmount -p '%1' %2 '%3' '%4' 2>&1") 00976 .arg(passFileName).arg(optionString).arg(devNode).arg(mediaName); 00977 00978 FILE *exepipe = popen(command.local8Bit(), "r"); 00979 if (exepipe) { 00980 TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); 00981 TQString mount_output = ts->read(); 00982 delete ts; 00983 int retcode = pclose(exepipe); 00984 result["errStr"] = mount_output; 00985 result["retCode"] = retcode; 00986 } 00987 00988 // Update internal mount data 00989 TDEGlobal::hardwareDevices()->processModifiedMounts(); 00990 result["mountPath"] = mountPath(); 00991 result["result"] = !mountPath().isEmpty(); 00992 return result; 00993 } 00994 00995 TQStringVariantMap TDEStorageDevice::unmountDevice() { 00996 TQStringVariantMap result; 00997 00998 // Check if device is already unmounted 00999 TQString mountpoint = mountPath(); 01000 if (mountpoint.isEmpty()) { 01001 result["result"] = true; 01002 return result; 01003 } 01004 01005 mountpoint.replace("'", "'\\''"); 01006 TQString devNode = deviceNode(); 01007 TQString command = TQString::null; 01008 TQStringVariantMap unmountResult; 01009 01010 #if defined(WITH_UDISKS2) 01011 // Try to use UDISKS v2 via DBUS, if available 01012 unmountResult = UDisks2UnmountDrive(devNode, TQString::null); 01013 if (unmountResult["result"].toBool()) { 01014 // Update internal mount data 01015 TDEGlobal::hardwareDevices()->processModifiedMounts(); 01016 result["result"] = true; 01017 return result; 01018 } 01019 else if (unmountResult["retcode"].toInt() == -1) { 01020 // Update internal mount data 01021 TDEGlobal::hardwareDevices()->processModifiedMounts(); 01022 result["errStr"] = unmountResult["errStr"]; 01023 result["result"] = false; 01024 return result; 01025 } 01026 #endif 01027 01028 #if defined(WITH_UDISKS) 01029 // The UDISKS v2 DBUS service was either not available or was unusable 01030 // Try to use UDISKS v1 via DBUS, if available 01031 unmountResult = UDisksUnmountDrive(devNode, TQStringList()); 01032 if (unmountResult["result"].toBool()) { 01033 // Update internal mount data 01034 TDEGlobal::hardwareDevices()->processModifiedMounts(); 01035 result["result"] = true; 01036 return result; 01037 } 01038 else if (unmountResult["retcode"].toInt() == -1) { 01039 // Update internal mount data 01040 TDEGlobal::hardwareDevices()->processModifiedMounts(); 01041 result["errStr"] = unmountResult["errStr"]; 01042 result["result"] = false; 01043 return result; 01044 } 01045 #endif 01046 01047 #if defined(WITH_UDEVIL) 01048 // The UDISKS v1 DBUS service was either not available or was unusable 01049 // Use 'udevil' command, if available 01050 if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) { 01051 command = TQString("udevil umount '%1' 2>&1").arg(mountpoint); 01052 } 01053 #endif 01054 01055 // If no other method was found, use 'pmount' command if available 01056 if(command.isEmpty() && !TDEGlobal::dirs()->findExe("pumount").isEmpty()) { 01057 command = TQString("pumount '%1' 2>&1").arg(mountpoint); 01058 } 01059 01060 if(command.isEmpty()) { 01061 result["errStr"] = i18n("No supported unmounting methods were detected on your system"); 01062 result["result"] = false; 01063 return result; 01064 } 01065 01066 FILE *exepipe = popen(command.local8Bit(), "r"); 01067 if (exepipe) { 01068 TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly); 01069 TQString umount_output = ts->read(); 01070 delete ts; 01071 int retcode = pclose(exepipe); 01072 if (retcode == 0) { 01073 // Update internal mount data 01074 TDEGlobal::hardwareDevices()->processModifiedMounts(); 01075 result["result"] = true; 01076 return result; 01077 } 01078 else { 01079 result["errStr"] = umount_output; 01080 result["retCode"] = retcode; 01081 } 01082 } 01083 01084 // Update internal mount data 01085 TDEGlobal::hardwareDevices()->processModifiedMounts(); 01086 result["result"] = false; 01087 return result; 01088 } 01089 01090 TQString TDEStorageDevice::determineFileSystemType(TQString path) { 01091 TQStringList mountTable; 01092 TQString prevPath = path; 01093 dev_t prevDev = 0; 01094 int pos; 01095 struct stat directory_info; 01096 if (path.startsWith("/")) { 01097 stat(path.local8Bit(), &directory_info); 01098 prevDev = directory_info.st_dev; 01099 // Walk the directory tree up to the root, checking for any change in st_dev 01100 // If a change is found, the previous value of path is the mount point itself 01101 while (path != "/") { 01102 pos = path.findRev("/", -1, true); 01103 if (pos < 0) { 01104 break; 01105 } 01106 path = path.mid(0, pos); 01107 if (path == "") { 01108 path = "/"; 01109 } 01110 stat(path.local8Bit(), &directory_info); 01111 if (directory_info.st_dev != prevDev) { 01112 break; 01113 } 01114 prevPath = path; 01115 prevDev = directory_info.st_dev; 01116 } 01117 } 01118 01119 // Read in mount table 01120 mountTable.clear(); 01121 TQFile file( "/proc/mounts" ); 01122 if ( file.open( IO_ReadOnly ) ) { 01123 TQTextStream stream( &file ); 01124 while ( !stream.atEnd() ) { 01125 mountTable.append(stream.readLine()); 01126 } 01127 file.close(); 01128 } 01129 01130 // Parse mount table 01131 TQStringList::Iterator it; 01132 for ( it = mountTable.begin(); it != mountTable.end(); ++it ) { 01133 TQStringList mountInfo = TQStringList::split(" ", (*it), true); 01134 if ((*mountInfo.at(1)) == prevPath) { 01135 return (*mountInfo.at(2)); 01136 } 01137 } 01138 01139 // Unknown file system type 01140 return TQString::null; 01141 } 01142 01143 #include "tdestoragedevice.moc"
Trinity API Reference