• 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  if (!(TDEGlobal::dirs()->findExe("udisksctl").isEmpty())) {
312  TQStringVariantMap ejectResult = UDisks2EjectDrive(this);
313  if (ejectResult["result"].toBool()) {
314  return true;
315  }
316  else {
317  printf("[tdehwlib] Failed to eject drive '%s' via udisks2, falling back to alternate mechanism\n", deviceNode().ascii());
318  fflush(stdout);
319  }
320  }
321  if (!(TDEGlobal::dirs()->findExe("udisks").isEmpty())) {
322  TQStringVariantMap ejectResult = UDisksEjectDrive(this);
323  if (ejectResult["result"].toBool()) {
324  return true;
325  }
326  else {
327  printf("[tdehwlib] Failed to eject drive '%s' via udisks, falling back to alternate mechanism\n", deviceNode().ascii());
328  fflush(stdout);
329  }
330  }
331 
332  if (!(TDEGlobal::dirs()->findExe("eject").isEmpty())) {
333  TQString command = TQString("eject -v '%1' 2>&1").arg(deviceNode());
334 
335  FILE *exepipe = popen(command.ascii(), "r");
336  if (exepipe) {
337  TQString eject_output;
338  TQTextStream ts(exepipe, IO_ReadOnly);
339  eject_output = ts.read();
340  int retcode = pclose(exepipe);
341  if (retcode == 0) {
342  return true;
343  }
344  }
345  printf("[tdehwlib] Failed to eject drive '%s' via 'eject' command\n", deviceNode().ascii());
346  fflush(stdout);
347  }
348 
349  return false;
350 }
351 
352 bool TDEStorageDevice::ejectDriveMedia() {
353  int fd = open(deviceNode().ascii(), O_RDWR | O_NONBLOCK);
354  if (fd < 0) {
355  return false;
356  }
357  if (ioctl(fd, CDROMEJECT) != 0) {
358  close(fd);
359  return false;
360  }
361  else {
362  close(fd);
363  return true;
364  }
365 }
366 
367 TQString TDEStorageDevice::diskLabel() {
368  return m_diskName;
369 }
370 
371 void TDEStorageDevice::internalSetDiskLabel(TQString dn) {
372  m_diskName = dn;
373 }
374 
375 bool TDEStorageDevice::mediaInserted() {
376  return m_mediaInserted;
377 }
378 
379 void TDEStorageDevice::internalSetMediaInserted(bool inserted) {
380  m_mediaInserted = inserted;
381 }
382 
383 TQString TDEStorageDevice::fileSystemName() {
384  return m_fileSystemName;
385 }
386 
387 void TDEStorageDevice::internalSetFileSystemName(TQString fn) {
388  m_fileSystemName = fn;
389 }
390 
391 TQString TDEStorageDevice::fileSystemUsage() {
392  return m_fileSystemUsage;
393 }
394 
395 void TDEStorageDevice::internalSetFileSystemUsage(TQString fu) {
396  m_fileSystemUsage = fu;
397 }
398 
399 TQString TDEStorageDevice::diskUUID() {
400  return m_diskUUID;
401 }
402 
403 void TDEStorageDevice::internalSetDiskUUID(TQString id) {
404  m_diskUUID = id;
405 }
406 
407 TQStringList TDEStorageDevice::holdingDevices() {
408  return m_holdingDevices;
409 }
410 
411 void TDEStorageDevice::internalSetHoldingDevices(TQStringList hd) {
412  m_holdingDevices = hd;
413 }
414 
415 TQStringList TDEStorageDevice::slaveDevices() {
416  return m_slaveDevices;
417 }
418 
419 void TDEStorageDevice::internalSetSlaveDevices(TQStringList sd) {
420  m_slaveDevices = sd;
421 }
422 
423 TQString decodeHexEncoding(TQString str) {
424  TQRegExp hexEncRegExp("\\\\x[0-9A-Fa-f]{1,2}");
425  hexEncRegExp.setMinimal(false);
426  hexEncRegExp.setCaseSensitive(true);
427  int s = -1;
428 
429  while((s = hexEncRegExp.search(str, s+1))>=0){
430  str.replace(s, hexEncRegExp.cap(0).length(), TQChar((char)strtol(hexEncRegExp.cap(0).mid(2).ascii(), NULL, 16)));
431  }
432 
433  return str;
434 }
435 
436 TQString TDEStorageDevice::friendlyName() {
437  // Return the actual storage device name
438  TQString devicevendorid = vendorEncoded();
439  TQString devicemodelid = modelEncoded();
440 
441  devicevendorid = decodeHexEncoding(devicevendorid);
442  devicemodelid = decodeHexEncoding(devicemodelid);
443 
444  devicevendorid = devicevendorid.stripWhiteSpace();
445  devicemodelid = devicemodelid.stripWhiteSpace();
446  devicevendorid = devicevendorid.simplifyWhiteSpace();
447  devicemodelid = devicemodelid.simplifyWhiteSpace();
448 
449  TQString devicename = devicevendorid + " " + devicemodelid;
450 
451  devicename = devicename.stripWhiteSpace();
452  devicename = devicename.simplifyWhiteSpace();
453 
454  if (devicename != "") {
455  return devicename;
456  }
457 
458  if (isDiskOfType(TDEDiskDeviceType::Camera)) {
459  return TDEGenericDevice::friendlyName();
460  }
461 
462  if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
463  return friendlyDeviceType();
464  }
465 
466  TQString label = diskLabel();
467  if (label.isNull()) {
468  if (deviceSize() > 0) {
469  if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
470  label = i18n("%1 Removable Device").arg(deviceFriendlySize());
471  }
472  else {
473  label = i18n("%1 Fixed Storage Device").arg(deviceFriendlySize());
474  }
475  }
476  }
477 
478  if (!label.isNull()) {
479  return label;
480  }
481 
482  return friendlyDeviceType();
483 }
484 
485 TQString TDEStorageDevice::detailedFriendlyName() {
486  return TQString("%1 [%2]").arg(friendlyName()).arg(deviceNode());
487 }
488 
489 TQString TDEStorageDevice::friendlyDeviceType() {
490  TQString ret = i18n("Hard Disk Drive");
491 
492  // Keep this in sync with TDEStorageDevice::icon(TDEIcon::StdSizes size) below
493  if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
494  ret = i18n("Floppy Drive");
495  }
496  if (isDiskOfType(TDEDiskDeviceType::Optical)) {
497  ret = i18n("Optical Drive");
498  }
499  if (isDiskOfType(TDEDiskDeviceType::CDROM)) {
500  ret = i18n("CDROM Drive");
501  }
502  if (isDiskOfType(TDEDiskDeviceType::CDRW)) {
503  ret = i18n("CDRW Drive");
504  }
505  if (isDiskOfType(TDEDiskDeviceType::DVDROM)) {
506  ret = i18n("DVD Drive");
507  }
508  if (isDiskOfType(TDEDiskDeviceType::DVDRW)) {
509  ret = i18n("DVDRW Drive");
510  }
511  if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) {
512  ret = i18n("DVDRAM Drive");
513  }
514  if (isDiskOfType(TDEDiskDeviceType::Zip)) {
515  ret = i18n("Zip Drive");
516  }
517  if (isDiskOfType(TDEDiskDeviceType::Tape)) {
518  ret = i18n("Tape Drive");
519  }
520  if (isDiskOfType(TDEDiskDeviceType::Camera)) {
521  ret = i18n("Digital Camera");
522  }
523 
524  if (isDiskOfType(TDEDiskDeviceType::HDD)) {
525  ret = i18n("Hard Disk Drive");
526  if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
527  ret = i18n("Removable Storage");
528  }
529  if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
530  ret = i18n("Compact Flash");
531  }
532  if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) {
533  ret = i18n("Memory Stick");
534  }
535  if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) {
536  ret = i18n("Smart Media");
537  }
538  if (isDiskOfType(TDEDiskDeviceType::SDMMC)) {
539  ret = i18n("Secure Digital");
540  }
541  }
542 
543  if (isDiskOfType(TDEDiskDeviceType::RAM)) {
544  ret = i18n("Random Access Memory");
545  }
546  if (isDiskOfType(TDEDiskDeviceType::Loop)) {
547  ret = i18n("Loop Device");
548  }
549 
550  return ret;
551 }
552 
553 TQPixmap TDEStorageDevice::icon(TDEIcon::StdSizes size) {
554  TQString mountString;
555  if (mountPath() != TQString::null) {
556  mountString = "-mounted";
557  }
558  else {
559  mountString = "-unmounted";
560  }
561 
562  TQPixmap ret = DesktopIcon("drive-harddisk" + mountString, size);
563 
564  if (isDiskOfType(TDEDiskDeviceType::Floppy)) {
565  ret = DesktopIcon("media-floppy-3_5" + mountString, size);
566  }
567  if (isDiskOfType(TDEDiskDeviceType::Optical)) {
568  ret = DesktopIcon("media-optical-cdrom" + mountString, size);
569  }
570  if (isDiskOfType(TDEDiskDeviceType::CDROM)) {
571  ret = DesktopIcon("media-optical-cdrom" + mountString, size);
572  }
573  if (isDiskOfType(TDEDiskDeviceType::CDRW)) {
574  ret = DesktopIcon("cd-rw" + mountString, size);
575  }
576  if (isDiskOfType(TDEDiskDeviceType::DVDROM)) {
577  ret = DesktopIcon("media-optical-dvd" + mountString, size);
578  }
579  if (isDiskOfType(TDEDiskDeviceType::DVDRW)) {
580  ret = DesktopIcon("media-optical-dvd" + mountString, size);
581  }
582  if (isDiskOfType(TDEDiskDeviceType::DVDRAM)) {
583  ret = DesktopIcon("media-optical-dvd" + mountString, size);
584  }
585  if (isDiskOfType(TDEDiskDeviceType::Zip)) {
586  ret = DesktopIcon("media-floppy-zip" + mountString, size);
587  }
588  if (isDiskOfType(TDEDiskDeviceType::Tape)) {
589  ret = DesktopIcon("media-tape" + mountString, size);
590  }
591  if (isDiskOfType(TDEDiskDeviceType::Camera)) {
592  ret = DesktopIcon("camera" + mountString, size);
593  }
594 
595  if (isDiskOfType(TDEDiskDeviceType::HDD)) {
596  ret = DesktopIcon("drive-harddisk" + mountString, size);
597  if (checkDiskStatus(TDEDiskDeviceStatus::Hotpluggable)) {
598  ret = DesktopIcon("media-flash-usb" + mountString, size);
599  }
600  if (isDiskOfType(TDEDiskDeviceType::CompactFlash)) {
601  ret = DesktopIcon("media-flash-compact_flash" + mountString, size);
602  }
603  if (isDiskOfType(TDEDiskDeviceType::MemoryStick)) {
604  ret = DesktopIcon("media-flash-memory_stick" + mountString, size);
605  }
606  if (isDiskOfType(TDEDiskDeviceType::SmartMedia)) {
607  ret = DesktopIcon("media-flash-smart_media" + mountString, size);
608  }
609  if (isDiskOfType(TDEDiskDeviceType::SDMMC)) {
610  ret = DesktopIcon("media-flash-sd_mmc" + mountString, size);
611  }
612  }
613 
614  if (isDiskOfType(TDEDiskDeviceType::RAM)) {
615  ret = DesktopIcon("memory", size); // FIXME there is only a single icon available for this device
616  }
617  if (isDiskOfType(TDEDiskDeviceType::Loop)) {
618  ret = DesktopIcon("blockdevice", size); // FIXME there is only a single icon available for this device
619  }
620 
621  return ret;
622 }
623 
624 unsigned long long TDEStorageDevice::deviceSize() {
625  TQString bsnodename = systemPath();
626  // 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
627  // appears to only ever report the device size in 512 byte units. This does not appear to be documented anywhere!
628  TQString blocksize = "512";
629 
630  TQString dsnodename = systemPath();
631  dsnodename.append("/size");
632  TQFile dsfile( dsnodename );
633  TQString devicesize;
634  if ( dsfile.open( IO_ReadOnly ) ) {
635  TQTextStream stream( &dsfile );
636  devicesize = stream.readLine();
637  dsfile.close();
638  }
639 
640  return ((unsigned long long)blocksize.toULong()*(unsigned long long)devicesize.toULong());
641 }
642 
643 TQString TDEStorageDevice::deviceFriendlySize() {
644  return TDEHardwareDevices::bytesToFriendlySizeString(deviceSize());
645 }
646 
647 TQString TDEStorageDevice::mountPath() {
648  // See if this device node is mounted
649  // This requires parsing /proc/mounts, looking for deviceNode()
650 
651  // The Device Mapper throws a monkey wrench into this
652  // It likes to advertise mounts as /dev/mapper/<something>,
653  // where <something> is listed in <system path>/dm/name
654 
655  // First, ensure that all device information (mainly holders/slaves) is accurate
656  TDEGlobal::hardwareDevices()->rescanDeviceInformation(this);
657 
658  TQString dmnodename = systemPath();
659  dmnodename.append("/dm/name");
660  TQFile namefile( dmnodename );
661  TQString dmaltname;
662  if ( namefile.open( IO_ReadOnly ) ) {
663  TQTextStream stream( &namefile );
664  dmaltname = stream.readLine();
665  namefile.close();
666  }
667  if (!dmaltname.isNull()) {
668  dmaltname.prepend("/dev/mapper/");
669  }
670 
671  TQStringList lines;
672  TQFile file( "/proc/mounts" );
673  if ( file.open( IO_ReadOnly ) ) {
674  TQTextStream stream( &file );
675  TQString line;
676  while ( !stream.atEnd() ) {
677  line = stream.readLine();
678  TQStringList mountInfo = TQStringList::split(" ", line, true);
679  TQString testNode = *mountInfo.at(0);
680  // Check for match
681  if ((testNode == deviceNode()) || (testNode == dmaltname) || (testNode == ("/dev/disk/by-uuid/" + diskUUID()))) {
682  TQString ret = *mountInfo.at(1);
683  ret.replace("\\040", " ");
684  return ret;
685  }
686  lines += line;
687  }
688  file.close();
689  }
690 
691  // While this device is not directly mounted, it could concievably be mounted via the Device Mapper
692  // If so, try to retrieve the mount path...
693  TQStringList slaveDeviceList = holdingDevices();
694  for ( TQStringList::Iterator slavedevit = slaveDeviceList.begin(); slavedevit != slaveDeviceList.end(); ++slavedevit ) {
695  // Try to locate this device path in the TDE device tree
696  TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
697  TDEGenericDevice *hwdevice = hwdevices->findBySystemPath(*slavedevit);
698  if ((hwdevice) && (hwdevice->type() == TDEGenericDeviceType::Disk)) {
699  TDEStorageDevice* sdevice = static_cast<TDEStorageDevice*>(hwdevice);
700  return sdevice->mountPath();
701  }
702  }
703 
704  return TQString::null;
705 }
706 
707 TQStringVariantMap TDEStorageDevice::mountDevice(TQString mediaName, TDEStorageMountOptions mountOptions) {
708  TQStringVariantMap result;
709 
710  // Check if device is already mounted
711  TQString mountpath = mountPath();
712  if (!mountpath.isEmpty()) {
713  result["mountPath"] = mountpath;
714  result["result"] = true;
715  return result;
716  }
717 
718  TQString devNode = deviceNode();
719  devNode.replace("'", "'\\''");
720  mediaName.replace("'", "'\\''");
721 
722  // Prepare filesystem options for mount
723  TQStringList udisksOptions;
724  if (mountOptions["ro"] == "true") {
725  udisksOptions.append("ro");
726  }
727 
728  if (mountOptions["atime"] != "true") {
729  udisksOptions.append("noatime");
730  }
731 
732  if (mountOptions["sync"] == "true") {
733  udisksOptions.append("sync");
734  }
735 
736  if ((mountOptions["filesystem"] == "fat") || (mountOptions["filesystem"] == "vfat") ||
737  (mountOptions["filesystem"] == "msdos") || (mountOptions["filesystem"] == "umsdos")) {
738  if (mountOptions.contains("shortname")) {
739  udisksOptions.append(TQString("shortname=%1").arg(mountOptions["shortname"]));
740  }
741  }
742 
743  if ((mountOptions["filesystem"] == "jfs")) {
744  if (mountOptions["utf8"] == "true") {
745  // udisks/udisks2 for now does not support option iocharset= for jfs
746  // udisksOptions.append("iocharset=utf8");
747  }
748  }
749 
750  if ((mountOptions["filesystem"] == "ntfs-3g")) {
751  if (mountOptions.contains("locale")) {
752  udisksOptions.append(TQString("locale=%1").arg(mountOptions["locale"]));
753  }
754  }
755 
756  if ((mountOptions["filesystem"] == "ext3") || (mountOptions["filesystem"] == "ext4")) {
757  if (mountOptions.contains("journaling")) {
758  // udisks/udisks2 for now does not support option data= for ext3/ext4
759  // udisksOptions.append(TQString("data=%1").arg(mountOptions["journaling"]));
760  }
761  }
762 
763  TQString optionString;
764  for (TQStringList::Iterator it = udisksOptions.begin(); it != udisksOptions.end(); ++it) {
765  optionString.append(",");
766  optionString.append(*it);
767  }
768 
769  if (!optionString.isEmpty()) {
770  optionString.remove(0, 1);
771  }
772 
773  // Try to use UDISKS v2 via DBUS, if available
774  TQString fileSystemType;
775  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
776  fileSystemType = mountOptions["filesystem"];
777  }
778 
779  TQStringVariantMap mountResult = UDisks2MountDrive(devNode, fileSystemType, optionString);
780  if (mountResult["result"].toBool()) {
781  // Update internal mount data
782  TDEGlobal::hardwareDevices()->processModifiedMounts();
783  result["mountPath"] = mountPath();
784  result["result"] = true;
785  return result;
786  }
787  else if (mountResult["retcode"].toInt() == -1) {
788  // Update internal mount data
789  TDEGlobal::hardwareDevices()->processModifiedMounts();
790  result["errStr"] = mountResult["errStr"];
791  result["result"] = false;
792  return result;
793  }
794 
795  // The UDISKS v2 DBUS service was either not available or was unusable
796  // Try to use UDISKS v1 via DBUS, if available
797  mountResult = UDisksMountDrive(devNode, fileSystemType, udisksOptions);
798  if (mountResult["result"].toBool()) {
799  // Update internal mount data
800  TDEGlobal::hardwareDevices()->processModifiedMounts();
801  result["mountPath"] = mountPath();
802  result["result"] = true;
803  return result;
804  }
805  else if (mountResult["retcode"].toInt() == -1) {
806  // Update internal mount data
807  TDEGlobal::hardwareDevices()->processModifiedMounts();
808  result["errStr"] = mountResult["errStr"];
809  result["result"] = false;
810  return result;
811  }
812 
813  // The UDISKS v1 DBUS service was either not available or was unusable
814  // Use 'udevil' command, if available
815  TQString command = TQString::null;
816  if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) {
817  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
818  fileSystemType = TQString("-t %1").arg(mountOptions["filesystem"]);
819  }
820  TQString mountpoint;
821  if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() &&
822  (mountOptions["mountpoint"] != "/media/")) {
823  mountpoint = mountOptions["mountpoint"];
824  mountpoint.replace("'", "'\\''");
825  }
826  else {
827  mountpoint = TQString("/media/%1").arg(mediaName);
828  }
829  command = TQString("udevil mount %1 -o '%2' '%3' '%4' 2>&1")
830  .arg(fileSystemType).arg(optionString).arg(devNode).arg(mountpoint);
831  }
832 
833  // If 'udevil' was not found, use 'pmount' command if available
834  if(command.isEmpty()) {
835  if (!TDEGlobal::dirs()->findExe("pmount").isEmpty()) {
836  // Create dummy password file
837  KTempFile passwordFile(TQString::null, "tmp", 0600);
838  passwordFile.setAutoDelete(true);
839 
840  TQString optionString;
841  if (mountOptions["ro"] == "true") {
842  optionString.append(" -r");
843  }
844 
845  if (mountOptions["atime"] != "true") {
846  optionString.append(" -A");
847  }
848 
849  if (mountOptions["utf8"] == "true") {
850  optionString.append(" -c utf8");
851  }
852 
853  if (mountOptions["sync"] == "true") {
854  optionString.append(" -s");
855  }
856 
857  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
858  optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"]));
859  }
860 
861  if (mountOptions.contains("locale")) {
862  optionString.append(TQString(" -c %1").arg(mountOptions["locale"]));
863  }
864 
865  TQString mountpoint;
866  if (mountOptions.contains("mountpoint") && !mountOptions["mountpoint"].isEmpty() &&
867  (mountOptions["mountpoint"] != "/media/")) {
868  mountpoint = mountOptions["mountpoint"];
869  mountpoint.replace("'", "'\\''");
870  }
871  else {
872  mountpoint = mediaName;
873  }
874 
875  TQString passFileName = passwordFile.name();
876  passFileName.replace("'", "'\\''");
877 
878  command = TQString("pmount -p '%1' %2 '%3' '%4' 2>&1")
879  .arg(passFileName).arg(optionString).arg(devNode).arg(mountpoint);
880  }
881  }
882 
883  if(command.isEmpty()) {
884  result["errStr"] = i18n("No supported mounting methods were detected on your system");
885  result["result"] = false;
886  return result;
887  }
888 
889  FILE *exepipe = popen(command.local8Bit(), "r");
890  if (exepipe) {
891  TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly);
892  TQString mount_output = ts->read();
893  delete ts;
894  int retcode = pclose(exepipe);
895  result["errStr"] = mount_output;
896  result["retCode"] = retcode;
897  }
898 
899  // Update internal mount data
900  TDEGlobal::hardwareDevices()->processModifiedMounts();
901  result["mountPath"] = mountPath();
902  result["result"] = !mountPath().isEmpty();
903  return result;
904 }
905 
906 TQStringVariantMap TDEStorageDevice::mountEncryptedDevice(TQString passphrase, TQString mediaName,
907  TDEStorageMountOptions mountOptions) {
908  TQStringVariantMap result;
909 
910  // Check if device is already mounted
911  TQString mountpath = mountPath();
912  if (!mountpath.isEmpty()) {
913  result["mountPath"] = mountpath;
914  result["result"] = true;
915  return result;
916  }
917 
918  // Create dummy password file
919  KTempFile passwordFile(TQString::null, "tmp", 0600);
920  passwordFile.setAutoDelete(true);
921  TQFile* pwFile = passwordFile.file();
922  if (!pwFile) {
923  result["errStr"] = i18n("Cannot create temporary password file");
924  result["result"] = false;
925  return result;
926  }
927 
928  pwFile->writeBlock(passphrase.ascii(), passphrase.length());
929  pwFile->flush();
930 
931  TQString optionString;
932  if (mountOptions["ro"] == "true") {
933  optionString.append(" -r");
934  }
935 
936  if (mountOptions["atime"] != "true") {
937  optionString.append(" -A");
938  }
939 
940  if (mountOptions["utf8"] == "true") {
941  optionString.append(" -c utf8");
942  }
943 
944  if (mountOptions["sync"] == "true") {
945  optionString.append(" -s");
946  }
947 
948  if (mountOptions.contains("filesystem") && !mountOptions["filesystem"].isEmpty()) {
949  optionString.append(TQString(" -t %1").arg(mountOptions["filesystem"]));
950  }
951 
952  if (mountOptions.contains("locale")) {
953  optionString.append(TQString(" -c %1").arg(mountOptions["locale"]));
954  }
955 
956  TQString passFileName = passwordFile.name();
957  TQString devNode = deviceNode();
958  passFileName.replace("'", "'\\''");
959  devNode.replace("'", "'\\''");
960  mediaName.replace("'", "'\\''");
961  TQString command = TQString("pmount -p '%1' %2 '%3' '%4' 2>&1")
962  .arg(passFileName).arg(optionString).arg(devNode).arg(mediaName);
963 
964  FILE *exepipe = popen(command.local8Bit(), "r");
965  if (exepipe) {
966  TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly);
967  TQString mount_output = ts->read();
968  delete ts;
969  int retcode = pclose(exepipe);
970  result["errStr"] = mount_output;
971  result["retCode"] = retcode;
972  }
973 
974  // Update internal mount data
975  TDEGlobal::hardwareDevices()->processModifiedMounts();
976  result["mountPath"] = mountPath();
977  result["result"] = !mountPath().isEmpty();
978  return result;
979 }
980 
981 TQStringVariantMap TDEStorageDevice::unmountDevice() {
982  TQStringVariantMap result;
983 
984  // Check if device is already unmounted
985  TQString mountpoint = mountPath();
986  if (mountpoint.isEmpty()) {
987  result["result"] = true;
988  return result;
989  }
990 
991  mountpoint.replace("'", "'\\''");
992  TQString devNode = deviceNode();
993 
994  // Try to use UDISKS v2 via DBUS, if available
995  TQStringVariantMap unmountResult = UDisks2UnmountDrive(devNode, TQString::null);
996  if (unmountResult["result"].toBool()) {
997  // Update internal mount data
998  TDEGlobal::hardwareDevices()->processModifiedMounts();
999  result["result"] = true;
1000  return result;
1001  }
1002  else if (unmountResult["retcode"].toInt() == -1) {
1003  // Update internal mount data
1004  TDEGlobal::hardwareDevices()->processModifiedMounts();
1005  result["errStr"] = unmountResult["errStr"];
1006  result["result"] = false;
1007  return result;
1008  }
1009 
1010  // The UDISKS v2 DBUS service was either not available or was unusable
1011  // Try to use UDISKS v1 via DBUS, if available
1012  unmountResult = UDisksUnmountDrive(devNode, TQStringList());
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 
1027  // The UDISKS v1 DBUS service was either not available or was unusable
1028  // Use 'udevil' command, if available
1029  TQString command = TQString::null;
1030  if (!TDEGlobal::dirs()->findExe("udevil").isEmpty()) {
1031  command = TQString("udevil umount '%1' 2>&1").arg(mountpoint);
1032  }
1033 
1034  // If 'udevil' was not found, use 'pmount' command if available
1035  if(command.isEmpty() && !TDEGlobal::dirs()->findExe("pumount").isEmpty()) {
1036  command = TQString("pumount '%1' 2>&1").arg(mountpoint);
1037  }
1038 
1039  if(command.isEmpty()) {
1040  result["errStr"] = i18n("No supported unmounting methods were detected on your system");
1041  result["result"] = false;
1042  return result;
1043  }
1044 
1045  FILE *exepipe = popen(command.local8Bit(), "r");
1046  if (exepipe) {
1047  TQTextStream* ts = new TQTextStream(exepipe, IO_ReadOnly);
1048  TQString umount_output = ts->read();
1049  delete ts;
1050  int retcode = pclose(exepipe);
1051  if (retcode == 0) {
1052  // Update internal mount data
1053  TDEGlobal::hardwareDevices()->processModifiedMounts();
1054  result["result"] = true;
1055  return result;
1056  }
1057  else {
1058  result["errStr"] = umount_output;
1059  result["retCode"] = retcode;
1060  }
1061  }
1062 
1063  // Update internal mount data
1064  TDEGlobal::hardwareDevices()->processModifiedMounts();
1065  result["result"] = false;
1066  return result;
1067 }
1068 
1069 TQString TDEStorageDevice::determineFileSystemType(TQString path) {
1070  TQStringList mountTable;
1071  TQString prevPath = path;
1072  dev_t prevDev = 0;
1073  int pos;
1074  struct stat directory_info;
1075  if (path.startsWith("/")) {
1076  stat(path.local8Bit(), &directory_info);
1077  prevDev = directory_info.st_dev;
1078  // Walk the directory tree up to the root, checking for any change in st_dev
1079  // If a change is found, the previous value of path is the mount point itself
1080  while (path != "/") {
1081  pos = path.findRev("/", -1, true);
1082  if (pos < 0) {
1083  break;
1084  }
1085  path = path.mid(0, pos);
1086  if (path == "") {
1087  path = "/";
1088  }
1089  stat(path.local8Bit(), &directory_info);
1090  if (directory_info.st_dev != prevDev) {
1091  break;
1092  }
1093  prevPath = path;
1094  prevDev = directory_info.st_dev;
1095  }
1096  }
1097 
1098  // Read in mount table
1099  mountTable.clear();
1100  TQFile file( "/proc/mounts" );
1101  if ( file.open( IO_ReadOnly ) ) {
1102  TQTextStream stream( &file );
1103  while ( !stream.atEnd() ) {
1104  mountTable.append(stream.readLine());
1105  }
1106  file.close();
1107  }
1108 
1109  // Parse mount table
1110  TQStringList::Iterator it;
1111  for ( it = mountTable.begin(); it != mountTable.end(); ++it ) {
1112  TQStringList mountInfo = TQStringList::split(" ", (*it), true);
1113  if ((*mountInfo.at(1)) == prevPath) {
1114  return (*mountInfo.at(2));
1115  }
1116  }
1117 
1118  // Unknown file system type
1119  return TQString::null;
1120 }
1121 
1122 #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.