From 0d6ff4d0ed05a2a35cd7ade12e2c924704211bc8 Mon Sep 17 00:00:00 2001 From: George Hazan Date: Fri, 29 Jun 2018 14:31:56 +0300 Subject: safer method of backing up databases instead of trying to read them manually --- plugins/Db_autobackups/src/backup.cpp | 53 ++++++++++++++++++++++++++--------- plugins/Db_autobackups/src/stdafx.h | 1 + plugins/Dbx_mdbx/src/dbintf.cpp | 17 +++++++++++ plugins/Dbx_mdbx/src/dbintf.h | 1 + 4 files changed, 58 insertions(+), 14 deletions(-) (limited to 'plugins') diff --git a/plugins/Db_autobackups/src/backup.cpp b/plugins/Db_autobackups/src/backup.cpp index 0d9764b75e..cd87c676a1 100644 --- a/plugins/Db_autobackups/src/backup.cpp +++ b/plugins/Db_autobackups/src/backup.cpp @@ -3,7 +3,6 @@ static UINT_PTR timer_id = 0; volatile long m_state = 0; - LRESULT CALLBACK DlgProcPopup(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { @@ -78,18 +77,36 @@ wchar_t* DoubleSlash(wchar_t *sorce) return ret; } -bool MakeZip_Dir(LPCWSTR szDir, LPCWSTR szDest, LPCWSTR pwszBackupFolder, HWND progress_dialog) +bool MakeZip_Dir(LPCWSTR szDir, LPCWSTR pwszProfile, LPCWSTR szDest, LPCWSTR pwszBackupFolder, HWND progress_dialog) { HWND hProgBar = GetDlgItem(progress_dialog, IDC_PROGRESS); size_t count = 0, folderNameLen = mir_wstrlen(pwszBackupFolder); OBJLIST lstFiles(15); + wchar_t wszTempName[MAX_PATH]; + if (!GetTempPathW(_countof(wszTempName), wszTempName)) + return false; + + if (!GetTempFileNameW(wszTempName, L"mir_backup_", 0, wszTempName)) + return false; + + if (db_get_current()->Backup(wszTempName)) + return false; + + lstFiles.insert(new ZipFile(wszTempName, pwszProfile)); + + CMStringW wszProfile; + wszProfile.Format(L"%s\\%s", szDir, pwszProfile); + for (auto it = fs::recursive_directory_iterator(fs::path(szDir)); it != fs::recursive_directory_iterator(); ++it) { const auto& file = it->path(); if (fs::is_directory(file)) continue; const std::wstring &filepath = file.wstring(); + if (wszProfile == filepath.c_str()) + continue; + if (filepath.find(szDest) != std::wstring::npos || !mir_wstrncmpi(filepath.c_str(), pwszBackupFolder, folderNameLen)) continue; @@ -106,19 +123,29 @@ bool MakeZip_Dir(LPCWSTR szDir, LPCWSTR szDest, LPCWSTR pwszBackupFolder, HWND p return GetWindowLongPtr(progress_dialog, GWLP_USERDATA) != 1; }); + DeleteFileW(wszTempName); return 1; } -bool MakeZip(wchar_t *tszSource, wchar_t *tszDest, wchar_t *dbname, HWND progress_dialog) +bool MakeZip(wchar_t *tszDest, wchar_t *dbname, HWND progress_dialog) { HWND hProgBar = GetDlgItem(progress_dialog, IDC_PROGRESS); - ptrW tszDestPath(DoubleSlash(tszDest)); - OBJLIST lstFiles(15); - lstFiles.insert(new ZipFile(tszSource, dbname)); + wchar_t wszTempName[MAX_PATH]; + if (!GetTempPathW(_countof(wszTempName), wszTempName)) + return false; - CreateZipFile(tszDest, lstFiles, [&](size_t)->bool { SendMessage(hProgBar, PBM_SETPOS, (WPARAM)(100), 0); return true; }); + if (!GetTempFileNameW(wszTempName, L"mir_backup_", 0, wszTempName)) + return false; + if (db_get_current()->Backup(wszTempName)) + return false; + + OBJLIST lstFiles(1); + lstFiles.insert(new ZipFile(wszTempName, dbname)); + + CreateZipFile(tszDest, lstFiles, [&](size_t)->bool { SendMessage(hProgBar, PBM_SETPOS, (WPARAM)(100), 0); return true; }); + DeleteFileW(wszTempName); return true; } @@ -183,7 +210,7 @@ err_out: int Backup(wchar_t *backup_filename) { bool bZip = false; - wchar_t dbname[MAX_PATH], source_file[MAX_PATH] = { 0 }, dest_file[MAX_PATH]; + wchar_t dbname[MAX_PATH], dest_file[MAX_PATH]; HWND progress_dialog = nullptr; Profile_GetNameW(_countof(dbname), dbname); @@ -223,15 +250,13 @@ int Backup(wchar_t *backup_filename) SetDlgItemText(progress_dialog, IDC_PROGRESSMESSAGE, TranslateT("Copying database file...")); - VARSW profile_path(L"%miranda_userdata%"); - mir_snwprintf(source_file, L"%s\\%s", profile_path, dbname); - BOOL res = 0; + BOOL res; if (bZip) { res = options.backup_profile - ? MakeZip_Dir(profile_path, dest_file, backupfolder, progress_dialog) - : MakeZip(source_file, dest_file, dbname, progress_dialog); + ? MakeZip_Dir(VARSW(L"%miranda_userdata%"), dbname, dest_file, backupfolder, progress_dialog) + : MakeZip(dest_file, dbname, progress_dialog); } - else res = CopyFile(source_file, dest_file, 0); + else res = db_get_current()->Backup(dest_file) == ERROR_SUCCESS; if (res) { if (!bZip) { // Set the backup file to the current time for rotator's correct work diff --git a/plugins/Db_autobackups/src/stdafx.h b/plugins/Db_autobackups/src/stdafx.h index e6d992c8ca..1c2036e736 100644 --- a/plugins/Db_autobackups/src/stdafx.h +++ b/plugins/Db_autobackups/src/stdafx.h @@ -15,6 +15,7 @@ namespace fs = std::experimental::filesystem; #include #include #include +#include #include #include #include diff --git a/plugins/Dbx_mdbx/src/dbintf.cpp b/plugins/Dbx_mdbx/src/dbintf.cpp index 9fffe8f732..cb663276c6 100644 --- a/plugins/Dbx_mdbx/src/dbintf.cpp +++ b/plugins/Dbx_mdbx/src/dbintf.cpp @@ -200,6 +200,23 @@ BOOL CDbxMDBX::Compact() return 0; } +BOOL CDbxMDBX::Backup(const wchar_t *pwszPath) +{ + HANDLE pFile = ::CreateFile(pwszPath, GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr); + if (pFile == nullptr) { + Netlib_Logf(0, "Backup file <%S> cannot be created", pwszPath); + return 1; + } + + int res = mdbx_env_copy2fd(m_env, pFile, 0); + CloseHandle(pFile); + if (res == MDBX_SUCCESS) + return 0; + + DeleteFileW(pwszPath); + return res; +} + ///////////////////////////////////////////////////////////////////////////////////////// int CDbxMDBX::PrepareCheck() diff --git a/plugins/Dbx_mdbx/src/dbintf.h b/plugins/Dbx_mdbx/src/dbintf.h index 1eebe92b2c..73fb14e36b 100644 --- a/plugins/Dbx_mdbx/src/dbintf.h +++ b/plugins/Dbx_mdbx/src/dbintf.h @@ -268,6 +268,7 @@ public: STDMETHODIMP_(BOOL) MetaSplitHistory(DBCachedContact *ccMeta, DBCachedContact *ccSub); STDMETHODIMP_(BOOL) Compact(); + STDMETHODIMP_(BOOL) Backup(LPCWSTR); public: MICryptoEngine *m_crypto; -- cgit v1.2.3