• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • tdecore
 

tdecore

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"

tdecore

Skip menu "tdecore"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

tdecore

Skip menu "tdecore"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for tdecore by doxygen 1.7.6.1
This website is maintained by Timothy Pearson.