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

tdecore

  • tdecore
  • tdehw
tdestoragedevice.cpp
1 /* This file is part of the TDE libraries
2  Copyright (C) 2012 Timothy Pearson <kb9vqf@pearsoncomputing.net>
3  (C) 2013 Golubev Alexander <fatzer2@gmail.com>
4 
5  This library is free software; you can redistribute it and/or
6  modify it under the terms of the GNU Library General Public
7  License version 2 as published by the Free Software Foundation.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "tdestoragedevice.h"
21 
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <sys/stat.h>
25 #include <sys/ioctl.h>
26 #include <linux/cdrom.h>
27 
28 #include <tqregexp.h>
29 #include <tqpixmap.h>
30 #include <tqfile.h>
31 
32 #include "kdebug.h"
33 #include "tdelocale.h"
34 #include "tdeglobal.h"
35 #include "kiconloader.h"
36 #include "tdetempfile.h"
37 #include "kstandarddirs.h"
38 #include "tdehardwaredevices.h"
39 #include "disksHelper.h"
40 
41 #include "config.h"
42 
43 #if defined(WITH_CRYPTSETUP)
44  #ifdef CRYPTSETUP_OLD_API
45  #define class cryptsetup_class
46  #define CRYPT_SLOT_INVALID INVALID
47  #define CRYPT_SLOT_INACTIVE INACTIVE
48  #define CRYPT_SLOT_ACTIVE ACTIVE
49  #define CRYPT_SLOT_BUSY BUSY
50  #define CRYPT_SLOT_ACTIVE_LAST ACTIVE
51  #include <libcryptsetup.h>
52  #undef class
53  #else
54  #include <libcryptsetup.h>
55  #endif
56 #endif
57 
58 TDEStorageDevice::TDEStorageDevice(TDEGenericDeviceType::TDEGenericDeviceType dt, TQString dn) : TDEGenericDevice(dt, dn), m_mediaInserted(true), m_cryptDevice(NULL) {
59  m_diskType = TDEDiskDeviceType::Null;
60  m_diskStatus = TDEDiskDeviceStatus::Null;
61 }
62 
63 TDEStorageDevice::~TDEStorageDevice() {
64 #if defined(WITH_CRYPTSETUP)
65  if (m_cryptDevice) {
66  crypt_free(m_cryptDevice);
67  m_cryptDevice = NULL;
68  }
69 #endif
70 }
71 
72 TDEDiskDeviceType::TDEDiskDeviceType TDEStorageDevice::diskType() {
73  return m_diskType;
74 }
75 
76 void TDEStorageDevice::internalGetLUKSKeySlotStatus() {
77 #if defined(WITH_CRYPTSETUP)
78  unsigned int i;
79  crypt_keyslot_info keyslot_status;
80  TDELUKSKeySlotStatus::TDELUKSKeySlotStatus tde_keyslot_status;
81 
82  m_cryptKeyslotStatus.clear();
83  for (i = 0; i < m_cryptKeySlotCount; i++) {
84  keyslot_status = crypt_keyslot_status(m_cryptDevice, i);
85  tde_keyslot_status = TDELUKSKeySlotStatus::Invalid;
86  if (keyslot_status == CRYPT_SLOT_INACTIVE) {
87  tde_keyslot_status = TDELUKSKeySlotStatus::Inactive;
88  }
89  else if (keyslot_status == CRYPT_SLOT_ACTIVE) {
90  tde_keyslot_status = TDELUKSKeySlotStatus::Active;
91  }
92  else if (keyslot_status == CRYPT_SLOT_ACTIVE_LAST) {
93  tde_keyslot_status = TDELUKSKeySlotStatus::Active | TDELUKSKeySlotStatus::Last;
94  }
95  m_cryptKeyslotStatus.append(tde_keyslot_status);
96  }
97 #endif
98 }
99 
100 void TDEStorageDevice::internalInitializeLUKSIfNeeded() {
101 #if defined(WITH_CRYPTSETUP)
102  int ret;
103 
104  if (m_diskType & TDEDiskDeviceType::LUKS) {
105  if (!m_cryptDevice) {
106  TQString node = deviceNode();
107  if (node != "") {
108  ret = crypt_init(&m_cryptDevice, node.ascii());
109  if (ret == 0) {
110  ret = crypt_load(m_cryptDevice, NULL, NULL);
111  if (ret == 0) {
112  int keyslot_count;
113 #if defined(CRYPTSETUP_OLD_API) || !defined(HAVE_CRYPTSETUP_GET_TYPE)
114  kdWarning() << "TDEStorageDevice: The version of libcryptsetup that TDE was compiled against was too old! Most LUKS features will not function" << endl;
115  m_cryptDeviceType = TQString::null;
116  keyslot_count = 0;
117 #else
118  m_cryptDeviceType = crypt_get_type(m_cryptDevice);
119  keyslot_count = crypt_keyslot_max(m_cryptDeviceType.ascii());
120 #endif
121  if (keyslot_count < 0) {
122  m_cryptKeySlotCount = 0;
123  }
124  else {
125  m_cryptKeySlotCount = keyslot_count;
126  }
127  internalGetLUKSKeySlotStatus();
128  }
129  }
130  else {
131  m_cryptDevice = NULL;
132  }
133  }
134  }
135  }
136  else {
137  if (m_cryptDevice) {
138  crypt_free(m_cryptDevice);
139  m_cryptDevice = NULL;
140  }
141  }
142 #endif
143 }
144 
145 void TDEStorageDevice::cryptSetOperationsUnlockPassword(TQByteArray password) {
146 #if defined(WITH_CRYPTSETUP)
147  crypt_memory_lock(NULL, 1);
148  m_cryptDevicePassword = password;
149 #endif
150 }
151 
152 void TDEStorageDevice::cryptClearOperationsUnlockPassword() {
153  m_cryptDevicePassword.fill(0);
154  m_cryptDevicePassword.resize(0);
155 #if defined(WITH_CRYPTSETUP)
156  crypt_memory_lock(NULL, 0);
157 #endif
158 }
159 
160 bool TDEStorageDevice::cryptOperationsUnlockPasswordSet() {
161  if (m_cryptDevicePassword.size() > 0) {
162  return true;
163  }
164  else {
165  return false;
166  }
167 }
168 
169 TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptCheckKey(unsigned int keyslot) {
170 #if defined(WITH_CRYPTSETUP)
171  int ret;
172 
173  if (m_cryptDevice) {
174  if (keyslot < m_cryptKeySlotCount) {
175  ret = crypt_activate_by_passphrase(m_cryptDevice, NULL, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), 0);
176  if (ret < 0) {
177  return TDELUKSResult::KeyslotOpFailed;
178  }
179  else {
180  return TDELUKSResult::Success;
181  }
182  }
183  else {
184  return TDELUKSResult::InvalidKeyslot;
185  }
186  }
187  else {
188  return TDELUKSResult::LUKSNotFound;
189  }
190 #else
191  return TDELUKSResult::LUKSNotSupported;
192 #endif
193 }
194 
195 TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptAddKey(unsigned int keyslot, TQByteArray password) {
196 #if defined(WITH_CRYPTSETUP)
197  int ret;
198 
199  if (m_cryptDevice) {
200  if (keyslot < m_cryptKeySlotCount) {
201  ret = crypt_keyslot_add_by_passphrase(m_cryptDevice, keyslot, m_cryptDevicePassword.data(), m_cryptDevicePassword.size(), password.data(), password.size());
202  if (ret < 0) {
203  return TDELUKSResult::KeyslotOpFailed;
204  }
205  else {
206  internalGetLUKSKeySlotStatus();
207  return TDELUKSResult::Success;
208  }
209  }
210  else {
211  return TDELUKSResult::InvalidKeyslot;
212  }
213  }
214  else {
215  return TDELUKSResult::LUKSNotFound;
216  }
217 #else
218  return TDELUKSResult::LUKSNotSupported;
219 #endif
220 }
221 
222 TDELUKSResult::TDELUKSResult TDEStorageDevice::cryptDelKey(unsigned int keyslot) {
223 #if defined(WITH_CRYPTSETUP)
224  int ret;
225 
226  if (m_cryptDevice) {
227  if (keyslot < m_cryptKeySlotCount) {
228  ret = crypt_keyslot_destroy(m_cryptDevice, keyslot);
229  if (ret < 0) {
230  return TDELUKSResult::KeyslotOpFailed;
231  }
232  else {
233  internalGetLUKSKeySlotStatus();
234  return TDELUKSResult::Success;
235  }
236  }
237  else {
238  return TDELUKSResult::InvalidKeyslot;
239  }
240  }
241  else {
242  return TDELUKSResult::LUKSNotFound;
243  }
244 #else
245  return TDELUKSResult::LUKSNotSupported;
246 #endif
247 }
248 
249 unsigned int TDEStorageDevice::cryptKeySlotCount() {
250  return m_cryptKeySlotCount;
251 }
252 
253 TDELUKSKeySlotStatusList TDEStorageDevice::cryptKeySlotStatus() {
254  return m_cryptKeyslotStatus;
255 }
256 
257 TQString TDEStorageDevice::cryptKeySlotFriendlyName(TDELUKSKeySlotStatus::TDELUKSKeySlotStatus status) {
258  if (status & TDELUKSKeySlotStatus::Inactive) {
259  return i18n("Inactive");
260  }
261  else if (status & TDELUKSKeySlotStatus::Active) {
262  return i18n("Active");
263  }
264  else {
265  return i18n("Unknown");
266  }
267 }
268 
269 void TDEStorageDevice::internalSetDeviceNode(TQString sn) {
270  TDEGenericDevice::internalSetDeviceNode(sn);
271  internalInitializeLUKSIfNeeded();
272 }
273 
274 void TDEStorageDevice::internalSetDiskType(TDEDiskDeviceType::TDEDiskDeviceType dt) {
275  m_diskType = dt;
276  internalInitializeLUKSIfNeeded();
277 }
278 
279 bool TDEStorageDevice::isDiskOfType(TDEDiskDeviceType::TDEDiskDeviceType tf) {
280  return ((m_diskType&tf)!=TDEDiskDeviceType::Null);
281 }
282 
283 TDEDiskDeviceStatus::TDEDiskDeviceStatus TDEStorageDevice::diskStatus() {
284  return m_diskStatus;
285 }
286 
287 void TDEStorageDevice::internalSetDiskStatus(TDEDiskDeviceStatus::TDEDiskDeviceStatus st) {
288  m_diskStatus = st;
289 }
290 
291 bool TDEStorageDevice::checkDiskStatus(TDEDiskDeviceStatus::TDEDiskDeviceStatus sf) {
292  return ((m_diskStatus&sf)!=(TDEDiskDeviceStatus::TDEDiskDeviceStatus)0);
293 }
294 
295 bool TDEStorageDevice::lockDriveMedia(bool lock) {
296  int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK);
297  if (fd < 0) {
298  return false;
299  }
300  if (ioctl(fd, CDROM_LOCKDOOR, (lock)?1:0) != 0) {
301  close(fd);
302  return false;
303  }
304  else {
305  close(fd);
306  return true;
307  }
308 }
309 
310 bool TDEStorageDevice::ejectDrive() {
311 #ifdef WITH_UDISKS2
312  if (!(TDEGlobal::dirs()->findExe("udisksctl").isEmpty())) {
313  TQStringVariantMap ejectResult = UDisks2EjectDrive(this);
314  if (ejectResult["result"].toBool()) {
315  return true;
316  }
317  else {
318  printf("[tdehwlib] Failed to eject drive '%s' via udisks2, falling back to alternate mechanism\n", deviceNode().ascii());
319  fflush(stdout);
320  }
321  }
322 #endif
323 #ifdef WITH_UDISKS
324  if (!(TDEGlobal::dirs()->findExe("udisks").isEmpty())) {
325  TQStringVariantMap ejectResult = UDisksEjectDrive(this);
326  if (ejectResult["result"].toBool()) {
327  return true;
328  }
329  else {
330  printf("[tdehwlib] Failed to eject drive '%s' via udisks, falling back to alternate mechanism\n", deviceNode().ascii());
331  fflush(stdout);
332  }
333  }
334 #endif
335 
336  if (!(TDEGlobal::dirs()->findExe("eject").isEmpty())) {
337  TQString command = TQString("eject -v '%1' 2>&1").arg(deviceNode());
338 
339  FILE *exepipe = popen(command.ascii(), "r");
340  if (exepipe) {
341  TQString eject_output;
342  TQTextStream ts(exepipe, IO_ReadOnly);
343  eject_output = ts.read();
344  int retcode = pclose(exepipe);
345  if (retcode == 0) {
346  return true;
347  }
348  }
349  printf("[tdehwlib] Failed to eject drive '%s' via 'eject' command\n", deviceNode().ascii());
350  fflush(stdout);
351  }
352 
353  return false;
354 }
355 
356 bool TDEStorageDevice::ejectDriveMedia() {
357  int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK);
358  if (fd < 0) {
359  return false;
360  }
361  if (ioctl(fd, CDROMEJECT) != 0) {
362  close(fd);
363  return false;
364  }
365  else {
366  close(fd);
367  return true;
368  }
369 }
370 
371 TQString TDEStorageDevice::diskLabel() {
372  return m_diskName;
373 }
374 
375 void TDEStorageDevice::internalSetDiskLabel(TQString dn) {
376  m_diskName = dn;
377 }
378 
379 bool TDEStorageDevice::mediaInserted() {
380  return m_mediaInserted;
381 }
382 
383 void TDEStorageDevice::internalSetMediaInserted(bool inserted) {
384  m_mediaInserted = inserted;
385 }
386 
387 TQString TDEStorageDevice::fileSystemName() {
388  return m_fileSystemName;
389 }
390 
391 void TDEStorageDevice::internalSetFileSystemName(TQString fn) {
392  m_fileSystemName = fn;
393 }
394 
395 TQString TDEStorageDevice::fileSystemUsage() {
396  return m_fileSystemUsage;
397 }
398 
399 void TDEStorageDevice::internalSetFileSystemUsage(TQString fu) {
400  m_fileSystemUsage = fu;
401 }
402 
403 TQString TDEStorageDevice::diskUUID() {
404  return m_diskUUID;
405 }
406 
407 void TDEStorageDevice::internalSetDiskUUID(TQString id) {
408  m_diskUUID = id;
409 }
410 
411 TQStringList TDEStorageDevice::holdingDevices() {
412  return m_holdingDevices;
413 }
414 
415 void TDEStorageDevice::internalSetHoldingDevices(TQStringList hd) {
416  m_holdingDevices = hd;
417 }
418 
419 TQStringList TDEStorageDevice::slaveDevices() {
420  return m_slaveDevices;
421 }
422 
423 void TDEStorageDevice::internalSetSlaveDevices(TQStringList sd) {
424  m_slaveDevices = sd;
425 }
426 
427 TQString decodeHexEncoding(TQString str) {
428  TQRegExp hexEncRegExp("\\\\x[0-9A-Fa-f]{1,2}");
429  hexEncRegExp.setMinimal(false);
430  hexEncRegExp.setCaseSensitive(true);
431  int s = -1;
432 
433  while((s = hexEncRegExp.search(str, s+1))>=0){
434  str.replace(s, hexEncRegExp.cap(0).length(), TQChar((char)strtol(hexEncRegExp.cap(0).mid(2).ascii(), NULL, 16)));
435  }
436 
437  return str;
438 }
439 
440 TQString TDEStorageDevice::friendlyName() {
441  // Return the actual storage device name
442  TQString devicevendorid = vendorEncoded();
443  TQString devicemodelid = modelEncoded();
444 
445  devicevendorid = decodeHexEncoding(devicevendorid);
446  devicemodelid = decodeHexEncoding(devicemodelid);
447 
448  devicevendorid = devicevendorid.stripWhiteSpace();
449  devicemodelid = devicemodelid.stripWhiteSpace();
450  devicevendorid = devicevendorid.simplifyWhiteSpace();
451  devicemodelid = devicemodelid.simplifyWhiteSpace();
452 
453  TQString devicename = devicevendorid + " " + devicemodelid;
454 
455  devicename = devicename.stripWhiteSpace();
456  devicename = devicename.simplifyWhiteSpace();
457 
458  if (devicename != "") {
459  return devicename;
460  }
461 
462  if (isDiskOfType(TDEDiskDeviceType::Camera)) {
463  return TDEGenericDevice::friendlyName();
464  }
465 
466  if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
467  return friendlyDeviceType();
468  }
469 
470  TQString label = diskLabel();
471  if (label.isNull()) {
472  if (deviceSize() > 0) {
473  if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
474  label = i18n("%1 Removable Device").arg(deviceFriendlySize());
475  }
476  else {
477  label = i18n("%1 Fixed Storage Device").arg(deviceFriendlySize());
478  }
479  }
480  }
481 
482  if (!label.isNull()) {
483  return label;
484  }
485 
486  return friendlyDeviceType();
487 }
488 
489 TQString TDEStorageDevice::detailedFriendlyName() {
490  return TQString("%1 [%2]").arg(friendlyName()).arg(deviceNode());
491 }
492 
493 TQString TDEStorageDevice::friendlyDeviceType() {
494  TQString ret = i18n("Hard Disk Drive");
495 
496  // Keep this in sync with TDEStorageDevice::icon(TDEIcon::StdSizes size) below
497  if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
498  ret = i18n("Floppy Drive");
499  }
500  if (isDiskOfType(TDEDiskDeviceType::Optical)) {
501  ret = i18n("Optical Drive");
502  }
503  if (isDiskOfType(TDEDiskDeviceType::CDROM)) {
504  ret = i18n("CDROM Drive");
505  }
506  if (isDiskOfType(TDEDiskDeviceType::CDRW)) {
507  ret = i18n("CDRW Drive");
508  }
509  if (isDiskOfType(TDEDiskDeviceType::DVDROM)) {
510  ret = i18n("DVD Drive");
511  }
512  if (isDiskOfType(TDEDiskDeviceType::DVDRW)) {
513  ret = i18n("DVDRW Drive");
514  }
515  if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) {
516  ret = i18n("DVDRAM Drive");
517  }
518  if (isDiskOfType(TDEDiskDeviceType::Zip)) {
519  ret = i18n("Zip Drive");
520  }
521  if (isDiskOfType(TDEDiskDeviceType::Tape)) {
522  ret = i18n("Tape Drive");
523  }
524  if (isDiskOfType(TDEDiskDeviceType::Camera)) {
525  ret = i18n("Digital Camera");
526  }
527 
528  if (isDiskOfType(TDEDiskDeviceType::HDD)) {
529  ret = i18n("Hard Disk Drive");
530  if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
531  ret = i18n("Removable Storage");
532  }
533  if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
534  ret = i18n("Compact Flash");
535  }
536  if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) {
537  ret = i18n("Memory Stick");
538  }
539  if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) {
540  ret = i18n("Smart Media");
541  }
542  if (isDiskOfType(TDEDiskDeviceType::SDMMC)) {
543  ret = i18n("Secure Digital");
544  }
545  }
546 
547  if (isDiskOfType(TDEDiskDeviceType::RAM)) {
548  ret = i18n("Random Access Memory");
549  }
550  if (isDiskOfType(TDEDiskDeviceType::Loop)) {
551  ret = i18n("Loop Device");
552  }
553 
554  return ret;
555 }
556 
557 TQPixmap TDEStorageDevice::icon(TDEIcon::StdSizes size) {
558  TQString mountString;
559  if (mountPath() != TQString::null) {
560  mountString = "-mounted";
561  }
562  else {
563  mountString = "-unmounted";
564  }
565 
566  TQPixmap ret = DesktopIcon("drive-harddisk" + mountString, size);
567 
568  if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
569  ret = DesktopIcon("media-floppy-3_5" + mountString, size);
570  }
571  if (isDiskOfType(TDEDiskDeviceType::Optical)) {
572  ret = DesktopIcon("media-optical-cdrom" + mountString, size);
573  }
574  if (isDiskOfType(TDEDiskDeviceType::CDROM)) {
575  ret = DesktopIcon("media-optical-cdrom" + mountString, size);
576  }
577  if (isDiskOfType(TDEDiskDeviceType::CDRW)) {
578  ret = DesktopIcon("cd-rw" + mountString, size);
579  }
580  if (isDiskOfType(TDEDiskDeviceType::DVDROM)) {
581  ret = DesktopIcon("media-optical-dvd" + mountString, size);
582  }
583  if (isDiskOfType(TDEDiskDeviceType::DVDRW)) {
584  ret = DesktopIcon("media-optical-dvd" + mountString, size);
585  }
586  if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) {
587  ret = DesktopIcon("media-optical-dvd" + mountString, size);
588  }
589  if (isDiskOfType(TDEDiskDeviceType::Zip)) {
590  ret = DesktopIcon("media-floppy-zip" + mountString, size);
591  }
592  if (isDiskOfType(TDEDiskDeviceType::Tape)) {
593  ret = DesktopIcon("media-tape" + mountString, size);
594  }
595  if (isDiskOfType(TDEDiskDeviceType::Camera)) {
596  ret = DesktopIcon("camera" + mountString, size);
597  }
598 
599  if (isDiskOfType(TDEDiskDeviceType::HDD)) {
600  ret = DesktopIcon("drive-harddisk" + mountString, size);
601  if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
602  ret = DesktopIcon("media-flash-usb" + mountString, size);
603  }
604  if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
605  ret = DesktopIcon("media-flash-compact_flash" + mountString, size);
606  }
607  if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) {
608  ret = DesktopIcon("media-flash-memory_stick" + mountString, size);
609  }
610  if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) {
611  ret = DesktopIcon("media-flash-smart_media" + mountString, size);
612  }
613  if (isDiskOfType(TDEDiskDeviceType::SDMMC)) {
614  ret = DesktopIcon("media-flash-sd_mmc" + mountString, size);
615  }
616  }
617 
618  if (isDiskOfType(TDEDiskDeviceType::RAM)) {
619  ret = DesktopIcon("memory", size); // FIXME there is only a single icon available for this device
620  }
621  if (isDiskOfType(TDEDiskDeviceType::Loop)) {
622  ret = DesktopIcon("blockdevice", size); // FIXME there is only a single icon available for this device
623  }
624 
625  return ret;
626 }
627 
628 unsigned long long TDEStorageDevice::deviceSize() {
629  TQString bsnodename = systemPath();
630  // 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
631  // appears to only ever report the device size in 512 byte units. This does not appear to be documented anywhere!
632  TQString blocksize = "512";
633 
634  TQString dsnodename = systemPath();
635  dsnodename.append("/size");
636  TQFile dsfile( dsnodename );
637  TQString devicesize;
638  if ( dsfile.open( IO_ReadOnly ) ) {
639  TQTextStream stream( &dsfile );
640  devicesize = stream.readLine();
641  dsfile.close();
642  }
643 
644  return ((unsigned long long)blocksize.toULong()*(unsigned long long)devicesize.toULong());
645 }
646 
647 TQString TDEStorageDevice::deviceFriendlySize() {
648  return TDEHardwareDevices::bytesToFriendlySizeString(deviceSize());
649 }
650 
651 TQString TDEStorageDevice::mountPath() {
652  // See if this device node is mounted
653  // This requires parsing /proc/mounts, looking for deviceNode()
654 
655  // The Device Mapper throws a monkey wrench into this
656  // It likes to advertise mounts as /dev/mapper/<something>,
657  // where <something> is listed in <system path>/dm/name
658 
659  // First, ensure that all device information (mainly holders/slaves) is accurate
660  TDEGlobal::hardwareDevices()->rescanDeviceInformation(this);
661 
662  TQString dmnodename = systemPath();
663  dmnodename.append("/dm/name");
664  TQFile namefile( dmnodename );
665  TQString dmaltname;
666  if ( namefile.open( IO_ReadOnly ) ) {
667  TQTextStream stream( &namefile );
668  dmaltname = stream.readLine();
669  namefile.close();
670  }
671  if (!dmaltname.isNull()) {
672  dmaltname.prepend("/dev/mapper/");
673  }
674 
675  TQStringList lines;
676  TQFile file( "/proc/mounts" );
677  if ( file.open( IO_ReadOnly ) ) {
678  TQTextStream stream( &file );
679  TQString line;
680  while ( !stream.atEnd() ) {
681  line = stream.readLine();
682  TQStringList mountInfo = TQStringList::split(" ", line, true);
683  TQString testNode = *mountInfo.at(0);
684  // Check for match
685  if ((testNode == deviceNode()) || (testNode == dmaltname) || (testNode == ("/dev/disk/by-uuid/" + diskUUID()))) {
686  TQString ret = *mountInfo.at(1);
687  ret.replace("\\040", " ");
688  return ret;
689  }
690  lines += line;
691  }
692  file.close();
693  }
694 
695  // While this device is not directly mounted, it could concievably be mounted via the Device Mapper
696  // If so, try to retrieve the mount path...
697  TQStringList slaveDeviceList = holdingDevices();
698  for ( TQStringList::Iterator slavedevit = slaveDeviceList.begin(); slavedevit != slaveDeviceList.end(); ++slavedevit ) {
699  // Try to locate this device path in the TDE device tree
700  TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
701  TDEGenericDevice *hwdevice = hwdevices->findBySystemPath(*slavedevit);
702  if ((hwdevice) && (hwdevice->type() == TDEGenericDeviceType::Disk)) {
703  TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
704  return sdevice->mountPath();
705  }
706  }
707 
708  return TQString::null;
709 }
710 
711 TQStringVariantMap TDEStorageDevice::mountDevice(TQString mediaName, TDEStorageMountOptions mountOptions) {
712  TQStringVariantMap result;
713 
714  // Check if device is already mounted
715  TQString mountpath = mountPath();
716  if (!mountpath.isEmpty()) {
717  result["mountPath"] = mountpath;
718  result["result"] = true;
719  return result;
720  }
721 
722  TQString devNode = deviceNode();
723  devNode.replace("'", "'\\''");
724  mediaName.replace("'", "'\\''");
725  TQString command = TQString::null;
726 
727 #if defined(WITH_UDISKS2) || defined(WITH_UDISKS) || defined(WITH_UDEVIL)
728  // Prepare filesystem options for mount
729  TQStringList udisksOptions;
730  if (mountOptions["ro"] == "true") {
731  udisksOptions.append("ro");
732  }
733 
734  if (mountOptions["atime"] != "true") {
735  udisksOptions.append("noatime");
736  }
737 
738  if (mountOptions["sync"] == "true") {
739  udisksOptions.append("sync");
740  }
741 
742  if ((mountOptions["filesystem"] == "fat") || (mountOptions["filesystem"] == "vfat") ||
743  (mountOptions["filesystem"] == "msdos") || (mountOptions["filesystem"] == "umsdos")) {
744  if (mountOptions.contains("shortname")) {
745  udisksOptions.append(TQString("shortname=%1").arg(mountOptions["shortname"]));
746  }
747  }
748 
749  if ((mountOptions["filesystem"] == "jfs")) {
750  if (mountOptions["utf8"] == "true") {
751  // udisks/udisks2 for now does not support option iocharset= for jfs
752  // udisksOptions.append("iocharset=utf8");
753  }
754  }
755 
756  if ((mountOptions["filesystem"] == "ntfs-3g")) {
757  if (mountOptions.contains("locale")) {
758  udisksOptions.append(TQString("locale=%1").arg(mountOptions["locale"]));
759  }
760  }
761 
762  if ((mountOptions["filesystem"] == "ext3") || (mountOptions["filesystem"] == "ext4")) {
763  if (mountOptions.contains("journaling")) {
764  // udisks/udisks2 for now does not support option data= for ext3/ext4
765  // udisksOptions.append(TQString("data=%1").arg(mountOptions["journaling"]));
766  }
767  }
768 
769  TQString optionString;
770  for (TQStringList::Iterator it = udisksOptions.begin(); it != udisksOptions.end(); ++it) {
771  optionString.append(",");
772  optionString.append(*it);
773  }
774 
775  if (!optionString.isEmpty()) {
776  optionString.remove(0, 1);
777  }
778 
779  TQString fileSystemType;
780  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
781  fileSystemType = mountOptions["filesystem"];
782  }
783 
784  TQStringVariantMap mountResult;
785 #endif
786 
787 #if defined(WITH_UDISKS2)
788  // Try to use UDISKS v2 via DBUS, if available
789  mountResult = UDisks2MountDrive(devNode, fileSystemType, optionString);
790  if (mountResult["result"].toBool()) {
791  // Update internal mount data
792  TDEGlobal::hardwareDevices()->processModifiedMounts();
793  result["mountPath"] = mountPath();
794  result["result"] = true;
795  return result;
796  }
797  else if (mountResult["retcode"].toInt() == -1) {
798  // Update internal mount data
799  TDEGlobal::hardwareDevices()->processModifiedMounts();
800  result["errStr"] = mountResult["errStr"];
801  result["result"] = false;
802  return result;
803  }
804 #endif
805 
806 #if defined(WITH_UDISKS)
807  // The UDISKS v2 DBUS service was either not available or was unusable
808  // Try to use UDISKS v1 via DBUS, if available
809  mountResult = UDisksMountDrive(devNode, fileSystemType, udisksOptions);
810  if (mountResult["result"].toBool()) {
811  // Update internal mount data
812  TDEGlobal::hardwareDevices()->processModifiedMounts();
813  result["mountPath"] = mountPath();
814  result["result"] = true;
815  return result;
816  }
817  else if (mountResult["retcode"].toInt() == -1) {
818  // Update internal mount data
819  TDEGlobal::hardwareDevices()->processModifiedMounts();
820  result["errStr"] = mountResult["errStr"];
821  result["result"] = false;
822  return result;
823  }
824 #endif
825 
826 #if defined(WITH_UDEVIL)
827  // The UDISKS v1 DBUS service was either not available or was unusable
828  // Use 'udevil' command, if available
829  if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) {
830  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
831  fileSystemType = TQString("-t %1").arg(mountOptions["filesystem"]);
832  }
833  TQString mountpoint;
834  if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() &&
835  (mountOptions["mountpoint"] != "/media/")) {
836  mountpoint = mountOptions["mountpoint"];
837  mountpoint.replace("'", "'\\''");
838  }
839  else {
840  mountpoint = TQString("/media/%1").arg(mediaName);
841  }
842  command = TQString("udevil mount %1 -o '%2' '%3' '%4' 2>&1")
843  .arg(fileSystemType).arg(optionString).arg(devNode).arg(mountpoint);
844  }
845 #endif
846 
847  // If no other method was found, use 'pmount' command if available
848  if(command.isEmpty()) {
849  if (!TDEGlobal::dirs()->findExe("pmount").isEmpty()) {
850  // Create dummy password file
851  KTempFile passwordFile(TQString::null, "tmp", 0600);
852  passwordFile.setAutoDelete(true);
853 
854  TQString optionString;
855  if (mountOptions["ro"] == "true") {
856  optionString.append(" -r");
857  }
858 
859  if (mountOptions["atime"] != "true") {
860  optionString.append(" -A");
861  }
862 
863  if (mountOptions["utf8"] == "true") {
864  optionString.append(" -c utf8");
865  }
866 
867  if (mountOptions["sync"] == "true") {
868  optionString.append(" -s");
869  }
870 
871  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
872  optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"]));
873  }
874 
875  if (mountOptions.contains("locale")) {
876  optionString.append(TQString(" -c %1").arg(mountOptions["locale"]));
877  }
878 
879  TQString mountpoint;
880  if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() &&
881  (mountOptions["mountpoint"] != "/media/")) {
882  mountpoint = mountOptions["mountpoint"];
883  mountpoint.replace("'", "'\\''");
884  }
885  else {
886  mountpoint = mediaName;
887  }
888 
889  TQString passFileName = passwordFile.name();
890  passFileName.replace("'", "'\\''");
891 
892  command = TQString("pmount -p '%1' %2 '%3' '%4' 2>&1")
893  .arg(passFileName).arg(optionString).arg(devNode).arg(mountpoint);
894  }
895  }
896 
897  if(command.isEmpty()) {
898  result["errStr"] = i18n("No supported mounting methods were detected on your system");
899  result["result"] = false;
900  return result;
901  }
902 
903  FILE *exepipe = popen(command.local8Bit(), "r");
904  if (exepipe) {
905  TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly);
906  TQString mount_output = ts->read();
907  delete ts;
908  int retcode = pclose(exepipe);
909  result["errStr"] = mount_output;
910  result["retCode"] = retcode;
911  }
912 
913  // Update internal mount data
914  TDEGlobal::hardwareDevices()->processModifiedMounts();
915  result["mountPath"] = mountPath();
916  result["result"] = !mountPath().isEmpty();
917  return result;
918 }
919 
920 TQStringVariantMap TDEStorageDevice::mountEncryptedDevice(TQString passphrase, TQString mediaName,
921  TDEStorageMountOptions mountOptions) {
922  TQStringVariantMap result;
923 
924  // Check if device is already mounted
925  TQString mountpath = mountPath();
926  if (!mountpath.isEmpty()) {
927  result["mountPath"] = mountpath;
928  result["result"] = true;
929  return result;
930  }
931 
932  // Create dummy password file
933  KTempFile passwordFile(TQString::null, "tmp", 0600);
934  passwordFile.setAutoDelete(true);
935  TQFile* pwFile = passwordFile.file();
936  if (!pwFile) {
937  result["errStr"] = i18n("Cannot create temporary password file");
938  result["result"] = false;
939  return result;
940  }
941 
942  pwFile->writeBlock(passphrase.ascii(), passphrase.length());
943  pwFile->flush();
944 
945  TQString optionString;
946  if (mountOptions["ro"] == "true") {
947  optionString.append(" -r");
948  }
949 
950  if (mountOptions["atime"] != "true") {
951  optionString.append(" -A");
952  }
953 
954  if (mountOptions["utf8"] == "true") {
955  optionString.append(" -c utf8");
956  }
957 
958  if (mountOptions["sync"] == "true") {
959  optionString.append(" -s");
960  }
961 
962  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
963  optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"]));
964  }
965 
966  if (mountOptions.contains("locale")) {
967  optionString.append(TQString(" -c %1").arg(mountOptions["locale"]));
968  }
969 
970  TQString passFileName = passwordFile.name();
971  TQString devNode = deviceNode();
972  passFileName.replace("'", "'\\''");
973  devNode.replace("'", "'\\''");
974  mediaName.replace("'", "'\\''");
975  TQString command = TQString("pmount -p '%1' %2 '%3' '%4' 2>&1")
976  .arg(passFileName).arg(optionString).arg(devNode).arg(mediaName);
977 
978  FILE *exepipe = popen(command.local8Bit(), "r");
979  if (exepipe) {
980  TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly);
981  TQString mount_output = ts->read();
982  delete ts;
983  int retcode = pclose(exepipe);
984  result["errStr"] = mount_output;
985  result["retCode"] = retcode;
986  }
987 
988  // Update internal mount data
989  TDEGlobal::hardwareDevices()->processModifiedMounts();
990  result["mountPath"] = mountPath();
991  result["result"] = !mountPath().isEmpty();
992  return result;
993 }
994 
995 TQStringVariantMap TDEStorageDevice::unmountDevice() {
996  TQStringVariantMap result;
997 
998  // Check if device is already unmounted
999  TQString mountpoint = mountPath();
1000  if (mountpoint.isEmpty()) {
1001  result["result"] = true;
1002  return result;
1003  }
1004 
1005  mountpoint.replace("'", "'\\''");
1006  TQString devNode = deviceNode();
1007  TQString command = TQString::null;
1008  TQStringVariantMap unmountResult;
1009 
1010 #if defined(WITH_UDISKS2)
1011  // Try to use UDISKS v2 via DBUS, if available
1012  unmountResult = UDisks2UnmountDrive(devNode, TQString::null);
1013  if (unmountResult["result"].toBool()) {
1014  // Update internal mount data
1015  TDEGlobal::hardwareDevices()->processModifiedMounts();
1016  result["result"] = true;
1017  return result;
1018  }
1019  else if (unmountResult["retcode"].toInt() == -1) {
1020  // Update internal mount data
1021  TDEGlobal::hardwareDevices()->processModifiedMounts();
1022  result["errStr"] = unmountResult["errStr"];
1023  result["result"] = false;
1024  return result;
1025  }
1026 #endif
1027 
1028 #if defined(WITH_UDISKS)
1029  // The UDISKS v2 DBUS service was either not available or was unusable
1030  // Try to use UDISKS v1 via DBUS, if available
1031  unmountResult = UDisksUnmountDrive(devNode, TQStringList());
1032  if (unmountResult["result"].toBool()) {
1033  // Update internal mount data
1034  TDEGlobal::hardwareDevices()->processModifiedMounts();
1035  result["result"] = true;
1036  return result;
1037  }
1038  else if (unmountResult["retcode"].toInt() == -1) {
1039  // Update internal mount data
1040  TDEGlobal::hardwareDevices()->processModifiedMounts();
1041  result["errStr"] = unmountResult["errStr"];
1042  result["result"] = false;
1043  return result;
1044  }
1045 #endif
1046 
1047 #if defined(WITH_UDEVIL)
1048  // The UDISKS v1 DBUS service was either not available or was unusable
1049  // Use 'udevil' command, if available
1050  if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) {
1051  command = TQString("udevil umount '%1' 2>&1").arg(mountpoint);
1052  }
1053 #endif
1054 
1055  // If no other method was found, use 'pmount' command if available
1056  if(command.isEmpty() && !TDEGlobal::dirs()->findExe("pumount").isEmpty()) {
1057  command = TQString("pumount '%1' 2>&1").arg(mountpoint);
1058  }
1059 
1060  if(command.isEmpty()) {
1061  result["errStr"] = i18n("No supported unmounting methods were detected on your system");
1062  result["result"] = false;
1063  return result;
1064  }
1065 
1066  FILE *exepipe = popen(command.local8Bit(), "r");
1067  if (exepipe) {
1068  TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly);
1069  TQString umount_output = ts->read();
1070  delete ts;
1071  int retcode = pclose(exepipe);
1072  if (retcode == 0) {
1073  // Update internal mount data
1074  TDEGlobal::hardwareDevices()->processModifiedMounts();
1075  result["result"] = true;
1076  return result;
1077  }
1078  else {
1079  result["errStr"] = umount_output;
1080  result["retCode"] = retcode;
1081  }
1082  }
1083 
1084  // Update internal mount data
1085  TDEGlobal::hardwareDevices()->processModifiedMounts();
1086  result["result"] = false;
1087  return result;
1088 }
1089 
1090 TQString TDEStorageDevice::determineFileSystemType(TQString path) {
1091  TQStringList mountTable;
1092  TQString prevPath = path;
1093  dev_t prevDev = 0;
1094  int pos;
1095  struct stat directory_info;
1096  if (path.startsWith("/")) {
1097  stat(path.local8Bit(), &directory_info);
1098  prevDev = directory_info.st_dev;
1099  // Walk the directory tree up to the root, checking for any change in st_dev
1100  // If a change is found, the previous value of path is the mount point itself
1101  while (path != "/") {
1102  pos = path.findRev("/", -1, true);
1103  if (pos < 0) {
1104  break;
1105  }
1106  path = path.mid(0, pos);
1107  if (path == "") {
1108  path = "/";
1109  }
1110  stat(path.local8Bit(), &directory_info);
1111  if (directory_info.st_dev != prevDev) {
1112  break;
1113  }
1114  prevPath = path;
1115  prevDev = directory_info.st_dev;
1116  }
1117  }
1118 
1119  // Read in mount table
1120  mountTable.clear();
1121  TQFile file( "/proc/mounts" );
1122  if ( file.open( IO_ReadOnly ) ) {
1123  TQTextStream stream( &file );
1124  while ( !stream.atEnd() ) {
1125  mountTable.append(stream.readLine());
1126  }
1127  file.close();
1128  }
1129 
1130  // Parse mount table
1131  TQStringList::Iterator it;
1132  for ( it = mountTable.begin(); it != mountTable.end(); ++it ) {
1133  TQStringList mountInfo = TQStringList::split(" ", (*it), true);
1134  if ((*mountInfo.at(1)) == prevPath) {
1135  return (*mountInfo.at(2));
1136  }
1137  }
1138 
1139  // Unknown file system type
1140  return TQString::null;
1141 }
1142 
1143 #include "tdestoragedevice.moc"
TDEStdAccel::open
const TDEShortcut & open()
Open file.
Definition: tdestdaccel.cpp:270
TDEGlobal::dirs
static TDEStandardDirs * dirs()
Returns the application standard dirs object.
Definition: tdeglobal.cpp:58
tdelocale.h
TDEIcon::StdSizes
StdSizes
These are the standard sizes for icons.
Definition: kicontheme.h:112
TDEStandardDirs::findExe
static TQString findExe(const TQString &appname, const TQString &pathstr=TQString::null, bool ignoreExecBit=false)
Finds the executable in the system path.
Definition: kstandarddirs.cpp:932
TDEStdAccel::close
const TDEShortcut & close()
Close current document.
Definition: tdestdaccel.cpp:272
KTempFile
The KTempFile class creates and opens a unique file for temporary use.
Definition: tdetempfile.h:55
endl
kndbgstream & endl(kndbgstream &s)
Does nothing.
Definition: kdebug.h:583
TDEStdAccel::label
TQString label(StdAccel id)
Returns a localized label for user-visible display.
Definition: tdestdaccel.cpp:156

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.8.13
This website is maintained by Timothy Pearson.