From 5e547b127f25b0d4f526fdb4126b95c4ba03c4b2 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Tue, 21 Sep 2021 01:36:47 +0200 Subject: Linux/macOS: Add CLI switch (--size=max) and UI option to give a file container all available free space. This commit also makes --size switch accept KiB/MiB/GiB/TiB prefixes and adds TiB choice in UI. --- src/Common/Language.xml | 1 + src/Main/CommandLineInterface.cpp | 67 +++++++++++---------- src/Main/Forms/Forms.cpp | 8 +++ src/Main/Forms/Forms.h | 2 + src/Main/Forms/TrueCrypt.fbp | 98 ++++++++++++++++++++++++++++++ src/Main/Forms/VolumeSizeWizardPage.cpp | 58 ++++++++++++++---- src/Main/Forms/VolumeSizeWizardPage.h | 4 +- src/Main/TextUserInterface.cpp | 102 ++++++++++++++++++++++---------- src/Main/UserInterface.cpp | 3 +- 9 files changed, 269 insertions(+), 74 deletions(-) (limited to 'src') diff --git a/src/Common/Language.xml b/src/Common/Language.xml index e2a0fc46..6c0c64da 100644 --- a/src/Common/Language.xml +++ b/src/Common/Language.xml @@ -1566,6 +1566,7 @@ Volume Location WARNING: The host file/device {0} is already in use!\n\nIgnoring this can cause undesired results including system instability. All applications that might be using the host file/device should be closed before mounting the volume.\n\nContinue mounting? VeraCrypt was previously installed using an MSI package and so it can't be updated using the standard installer.\n\nPlease use the MSI package to update your VeraCrypt installation. + Use all available free space diff --git a/src/Main/CommandLineInterface.cpp b/src/Main/CommandLineInterface.cpp index 0ae246c6..0be53bd6 100644 --- a/src/Main/CommandLineInterface.cpp +++ b/src/Main/CommandLineInterface.cpp @@ -574,40 +574,45 @@ namespace VeraCrypt if (parser.Found (L"size", &str)) { - uint64 multiplier; - wxChar lastChar = str [str.Length () - 1]; - if (lastChar >= wxT('0') && lastChar <= wxT('9')) - multiplier = 1; - else if (lastChar == wxT('K') || lastChar == wxT('k')) - multiplier = BYTES_PER_KB; - else if (lastChar == wxT('M') || lastChar == wxT('m')) - multiplier = BYTES_PER_MB; - else if (lastChar == wxT('G') || lastChar == wxT('g')) - multiplier = BYTES_PER_GB; - else if (lastChar == wxT('T') || lastChar == wxT('t')) - multiplier = BYTES_PER_TB; - else - throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); - - // remove suffix if present - if (multiplier != 1) - str.RemoveLast (); - // check that we only have digits in the string - size_t index = str.find_first_not_of (wxT("0123456789")); - if (index != (size_t) wxNOT_FOUND) + if (str.CmpNoCase (wxT("max")) == 0) { - // restore last characater for error display - if (multiplier != 1) - str += lastChar; - throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); + ArgSize = (uint64) -1; // indicator of maximum available size } - try - { - ArgSize = multiplier * StringConverter::ToUInt64 (wstring (str)); - } - catch (...) + else { - throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); + uint64 multiplier; + wxString originalStr = str; + size_t index = str.find_first_not_of (wxT("0123456789")); + if (index == 0) + { + throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); + } + else if (index != (size_t) wxNOT_FOUND) + { + wxString sizeSuffix = str.Mid(index); + if (sizeSuffix.CmpNoCase(wxT("K")) == 0 || sizeSuffix.CmpNoCase(wxT("KiB")) == 0) + multiplier = BYTES_PER_KB; + else if (sizeSuffix.CmpNoCase(wxT("M")) == 0 || sizeSuffix.CmpNoCase(wxT("MiB")) == 0) + multiplier = BYTES_PER_MB; + else if (sizeSuffix.CmpNoCase(wxT("G")) == 0 || sizeSuffix.CmpNoCase(wxT("GiB")) == 0) + multiplier = BYTES_PER_GB; + else if (sizeSuffix.CmpNoCase(wxT("T")) == 0 || sizeSuffix.CmpNoCase(wxT("TiB")) == 0) + multiplier = BYTES_PER_TB; + else + throw_err (LangString["PARAMETER_INCORRECT"] + L": " + str); + + str = str.Left (index); + } + else + multiplier = 1; + try + { + ArgSize = multiplier * StringConverter::ToUInt64 (wstring (str)); + } + catch (...) + { + throw_err (LangString["PARAMETER_INCORRECT"] + L": " + originalStr); + } } } diff --git a/src/Main/Forms/Forms.cpp b/src/Main/Forms/Forms.cpp index 0af3e2a6..d281febc 100644 --- a/src/Main/Forms/Forms.cpp +++ b/src/Main/Forms/Forms.cpp @@ -3625,6 +3625,12 @@ VolumeSizeWizardPageBase::VolumeSizeWizardPageBase( wxWindow* parent, wxWindowID bSizer99->Add( 0, 0, 0, wxEXPAND|wxTOP|wxBOTTOM, 5 ); + UseAllFreeSpaceCheckBox = new wxCheckBox( this, wxID_ANY, _("IDC_USE_ALL_FREE_SPACE"), wxDefaultPosition, wxDefaultSize, 0 ); + bSizer99->Add( UseAllFreeSpaceCheckBox, 0, wxALL|wxEXPAND, 5 ); + + + bSizer99->Add( 0, 0, 0, wxBOTTOM|wxEXPAND|wxTOP, 5 ); + FreeSpaceStaticText = new wxStaticText( this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 ); FreeSpaceStaticText->Wrap( -1 ); @@ -3649,6 +3655,7 @@ VolumeSizeWizardPageBase::VolumeSizeWizardPageBase( wxWindow* parent, wxWindowID // Connect Events VolumeSizeTextCtrl->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizeTextChanged ), NULL, this ); VolumeSizePrefixChoice->Connect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizePrefixSelected ), NULL, this ); + UseAllFreeSpaceCheckBox->Connect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnUseAllFreeSpaceCheckBoxClick ), NULL, this ); } VolumeSizeWizardPageBase::~VolumeSizeWizardPageBase() @@ -3656,6 +3663,7 @@ VolumeSizeWizardPageBase::~VolumeSizeWizardPageBase() // Disconnect Events VolumeSizeTextCtrl->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizeTextChanged ), NULL, this ); VolumeSizePrefixChoice->Disconnect( wxEVT_COMMAND_CHOICE_SELECTED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnVolumeSizePrefixSelected ), NULL, this ); + UseAllFreeSpaceCheckBox->Disconnect( wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler( VolumeSizeWizardPageBase::OnUseAllFreeSpaceCheckBoxClick ), NULL, this ); } diff --git a/src/Main/Forms/Forms.h b/src/Main/Forms/Forms.h index 3ea89763..b1756876 100644 --- a/src/Main/Forms/Forms.h +++ b/src/Main/Forms/Forms.h @@ -1063,12 +1063,14 @@ namespace VeraCrypt protected: wxTextCtrl* VolumeSizeTextCtrl; wxChoice* VolumeSizePrefixChoice; + wxCheckBox* UseAllFreeSpaceCheckBox; wxStaticText* FreeSpaceStaticText; wxStaticText* InfoStaticText; // Virtual event handlers, overide them in your derived class virtual void OnVolumeSizeTextChanged( wxCommandEvent& event ) { event.Skip(); } virtual void OnVolumeSizePrefixSelected( wxCommandEvent& event ) { event.Skip(); } + virtual void OnUseAllFreeSpaceCheckBoxClick( wxCommandEvent& event ) { event.Skip(); } public: diff --git a/src/Main/Forms/TrueCrypt.fbp b/src/Main/Forms/TrueCrypt.fbp index 927a60b9..24689fcf 100644 --- a/src/Main/Forms/TrueCrypt.fbp +++ b/src/Main/Forms/TrueCrypt.fbp @@ -29550,6 +29550,104 @@ + 5 + wxALL|wxEXPAND + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + IDC_USE_ALL_FREE_SPACE + + 0 + + + 0 + + 1 + UseAllFreeSpaceCheckBox + 1 + + + protected + 1 + + Resizable + 1 + + + ; forward_declare + 0 + + + wxFILTER_NONE + wxDefaultValidator + + + + + + OnUseAllFreeSpaceCheckBoxClick + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxBOTTOM|wxEXPAND|wxTOP + 0 + + 0 + protected + 0 + + + 5 wxALL|wxEXPAND 0 diff --git a/src/Main/Forms/VolumeSizeWizardPage.cpp b/src/Main/Forms/VolumeSizeWizardPage.cpp index 47d73983..61427ea5 100644 --- a/src/Main/Forms/VolumeSizeWizardPage.cpp +++ b/src/Main/Forms/VolumeSizeWizardPage.cpp @@ -24,9 +24,10 @@ namespace VeraCrypt SectorSize (sectorSize), AvailableDiskSpace (0) { - VolumeSizePrefixChoice->Append (LangString["KB"], reinterpret_cast (1024)); - VolumeSizePrefixChoice->Append (LangString["MB"], reinterpret_cast (1024 * 1024)); - VolumeSizePrefixChoice->Append (LangString["GB"], reinterpret_cast (1024 * 1024 * 1024)); + VolumeSizePrefixChoice->Append (LangString["KB"], reinterpret_cast (1)); + VolumeSizePrefixChoice->Append (LangString["MB"], reinterpret_cast (2)); + VolumeSizePrefixChoice->Append (LangString["GB"], reinterpret_cast (3)); + VolumeSizePrefixChoice->Append (LangString["TB"], reinterpret_cast (4)); VolumeSizePrefixChoice->Select (Prefix::MB); wxLongLong diskSpace = 0; @@ -34,6 +35,7 @@ namespace VeraCrypt { VolumeSizeTextCtrl->Disable(); VolumeSizeTextCtrl->SetValue (L""); + UseAllFreeSpaceCheckBox->Disable(); } else { @@ -74,13 +76,25 @@ namespace VeraCrypt uint64 VolumeSizeWizardPage::GetVolumeSize () const { uint64 prefixMult = 1; - int selection = VolumeSizePrefixChoice->GetSelection(); - if (selection == wxNOT_FOUND) - return 0; - - prefixMult = reinterpret_cast (VolumeSizePrefixChoice->GetClientData (selection)); + uint64 val; + if (UseAllFreeSpaceCheckBox->IsChecked ()) + { + val = AvailableDiskSpace; + } + else + { + int selection = VolumeSizePrefixChoice->GetSelection(); + if (selection == wxNOT_FOUND) + return 0; - uint64 val = StringConverter::ToUInt64 (wstring (VolumeSizeTextCtrl->GetValue())); + uint64 counter = reinterpret_cast (VolumeSizePrefixChoice->GetClientData (selection)); + while (counter) + { + prefixMult *= 1024; + counter--; + } + val = StringConverter::ToUInt64 (wstring(VolumeSizeTextCtrl->GetValue())); + } if (val <= 0x7fffFFFFffffFFFFull / prefixMult) { val *= prefixMult; @@ -98,7 +112,7 @@ namespace VeraCrypt bool VolumeSizeWizardPage::IsValid () { - if (!VolumeSizeTextCtrl->GetValue().empty() && Validate()) + if ((!VolumeSizeTextCtrl->GetValue().empty() || UseAllFreeSpaceCheckBox->IsChecked ()) && Validate()) { try { @@ -126,7 +140,12 @@ namespace VeraCrypt return; } - if (size % (1024 * 1024 * 1024) == 0) + if (size % (1024ULL * 1024ULL * 1024ULL * 1024ULL) == 0) + { + size /= 1024ULL * 1024ULL * 1024ULL * 1024ULL; + VolumeSizePrefixChoice->Select (Prefix::TB); + } + else if (size % (1024 * 1024 * 1024) == 0) { size /= 1024 * 1024 * 1024; VolumeSizePrefixChoice->Select (Prefix::GB); @@ -144,4 +163,21 @@ namespace VeraCrypt VolumeSizeTextCtrl->SetValue (StringConverter::FromNumber (size)); } + + void VolumeSizeWizardPage::OnUseAllFreeSpaceCheckBoxClick( wxCommandEvent& event ) + { + if (UseAllFreeSpaceCheckBox->IsChecked ()) + { + VolumeSizePrefixChoice->Select (Prefix::MB); + VolumeSizeTextCtrl->SetValue (L""); + VolumeSizePrefixChoice->Disable(); + VolumeSizeTextCtrl->Disable(); + } + else + { + VolumeSizePrefixChoice->Enable(); + VolumeSizeTextCtrl->SetValue (L""); + VolumeSizeTextCtrl->Enable(); + } + } } diff --git a/src/Main/Forms/VolumeSizeWizardPage.h b/src/Main/Forms/VolumeSizeWizardPage.h index aac41f99..754bd691 100644 --- a/src/Main/Forms/VolumeSizeWizardPage.h +++ b/src/Main/Forms/VolumeSizeWizardPage.h @@ -37,13 +37,15 @@ namespace VeraCrypt { KB = 0, MB, - GB + GB, + TB }; }; void OnBrowseButtonClick (wxCommandEvent& event); void OnVolumeSizePrefixSelected (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } void OnVolumeSizeTextChanged (wxCommandEvent& event) { PageUpdatedEvent.Raise(); } + void OnUseAllFreeSpaceCheckBoxClick( wxCommandEvent& event ); uint64 MaxVolumeSize; bool MaxVolumeSizeValid; diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index 2cacbb1b..7233b8b6 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -646,6 +646,29 @@ namespace VeraCrypt } else { + uint64 AvailableDiskSpace = 0; + wxLongLong diskSpace = 0; + if (wxGetDiskSpace (wxFileName (wstring (options->Path)).GetPath(), nullptr, &diskSpace)) + { + AvailableDiskSpace = (uint64) diskSpace.GetValue (); + if (maxVolumeSize > AvailableDiskSpace) + maxVolumeSize = AvailableDiskSpace; + } + + if (options->Size == (uint64) (-1)) + { + if (AvailableDiskSpace) + { + // caller requesting maximum size + // we use maxVolumeSize because it is guaranteed to be less of equal to AvailableDiskSpace + options->Size = maxVolumeSize; + } + else + { + throw_err (_("Failed to get available disk space on the selected target.")); + } + } + options->Quick = false; uint32 sectorSizeRem = options->Size % options->SectorSize; @@ -657,43 +680,62 @@ namespace VeraCrypt if (Preferences.NonInteractive) throw MissingArgument (SRC_POS); - wstring sizeStr = AskString (options->Type == VolumeType::Hidden ? _("\nEnter hidden volume size (sizeK/size[M]/sizeG): ") : _("\nEnter volume size (sizeK/size[M]/sizeG): ")); uint64 multiplier = 1024 * 1024; - - if (sizeStr.find (L"K") != string::npos) - { - multiplier = 1024; - sizeStr.resize (sizeStr.size() - 1); - } - else if (sizeStr.find (L"M") != string::npos) + wxString sizeStr = AskString (options->Type == VolumeType::Hidden ? _("\nEnter hidden volume size (sizeK/size[M]/sizeG/sizeT/max): ") : _("\nEnter volume size (sizeK/size[M]/sizeG.sizeT/max): ")); + if (sizeStr.CmpNoCase(wxT("max")) == 0) { - sizeStr.resize (sizeStr.size() - 1); - } - else if (sizeStr.find (L"G") != string::npos) - { - multiplier = 1024 * 1024 * 1024; - sizeStr.resize (sizeStr.size() - 1); + multiplier = 1; + if (AvailableDiskSpace) + { + // caller requesting maximum size + // we use maxVolumeSize because it is guaranteed to be less of equal to AvailableDiskSpace + options->Size = maxVolumeSize; + } + else + { + throw_err (_("Failed to get available disk space on the selected target.")); + } } - else if (sizeStr.find (L"T") != string::npos) + else { - multiplier = (uint64) 1024 * 1024 * 1024 * 1024; - sizeStr.resize (sizeStr.size() - 1); - } + multiplier = 1024 * 1024; + size_t index = sizeStr.find_first_not_of (wxT("0123456789")); + if (index == 0) + { + continue; + } + else if (index != (size_t) wxNOT_FOUND) + { + wxString sizeSuffix = sizeStr.Mid(index); + if (sizeSuffix.CmpNoCase(wxT("K")) == 0 || sizeSuffix.CmpNoCase(wxT("KiB")) == 0) + multiplier = BYTES_PER_KB; + else if (sizeSuffix.CmpNoCase(wxT("M")) == 0 || sizeSuffix.CmpNoCase(wxT("MiB")) == 0) + multiplier = BYTES_PER_MB; + else if (sizeSuffix.CmpNoCase(wxT("G")) == 0 || sizeSuffix.CmpNoCase(wxT("GiB")) == 0) + multiplier = BYTES_PER_GB; + else if (sizeSuffix.CmpNoCase(wxT("T")) == 0 || sizeSuffix.CmpNoCase(wxT("TiB")) == 0) + multiplier = BYTES_PER_TB; + else + continue; - try - { - options->Size = StringConverter::ToUInt64 (sizeStr); - options->Size *= multiplier; + sizeStr = sizeStr.Left (index); + } - sectorSizeRem = options->Size % options->SectorSize; - if (sectorSizeRem != 0) - options->Size += options->SectorSize - sectorSizeRem; - } - catch (...) - { - options->Size = 0; - continue; + try + { + options->Size = StringConverter::ToUInt64 (wstring(sizeStr)); + } + catch (...) + { + options->Size = 0; + continue; + } } + options->Size *= multiplier; + + sectorSizeRem = options->Size % options->SectorSize; + if (sectorSizeRem != 0) + options->Size += options->SectorSize - sectorSizeRem; if (options->Size < minVolumeSize) { diff --git a/src/Main/UserInterface.cpp b/src/Main/UserInterface.cpp index b4bfe836..d0e2f9a1 100644 --- a/src/Main/UserInterface.cpp +++ b/src/Main/UserInterface.cpp @@ -1270,10 +1270,11 @@ namespace VeraCrypt "--slot=SLOT\n" " Use specified slot number when mounting, dismounting, or listing a volume.\n" "\n" - "--size=SIZE[K|M|G|T]\n" + "--size=SIZE[K|KiB|M|MiB|G|GiB|T|TiB] or --size=max\n" " Use specified size when creating a new volume. If no suffix is indicated,\n" " then SIZE is interpreted in bytes. Suffixes K, M, G or T can be used to\n" " indicate a value in KiB, MiB, GiB or TiB respectively.\n" + " If max is specified, the new volume will use all available free disk space.\n" "\n" "-t, --text\n" " Use text user interface. Graphical user interface is used by default if\n" -- cgit v1.2.3