1
0
mirror of https://github.com/veracrypt/VeraCrypt.git synced 2026-05-21 21:30:48 -05:00

Linux/macOS: show volume creation finalization stages

Report explicit progress stages while writing volume data, writing backup headers, and flushing data to disk so the wizard does not appear stuck at 100%.

Keep the wizard in progress during Unix post-creation formatting and show status for temporary mount/device setup, mkfs invocation, and dismount.
This commit is contained in:
Mounir IDRASSI
2026-05-03 00:03:04 +09:00
parent 8b80e2fc61
commit f8837090b8
49 changed files with 574 additions and 12 deletions
+10
View File
@@ -1672,6 +1672,16 @@
<entry lang="en" key="LINUX_PREF_MOUNT_NTFS_WITH_NTFS3_HELP">Linux only. When enabled, VeraCrypt probes the decrypted virtual device with blkid -p and mounts detected NTFS filesystems with ntfs3 instead of the default NTFS backend. If NTFS detection fails, VeraCrypt uses the normal automatic filesystem selection. If ntfs3 is unavailable or blocked by the distribution, mounting may fail. This opt-in option can avoid suspend or hibernate hangs caused by frozen user-space FUSE filesystems.</entry>
<entry lang="en" key="LINUX_EMERGENCY_UNMOUNT_WARNING">Normal unmount of volume {0} failed. This can happen when applications still have files or directories open on the volume, or when the backing device was disconnected and the mount became stale.\n\nIf the device is still connected, choose No, close applications using the volume, and try unmounting again.\n\nIf the device was disconnected or the mount is stale, VeraCrypt can attempt emergency cleanup by lazy-detaching the filesystem and removing or scheduling removal of VeraCrypt kernel objects. Pending writes may have failed, data may be lost, and cleanup may remain pending until applications close open files. Check the filesystem with fsck or the appropriate repair tool before using it again.\n\nContinue?</entry>
<entry lang="en" key="LINUX_EMERGENCY_UNMOUNTED">Emergency cleanup for volume {0} has been initiated. If the volume was disconnected, the mount was stale, or there were pending writes, check the filesystem with fsck or the appropriate repair tool before using it again.</entry>
<entry lang="en" key="FORMAT_STAGE_WRITING_DATA">Creating volume data. Please wait.</entry>
<entry lang="en" key="FORMAT_STAGE_WRITING_BACKUP_HEADER">Finalizing volume creation: writing backup header.</entry>
<entry lang="en" key="FORMAT_STAGE_FLUSHING_DATA">Finalizing volume creation: flushing data to disk. This can take several minutes on large volumes or slow/USB storage.</entry>
<entry lang="en" key="FORMAT_STAGE_FINISHED">Finalizing volume creation.</entry>
<entry lang="en" key="FORMAT_STAGE_ABORTED">Volume creation has been aborted.</entry>
<entry lang="en" key="FORMAT_STAGE_ERROR">Volume creation failed.</entry>
<entry lang="en" key="FORMAT_STAGE_PREPARING_TEMP_VOLUME">Finalizing volume creation: mounting temporary volume.</entry>
<entry lang="en" key="FORMAT_STAGE_PREPARING_TEMP_DEVICE">Finalizing volume creation: preparing temporary device.</entry>
<entry lang="en" key="FORMAT_STAGE_CREATING_FILESYSTEM">Finalizing volume creation: creating filesystem using {0}.</entry>
<entry lang="en" key="FORMAT_STAGE_DISMOUNTING_TEMP_VOLUME">Finalizing volume creation: dismounting temporary volume.</entry>
</localization>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="VeraCrypt">
+20 -1
View File
@@ -29,7 +29,9 @@
namespace VeraCrypt
{
VolumeCreator::VolumeCreator ()
: SizeDone (0)
: SizeDone (0),
Stage (ProgressStage::NotStarted),
mProgressInfo {false, 0, 0, ProgressStage::NotStarted}
{
}
@@ -58,6 +60,7 @@ namespace VeraCrypt
if (filesystemSize < 1)
throw ParameterIncorrect (SRC_POS);
Stage.Set (ProgressStage::WritingData);
DataStart = Layout->GetDataOffset (HostSize);
WriteOffset = DataStart;
endOffset = DataStart + Layout->GetDataSize (HostSize);
@@ -137,6 +140,8 @@ namespace VeraCrypt
{
SizeDone.Set (Options->Size);
Stage.Set (ProgressStage::WritingBackupHeader);
// Backup header
SecureBuffer backupHeader (Layout->GetHeaderSize());
@@ -191,19 +196,26 @@ namespace VeraCrypt
VolumeFile->Write (backupHeader);
}
Stage.Set (ProgressStage::FlushingData);
VolumeFile->Flush();
Stage.Set (ProgressStage::Finished);
}
else
Stage.Set (ProgressStage::Aborted);
}
catch (Exception &e)
{
Stage.Set (ProgressStage::Error);
ThreadException.reset (e.CloneNew());
}
catch (exception &e)
{
Stage.Set (ProgressStage::Error);
ThreadException.reset (new ExternalException (SRC_POS, StringConverter::ToExceptionString (e)));
}
catch (...)
{
Stage.Set (ProgressStage::Error);
ThreadException.reset (new UnknownException (SRC_POS));
}
@@ -214,6 +226,9 @@ namespace VeraCrypt
void VolumeCreator::CreateVolume (shared_ptr <VolumeCreationOptions> options)
{
EncryptionTest::TestAll();
SizeDone.Set (0);
Stage.Set (ProgressStage::NotStarted);
ThreadException.reset();
{
#ifdef TC_UNIX
@@ -379,6 +394,9 @@ namespace VeraCrypt
Options = options;
AbortRequested = false;
mProgressInfo.TotalSize = options->Size;
mProgressInfo.SizeDone = 0;
mProgressInfo.Stage = ProgressStage::NotStarted;
mProgressInfo.CreationInProgress = true;
struct ThreadFunctor : public Functor
@@ -412,6 +430,7 @@ namespace VeraCrypt
VolumeCreator::ProgressInfo VolumeCreator::GetProgressInfo ()
{
mProgressInfo.SizeDone = SizeDone.Get();
mProgressInfo.Stage = static_cast <ProgressStage::Enum> (Stage.Get());
return mProgressInfo;
}
}
+16
View File
@@ -144,11 +144,26 @@ namespace VeraCrypt
{
public:
struct ProgressStage
{
enum Enum
{
NotStarted = 0,
WritingData,
WritingBackupHeader,
FlushingData,
Finished,
Aborted,
Error
};
};
struct ProgressInfo
{
bool CreationInProgress;
uint64 TotalSize;
uint64 SizeDone;
ProgressStage::Enum Stage;
};
struct KeyInfo
@@ -180,6 +195,7 @@ namespace VeraCrypt
shared_ptr <VolumeLayout> Layout;
shared_ptr <File> VolumeFile;
SharedVal <uint64> SizeDone;
SharedVal <int> Stage;
uint64 WriteOffset;
ProgressInfo mProgressInfo;
@@ -22,7 +22,9 @@ namespace VeraCrypt
ProgressBarRange (1),
RealProgressBarRange (1),
VolumeCreatorRunning (false),
MouseEventsCounter (0)
MouseEventsCounter (0),
CurrentProgressStage (VolumeCreator::ProgressStage::NotStarted),
MaxStaticTextWidth (-1)
{
DisplayKeysCheckBox->SetValue (displayKeyInfo);
#ifdef TC_WINDOWS
@@ -170,9 +172,61 @@ namespace VeraCrypt
void VolumeCreationProgressWizardPage::SetMaxStaticTextWidth (int width)
{
MaxStaticTextWidth = width;
InfoStaticText->Wrap (width);
}
void VolumeCreationProgressWizardPage::SetPageText (const wxString &text)
{
InfoStaticText->SetLabel (text);
if (MaxStaticTextWidth > 0)
InfoStaticText->Wrap (MaxStaticTextWidth);
Layout();
if (GetParent())
GetParent()->Layout();
}
void VolumeCreationProgressWizardPage::SetProgressStage (VolumeCreator::ProgressStage::Enum stage)
{
if (stage == CurrentProgressStage)
return;
CurrentProgressStage = stage;
switch (stage)
{
case VolumeCreator::ProgressStage::WritingData:
SetPageText (LangString["FORMAT_STAGE_WRITING_DATA"]);
break;
case VolumeCreator::ProgressStage::WritingBackupHeader:
SetPageText (LangString["FORMAT_STAGE_WRITING_BACKUP_HEADER"]);
break;
case VolumeCreator::ProgressStage::FlushingData:
SetPageText (LangString["FORMAT_STAGE_FLUSHING_DATA"]);
break;
case VolumeCreator::ProgressStage::Finished:
SetPageText (LangString["FORMAT_STAGE_FINISHED"]);
break;
case VolumeCreator::ProgressStage::Aborted:
SetPageText (LangString["FORMAT_STAGE_ABORTED"]);
break;
case VolumeCreator::ProgressStage::Error:
SetPageText (LangString["FORMAT_STAGE_ERROR"]);
break;
case VolumeCreator::ProgressStage::NotStarted:
default:
break;
}
}
void VolumeCreationProgressWizardPage::SetProgressState (bool volumeCreatorRunning)
{
if (volumeCreatorRunning)
@@ -30,8 +30,9 @@ namespace VeraCrypt
void OnRandomPoolTimer ();
void SetKeyInfo (const VolumeCreator::KeyInfo &keyInfo);
void SetMaxStaticTextWidth (int width);
void SetPageText (const wxString &text) { InfoStaticText->SetLabel (text); }
void SetPageText (const wxString &text);
void SetProgressRange (uint64 progressBarRange);
void SetProgressStage (VolumeCreator::ProgressStage::Enum stage);
void SetProgressValue (uint64 value);
void SetProgressState (bool volumeCreatorRunning);
void IncrementEntropyProgress ();
@@ -54,6 +55,8 @@ namespace VeraCrypt
bool VolumeCreatorRunning;
int MouseEventsCounter;
Mutex AccessMutex;
VolumeCreator::ProgressStage::Enum CurrentProgressStage;
int MaxStaticTextWidth;
};
}
+48 -9
View File
@@ -429,11 +429,14 @@ namespace VeraCrypt
VolumeCreator::ProgressInfo progress = Creator->GetProgressInfo();
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
page->SetProgressValue (progress.SizeDone);
if (page)
{
page->SetProgressStage (progress.Stage);
page->SetProgressValue (progress.SizeDone);
}
if (!progress.CreationInProgress && !AbortConfirmationPending)
{
SetWorkInProgress (false);
OnVolumeCreatorFinished ();
}
}
@@ -447,16 +450,29 @@ namespace VeraCrypt
}
}
void VolumeCreationWizard::SetCreationProgressText (const wxString &text)
{
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
if (!page)
return;
page->SetPageText (text);
page->Refresh();
page->Update();
Gui->Yield();
}
void VolumeCreationWizard::OnVolumeCreatorFinished ()
{
VolumeCreationProgressWizardPage *page = dynamic_cast <VolumeCreationProgressWizardPage *> (GetCurrentPage());
ProgressTimer.reset();
page->SetProgressState (false);
Gui->EndInteractiveBusyState (this);
SetWorkInProgress (false);
UpdateControls();
if (page)
{
page->SetProgressState (false);
page->EnableAbort (false);
}
bool workInProgressCleared = false;
try
{
@@ -472,6 +488,8 @@ namespace VeraCrypt
{
wxBusyCursor busy;
SetCreationProgressText (LangString["FORMAT_STAGE_PREPARING_TEMP_VOLUME"]);
MountOptions mountOptions (Gui->GetPreferences().DefaultMountOptions);
mountOptions.Path = make_shared <VolumePath> (SelectedVolumePath);
mountOptions.NoFilesystem = true;
@@ -483,10 +501,11 @@ namespace VeraCrypt
shared_ptr <VolumeInfo> volume = Core->MountVolume (mountOptions);
finally_do_arg (shared_ptr <VolumeInfo>, volume, { Core->DismountVolume (finally_arg, true); });
shared_ptr <VolumeLayout> layout((volume->Type == VolumeType::Normal)? (VolumeLayout*) new VolumeLayoutV2Normal() : (VolumeLayout*) new VolumeLayoutV2Hidden());
uint64 filesystemSize = layout->GetMaxDataSize (VolumeSize);
SetCreationProgressText (LangString["FORMAT_STAGE_PREPARING_TEMP_DEVICE"]);
Thread::Sleep (2000); // Try to prevent race conditions caused by OS
// Temporarily take ownership of the device if the user is not an administrator
@@ -540,10 +559,16 @@ namespace VeraCrypt
args.push_back (string (virtualDevice));
SetCreationProgressText (StringFormatter (LangString["FORMAT_STAGE_CREATING_FILESYSTEM"], fsFormatter));
Process::Execute (fsFormatter, args);
SetCreationProgressText (LangString["FORMAT_STAGE_DISMOUNTING_TEMP_VOLUME"]);
}
#endif // TC_UNIX
Gui->EndInteractiveBusyState (this);
SetWorkInProgress (false);
workInProgressCleared = true;
if (OuterVolume)
{
SetStep (Step::OuterVolumeContents);
@@ -559,10 +584,24 @@ namespace VeraCrypt
}
catch (exception &e)
{
if (!workInProgressCleared)
{
Gui->EndInteractiveBusyState (this);
SetWorkInProgress (false);
workInProgressCleared = true;
}
Gui->ShowError (e);
}
page->SetProgressValue (0);
if (!workInProgressCleared)
{
Gui->EndInteractiveBusyState (this);
SetWorkInProgress (false);
}
if (page)
page->SetProgressValue (0);
if (SelectedVolumeType == VolumeType::Normal && !SelectedVolumePath.IsDevice())
{
try
+1
View File
@@ -59,6 +59,7 @@ namespace VeraCrypt
void OnThreadExiting (wxCommandEvent& event);
void OnVolumeCreatorFinished ();
WizardStep ProcessPageChangeRequest (bool forward);
void SetCreationProgressText (const wxString &text);
volatile bool AbortConfirmationPending;
volatile bool AbortRequested;