void UserInterface::DismountVolume (shared_ptr <VolumeInfo> volume, bool ignoreOpenFiles, bool interactive) const { VolumeInfoList volumes; volumes.push_back (volume); DismountVolumes (volumes, ignoreOpenFiles, interactive); }
void UserInterface::DisplayVolumeProperties (const VolumeInfoList &volumes) const { if (volumes.size() < 1) throw_err (LangString["NO_VOLUMES_MOUNTED"]); wxString prop; foreach_ref (const VolumeInfo &volume, volumes) { prop << _("Slot") << L": " << StringConverter::FromNumber (volume.SlotNumber) << L'\n'; prop << LangString["VOLUME"] << L": " << wstring (volume.Path) << L'\n'; #ifndef TC_WINDOWS prop << LangString["VIRTUAL_DEVICE"] << L": " << wstring (volume.VirtualDevice) << L'\n'; #endif prop << LangString["MOUNT_POINT"] << L": " << wstring (volume.MountPoint) << L'\n'; prop << LangString["SIZE"] << L": " << SizeToString (volume.Size) << L'\n'; prop << LangString["TYPE"] << L": " << VolumeTypeToString (volume.Type, volume.Protection) << L'\n'; prop << LangString["READ_ONLY"] << L": " << LangString [volume.Protection == VolumeProtection::ReadOnly ? "UISTR_YES" : "UISTR_NO"] << L'\n'; wxString protection; if (volume.Type == VolumeType::Hidden) protection = LangString["NOT_APPLICABLE_OR_NOT_AVAILABLE"]; else if (volume.HiddenVolumeProtectionTriggered) protection = LangString["HID_VOL_DAMAGE_PREVENTED"]; else protection = LangString [volume.Protection == VolumeProtection::HiddenVolumeReadOnly ? "UISTR_YES" : "UISTR_NO"]; prop << LangString["HIDDEN_VOL_PROTECTION"] << L": " << protection << L'\n'; prop << LangString["ENCRYPTION_ALGORITHM"] << L": " << volume.EncryptionAlgorithmName << L'\n'; prop << LangString["KEY_SIZE"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n'; if (volume.EncryptionModeName == L"XTS") prop << LangString["SECONDARY_KEY_SIZE_XTS"] << L": " << StringFormatter (L"{0} {1}", volume.EncryptionAlgorithmKeySize * 8, LangString ["BITS"]) << L'\n';; wstringstream blockSize; blockSize << volume.EncryptionAlgorithmBlockSize * 8; if (volume.EncryptionAlgorithmBlockSize != volume.EncryptionAlgorithmMinBlockSize) blockSize << L"/" << volume.EncryptionAlgorithmMinBlockSize * 8; prop << LangString["BLOCK_SIZE"] << L": " << blockSize.str() + L" " + LangString ["BITS"] << L'\n'; prop << LangString["MODE_OF_OPERATION"] << L": " << volume.EncryptionModeName << L'\n'; prop << LangString["PKCS5_PRF"] << L": " << volume.Pkcs5PrfName << L'\n'; prop << LangString["VOLUME_FORMAT_VERSION"] << L": " << (volume.MinRequiredProgramVersion < 0x600 ? 1 : 2) << L'\n'; prop << LangString["BACKUP_HEADER"] << L": " << LangString[volume.MinRequiredProgramVersion >= 0x600 ? "UISTR_YES" : "UISTR_NO"] << L'\n'; #ifdef TC_LINUX if (string (volume.VirtualDevice).find ("/dev/mapper/truecrypt") != 0) { #endif prop << LangString["TOTAL_DATA_READ"] << L": " << SizeToString (volume.TotalDataRead) << L'\n'; prop << LangString["TOTAL_DATA_WRITTEN"] << L": " << SizeToString (volume.TotalDataWritten) << L'\n'; #ifdef TC_LINUX } #endif prop << L'\n'; }
void UserInterface::DismountAllVolumes (bool ignoreOpenFiles, bool interactive) const { try { VolumeInfoList mountedVolumes = Core->GetMountedVolumes(); if (mountedVolumes.size() < 1) ShowInfo (LangString["NO_VOLUMES_MOUNTED"]); BusyScope busy (this); DismountVolumes (mountedVolumes, ignoreOpenFiles, interactive); } catch (exception &e) { ShowError (e); } }
VolumeInfoList CoreUnix::GetMountedVolumes (const VolumePath &volumePath) const { VolumeInfoList volumes; foreach_ref (const MountedFilesystem &mf, GetMountedFilesystems ()) { if (string (mf.MountPoint).find (GetFuseMountDirPrefix()) == string::npos) continue; shared_ptr <VolumeInfo> mountedVol; try { shared_ptr <File> controlFile (new File); controlFile->Open (string (mf.MountPoint) + FuseService::GetControlPath()); shared_ptr <Stream> controlFileStream (new FileStream (controlFile)); mountedVol = Serializable::DeserializeNew <VolumeInfo> (controlFileStream); } catch (...) { continue; } if (!volumePath.IsEmpty() && wstring (mountedVol->Path).compare (volumePath) != 0) continue; mountedVol->AuxMountPoint = mf.MountPoint; if (!mountedVol->VirtualDevice.IsEmpty()) { MountedFilesystemList mpl = GetMountedFilesystems (mountedVol->VirtualDevice); if (mpl.size() > 0) mountedVol->MountPoint = mpl.front()->MountPoint; } volumes.push_back (mountedVol); if (!volumePath.IsEmpty()) break; } return volumes; }
shared_ptr <VolumeInfo> CoreUnix::DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) { if (!mountedVolume->MountPoint.IsEmpty()) { DismountFilesystem (mountedVolume->MountPoint, ignoreOpenFiles); // Delete mount directory if a default path has been used if (string (mountedVolume->MountPoint).find (GetDefaultMountPointPrefix()) == 0) mountedVolume->MountPoint.Delete(); } try { DismountNativeVolume (mountedVolume); } catch (NotApplicable &) { } if (!mountedVolume->LoopDevice.IsEmpty()) { try { DetachLoopDevice (mountedVolume->LoopDevice); } catch (ExecutedProcessFailed&) { } } if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly) { sync(); VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path); if (ml.size() > 0) mountedVolume = ml.front(); } list <string> args; args.push_back ("--"); args.push_back (mountedVolume->AuxMountPoint); for (int t = 0; true; t++) { try { Process::Execute ("umount", args); break; } catch (ExecutedProcessFailed&) { if (t > 10) throw; Thread::Sleep (200); } } try { mountedVolume->AuxMountPoint.Delete(); } catch (...) { } VolumeEventArgs eventArgs (mountedVolume); VolumeDismountedEvent.Raise (eventArgs); return mountedVolume; }
shared_ptr <VolumeInfo> CoreUnix::MountVolume (MountOptions &options) { CoalesceSlotNumberAndMountPoint (options); if (IsVolumeMounted (*options.Path)) throw VolumeAlreadyMounted (SRC_POS); Cipher::EnableHwSupport (!options.NoHardwareCrypto); shared_ptr <Volume> volume; while (true) { try { volume = OpenVolume ( options.Path, options.PreserveTimestamps, options.Password, options.Keyfiles, options.Protection, options.ProtectionPassword, options.ProtectionKeyfiles, options.SharedAccessAllowed, VolumeType::Unknown, options.UseBackupHeaders, options.PartitionInSystemEncryptionScope ); options.Password.reset(); } catch (SystemException &e) { if (options.Protection != VolumeProtection::ReadOnly && (e.GetErrorCode() == EROFS || e.GetErrorCode() == EACCES || e.GetErrorCode() == EPERM)) { // Read-only filesystem options.Protection = VolumeProtection::ReadOnly; continue; } throw; } break; } if (options.Path->IsDevice()) { if (volume->GetFile()->GetDeviceSectorSize() != volume->GetSectorSize()) throw ParameterIncorrect (SRC_POS); #if defined (TC_LINUX) if (volume->GetSectorSize() != TC_SECTOR_SIZE_LEGACY) { if (options.Protection == VolumeProtection::HiddenVolumeReadOnly) throw UnsupportedSectorSizeHiddenVolumeProtection(); if (options.NoKernelCrypto) throw UnsupportedSectorSizeNoKernelCrypto(); } #endif } // Find a free mount point for FUSE service MountedFilesystemList mountedFilesystems = GetMountedFilesystems (); string fuseMountPoint; for (int i = 1; true; i++) { stringstream path; path << GetTempDirectory() << "/" << GetFuseMountDirPrefix() << i; FilesystemPath fsPath (path.str()); bool inUse = false; foreach_ref (const MountedFilesystem &mf, mountedFilesystems) { if (mf.MountPoint == path.str()) { inUse = true; break; } } if (!inUse) { try { if (fsPath.IsDirectory()) fsPath.Delete(); throw_sys_sub_if (mkdir (path.str().c_str(), S_IRUSR | S_IXUSR) == -1, path.str()); fuseMountPoint = fsPath; break; } catch (...) { if (i > 255) throw TemporaryDirectoryFailure (SRC_POS, StringConverter::ToWide (path.str())); } } } try { FuseService::Mount (volume, options.SlotNumber, fuseMountPoint); } catch (...) { try { DirectoryPath (fuseMountPoint).Delete(); } catch (...) { } throw; } try { // Create a mount directory if a default path has been specified bool mountDirCreated = false; string mountPoint; if (!options.NoFilesystem && options.MountPoint) { mountPoint = *options.MountPoint; #ifndef TC_MACOSX if (mountPoint.find (GetDefaultMountPointPrefix()) == 0 && !options.MountPoint->IsDirectory()) { Directory::Create (*options.MountPoint); try { throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint); } catch (ParameterIncorrect&) { } mountDirCreated = true; } #endif } try { try { MountVolumeNative (volume, options, fuseMountPoint); } catch (NotApplicable&) { MountAuxVolumeImage (fuseMountPoint, options); } } catch (...) { if (mountDirCreated) remove (mountPoint.c_str()); throw; } } catch (...) { try { VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); if (mountedVolumes.size() > 0) { shared_ptr <VolumeInfo> mountedVolume (mountedVolumes.front()); DismountVolume (mountedVolume); } } catch (...) { } throw; } VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path); if (mountedVolumes.size() != 1) throw ParameterIncorrect (SRC_POS); VolumeEventArgs eventArgs (mountedVolumes.front()); VolumeMountedEvent.Raise (eventArgs); return mountedVolumes.front(); }
void UserInterface::DismountVolumes (VolumeInfoList volumes, bool ignoreOpenFiles, bool interactive) const { BusyScope busy (this); volumes.sort (VolumeInfo::FirstVolumeMountedAfterSecond); wxString message; bool twoPassMode = volumes.size() > 1; bool volumesInUse = false; bool firstPass = true; #ifdef TC_WINDOWS if (Preferences.CloseExplorerWindowsOnDismount) { foreach (shared_ptr <VolumeInfo> volume, volumes) CloseExplorerWindows (volume); } #endif while (!volumes.empty()) { VolumeInfoList volumesLeft; foreach (shared_ptr <VolumeInfo> volume, volumes) { try { BusyScope busy (this); volume = Core->DismountVolume (volume, ignoreOpenFiles); } catch (MountedVolumeInUse&) { if (!firstPass) throw; if (twoPassMode || !interactive) { volumesInUse = true; volumesLeft.push_back (volume); continue; } else { if (AskYesNo (StringFormatter (LangString["UNMOUNT_LOCK_FAILED"], wstring (volume->Path)), true, true)) { BusyScope busy (this); volume = Core->DismountVolume (volume, true); } else throw UserAbort (SRC_POS); } } catch (...) { if (twoPassMode && firstPass) volumesLeft.push_back (volume); else throw; } if (volume->HiddenVolumeProtectionTriggered) ShowWarning (StringFormatter (LangString["DAMAGE_TO_HIDDEN_VOLUME_PREVENTED"], wstring (volume->Path))); if (Preferences.Verbose) { if (!message.IsEmpty()) message += L'\n'; message += StringFormatter (_("Volume \"{0}\" has been dismounted."), wstring (volume->Path)); } } if (twoPassMode && firstPass) { volumes = volumesLeft; if (volumesInUse && interactive) { if (AskYesNo (LangString["UNMOUNTALL_LOCK_FAILED"], true, true)) ignoreOpenFiles = true; else throw UserAbort (SRC_POS); } } else break; firstPass = false; } if (Preferences.Verbose && !message.IsEmpty()) ShowInfo (message); }
shared_ptr <VolumeInfo> CoreMacOSX::DismountVolume (shared_ptr <VolumeInfo> mountedVolume, bool ignoreOpenFiles, bool syncVolumeInfo) { if (!mountedVolume->VirtualDevice.IsEmpty() && mountedVolume->VirtualDevice.IsBlockDevice()) { list <string> args; args.push_back ("detach"); args.push_back (mountedVolume->VirtualDevice); if (ignoreOpenFiles) args.push_back ("-force"); try { Process::Execute ("hdiutil", args); } catch (ExecutedProcessFailed &e) { if (!ignoreOpenFiles) { string err = e.GetErrorOutput(); if (err.find ("couldn't unmount") != string::npos || err.find ("busy") != string::npos || err.find ("49153") != string::npos) { throw MountedVolumeInUse (SRC_POS); } } throw; } } if (syncVolumeInfo || mountedVolume->Protection == VolumeProtection::HiddenVolumeReadOnly) { sync(); VolumeInfoList ml = GetMountedVolumes (mountedVolume->Path); if (ml.size() > 0) mountedVolume = ml.front(); } list <string> args; args.push_back ("--"); args.push_back (mountedVolume->AuxMountPoint); for (int t = 0; true; t++) { try { Process::Execute ("umount", args); break; } catch (ExecutedProcessFailed&) { if (t > 10) throw; Thread::Sleep (200); } } try { mountedVolume->AuxMountPoint.Delete(); } catch (...) { } return mountedVolume; }