From 50f3321154bfce7604dba31eae7aaf2b2502208d Mon Sep 17 00:00:00 2001 From: Leland Lucius Date: Tue, 5 Jan 2021 01:32:03 -0600 Subject: [PATCH] Bug 2576 - FAT formatted disks can readily run out of space with multiple edits - wrong error message can be displayed --- src/FileNames.cpp | 19 +++++++++ src/FileNames.h | 1 + src/ProjectFileManager.cpp | 15 +++++++ src/prefs/DirectoriesPrefs.cpp | 75 ++++++++++++++++++++++++++++++++++ src/prefs/DirectoriesPrefs.h | 1 + 5 files changed, 111 insertions(+) diff --git a/src/FileNames.cpp b/src/FileNames.cpp index 4351aa62e..e4bacbada 100644 --- a/src/FileNames.cpp +++ b/src/FileNames.cpp @@ -37,6 +37,7 @@ used throughout Audacity into this one place. #include "PlatformCompatibility.h" #include "wxFileNameWrapper.h" #include "widgets/AudacityMessageBox.h" +#include "widgets/ErrorDialog.h" #include "widgets/FileDialog/FileDialog.h" #if defined(__WXMAC__) || defined(__WXGTK__) @@ -864,6 +865,23 @@ bool FileNames::IsOnFATFileSystem(const FilePath &path) } #endif +bool FileNames::FATFilesystemDenied( const FilePath &path, wxFrame *window /* = nullptr */ ) +{ + if (FileNames::IsOnFATFileSystem(path)) + { + ShowErrorDialog( + window, + XO("Unsuitable"), + XO("FAT formatted filesystems are unsuitable."), + "Error:_Unsuitable_drive" + ); + + return true; + } + + return false; +} + wxString FileNames::AbbreviatePath( const wxFileName &fileName ) { wxString target; @@ -884,3 +902,4 @@ wxString FileNames::AbbreviatePath( const wxFileName &fileName ) #endif return target; } + diff --git a/src/FileNames.h b/src/FileNames.h index 079e027f3..620d74abc 100644 --- a/src/FileNames.h +++ b/src/FileNames.h @@ -213,6 +213,7 @@ namespace FileNames AUDACITY_DLL_API bool IsOnFATFileSystem(const FilePath &path); + bool FATFilesystemDenied(const FilePath &path, wxFrame *window = nullptr); AUDACITY_DLL_API //! Give enough of the path to identify the device. (On Windows, drive letter plus ':') diff --git a/src/ProjectFileManager.cpp b/src/ProjectFileManager.cpp index 421e588ff..fdb869b4b 100644 --- a/src/ProjectFileManager.cpp +++ b/src/ProjectFileManager.cpp @@ -269,6 +269,11 @@ bool ProjectFileManager::DoSave(const FilePath & fileName, const bool fromSaveAs // Some confirmation dialogs { + if (FileNames::FATFilesystemDenied(fileName)) + { + return false; + } + auto &tracks = TrackList::Get( proj ); if (!tracks.Any()) { @@ -582,6 +587,16 @@ bool ProjectFileManager::SaveCopy(const FilePath &fileName /* = wxT("") */) filename.SetExt(wxT("aup3")); + if (FileNames::FATFilesystemDenied(filename.GetFullPath())) + { + if (project.mBatchMode) + { + return false; + } + + continue; + } + if (filename.FileExists()) { // Saving a copy of the project should never overwrite an existing project. diff --git a/src/prefs/DirectoriesPrefs.cpp b/src/prefs/DirectoriesPrefs.cpp index 61bfdcea9..ffd45ad6d 100644 --- a/src/prefs/DirectoriesPrefs.cpp +++ b/src/prefs/DirectoriesPrefs.cpp @@ -39,6 +39,63 @@ using namespace FileNames; +class FilesystemValidator : public wxValidator +{ +public: + FilesystemValidator() + : wxValidator() + { + } + + virtual wxObject* Clone() const wxOVERRIDE + { + return safenew FilesystemValidator(*this); + } + + virtual bool Validate(wxWindow* WXUNUSED(parent)) wxOVERRIDE + { + wxTextCtrl* tc = wxDynamicCast(GetWindow(), wxTextCtrl); + if (!tc) { + return true; + } + + if (FATFilesystemDenied(tc->GetValue())) { + return false; + } + + return true; + } + + void OnChar(wxKeyEvent &evt) + { + evt.Skip(); + + wxTextCtrl* tc = wxDynamicCast(GetWindow(), wxTextCtrl); + if (!tc) { + return; + } + + auto keycode = evt.GetUnicodeKey(); + if (keycode < WXK_SPACE || keycode == WXK_DELETE) { + return; + } + + wxString path = tc->GetValue(); + path.insert(tc->GetInsertionPoint(), keycode); + + if (FileNames::FATFilesystemDenied(path)) { + evt.Skip(false); + return; + } + } + + wxDECLARE_EVENT_TABLE(); +}; + +wxBEGIN_EVENT_TABLE(FilesystemValidator, wxValidator) + EVT_CHAR(FilesystemValidator::OnChar) +wxEND_EVENT_TABLE() + enum { TempTextID = 1000, @@ -110,6 +167,8 @@ void DirectoriesPrefs::Populate() void DirectoriesPrefs::PopulateOrExchange(ShuttleGui &S) { + FilesystemValidator validator; + S.SetBorder(2); S.StartScroller(); @@ -136,6 +195,7 @@ void DirectoriesPrefs::PopulateOrExchange(ShuttleGui &S) {PreferenceKey(Operation::Save, PathType::User), wxT("")}, 30); + mSaveText->SetValidator(validator); S.Id(SaveButtonID).AddButton(XXO("B&rowse...")); S.Id(ImportTextID); @@ -150,6 +210,7 @@ void DirectoriesPrefs::PopulateOrExchange(ShuttleGui &S) {PreferenceKey(Operation::Export, PathType::User), wxT("")}, 30); + mExportText->SetValidator(validator); S.Id(ExportButtonID).AddButton(XXO("Bro&wse...")); } S.EndMultiColumn(); @@ -167,6 +228,7 @@ void DirectoriesPrefs::PopulateOrExchange(ShuttleGui &S) {PreferenceKey(Operation::Temp, PathType::_None), wxT("")}, 30); + mTempText->SetValidator(validator); S.Id(TempButtonID).AddButton(XXO("Brow&se...")); S.AddPrompt(XXO("&Free Space:")); @@ -203,6 +265,10 @@ void DirectoriesPrefs::OnTempBrowse(wxCommandEvent &evt) wxFileName tmpDirPath; tmpDirPath.AssignDir(dlog.GetPath()); + if (FATFilesystemDenied(tmpDirPath.GetFullPath())) { + return; + } + // Append an "audacity_temp" directory to this path if necessary (the // default, the existing pref (as stored in the control), and any path // ending in a directory with the same name as what we'd add should be OK @@ -270,6 +336,14 @@ void DirectoriesPrefs::OnBrowse(wxCommandEvent &evt) return; } + if (evt.GetId() == SaveButtonID || evt.GetId() == ExportButtonID) + { + if (FATFilesystemDenied(dlog.GetPath())) + { + return; + } + } + tc->SetValue(dlog.GetPath()); } @@ -287,6 +361,7 @@ bool DirectoriesPrefs::Validate() wxOK | wxICON_ERROR); return false; } + if (!Temp.DirExists()) { int ans = AudacityMessageBox( XO("Directory %s does not exist. Create it?") diff --git a/src/prefs/DirectoriesPrefs.h b/src/prefs/DirectoriesPrefs.h index 609079b1c..398929b5f 100644 --- a/src/prefs/DirectoriesPrefs.h +++ b/src/prefs/DirectoriesPrefs.h @@ -40,6 +40,7 @@ class DirectoriesPrefs final : public PrefsPanel void OnTempBrowse(wxCommandEvent &evt); void OnBrowse(wxCommandEvent &evt); + void OnText(wxCommandEvent &evt); wxTextCtrl *mFreeSpace; wxTextCtrl *mTempText;