diff options
| author | Bitflash <btf01@proton.me> | 2026-08-01 14:48:12 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-08-01 14:48:12 -0300 |
| commit | ae81fa37123730982c4e054d7433c9d0c944a373 (patch) | |
| tree | 771c0e5ca58c476a0a6ba1138fef3efeaf767524 /src/gui.cpp | |
| parent | 9da2183bb16e4c32cafbb71eeadc7f112b48ab05 (diff) | |
wallet: keep the default backup out of the directory it protects (#90)
Two follow-ups to #89. The default backup path was inside the data directory --
same disk, same folder the README says to copy wholesale, same folder the user
eventually deletes, which is the moment the backup was for. It now defaults to
the home directory and the dialog says so when a path under the data directory
is chosen anyway.
And nLastWalletBackup was written by the GUI, so anyone backing up with
/backupwallet -- the method the README documents first -- was told forever that
they had never backed up. BackupWallet records it now, so both paths count.
Diffstat (limited to 'src/gui.cpp')
| -rw-r--r-- | src/gui.cpp | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/src/gui.cpp b/src/gui.cpp index df61bb1..51b5d5f 100644 --- a/src/gui.cpp +++ b/src/gui.cpp | |||
| @@ -125,9 +125,47 @@ static std::string BackupTimeSuffix() | |||
| 125 | return strprintf("%lld", (long long)GetTime()); | 125 | return strprintf("%lld", (long long)GetTime()); |
| 126 | } | 126 | } |
| 127 | 127 | ||
| 128 | // Where to put a backup by default. | ||
| 129 | // | ||
| 130 | // Not the data directory. A copy that lives in the folder it is meant to | ||
| 131 | // outlive is not a backup: same disk, same directory the README tells people to | ||
| 132 | // copy wholesale, and the same directory they are eventually going to delete -- | ||
| 133 | // which is the moment the backup was for. The home directory is not off-site | ||
| 134 | // either, but it survives the one accident this file exists to survive. | ||
| 135 | static std::string DefaultBackupDir() | ||
| 136 | { | ||
| 137 | #ifdef _WIN32 | ||
| 138 | const char* pszHome = getenv("USERPROFILE"); | ||
| 139 | #else | ||
| 140 | const char* pszHome = getenv("HOME"); | ||
| 141 | #endif | ||
| 142 | if (pszHome && *pszHome) | ||
| 143 | return std::string(pszHome); | ||
| 144 | return GetAppDir(); // nothing better available; the warning below still fires | ||
| 145 | } | ||
| 146 | |||
| 147 | // True when a path sits inside the data directory, so the dialog can say so. | ||
| 148 | static bool PathIsInsideDataDir(const std::string& strPath) | ||
| 149 | { | ||
| 150 | std::string strDir = GetAppDir(); | ||
| 151 | if (strPath.size() < strDir.size()) | ||
| 152 | return false; | ||
| 153 | std::string a = strPath.substr(0, strDir.size()); | ||
| 154 | // Windows paths are case-insensitive and mix separators; compare loosely. | ||
| 155 | for (size_t i = 0; i < a.size(); i++) | ||
| 156 | { | ||
| 157 | char c1 = a[i], c2 = strDir[i]; | ||
| 158 | if (c1 == '\\') c1 = '/'; | ||
| 159 | if (c2 == '\\') c2 = '/'; | ||
| 160 | if (tolower((unsigned char)c1) != tolower((unsigned char)c2)) | ||
| 161 | return false; | ||
| 162 | } | ||
| 163 | return true; | ||
| 164 | } | ||
| 165 | |||
| 128 | static void SetDefaultBackupPath() | 166 | static void SetDefaultBackupPath() |
| 129 | { | 167 | { |
| 130 | std::string path = GetAppDir() + "/wallet-backup-" + BackupTimeSuffix() + ".dat"; | 168 | std::string path = DefaultBackupDir() + "/wallet-backup-" + BackupTimeSuffix() + ".dat"; |
| 131 | strncpy(g_backupPath, path.c_str(), sizeof(g_backupPath)-1); | 169 | strncpy(g_backupPath, path.c_str(), sizeof(g_backupPath)-1); |
| 132 | g_backupPath[sizeof(g_backupPath)-1] = '\0'; | 170 | g_backupPath[sizeof(g_backupPath)-1] = '\0'; |
| 133 | } | 171 | } |
| @@ -899,6 +937,16 @@ static void DrawWalletSafetyDialog() | |||
| 899 | ImGui::SetNextItemWidth(-1.0f); | 937 | ImGui::SetNextItemWidth(-1.0f); |
| 900 | ImGui::InputText("##backup-path", g_backupPath, sizeof(g_backupPath)); | 938 | ImGui::InputText("##backup-path", g_backupPath, sizeof(g_backupPath)); |
| 901 | 939 | ||
| 940 | if (PathIsInsideDataDir(g_backupPath)) | ||
| 941 | { | ||
| 942 | ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 0.75f, 0.25f, 1.0f)); | ||
| 943 | ImGui::TextWrapped( | ||
| 944 | "This path is inside the data directory. A backup kept there is lost " | ||
| 945 | "with the thing it was protecting -- put it on another disk, or at " | ||
| 946 | "least somewhere you would not delete along with the node's files."); | ||
| 947 | ImGui::PopStyleColor(); | ||
| 948 | } | ||
| 949 | |||
| 902 | if (ImGui::Button("Use new default name", ImVec2(170.0f, 0.0f))) | 950 | if (ImGui::Button("Use new default name", ImVec2(170.0f, 0.0f))) |
| 903 | SetDefaultBackupPath(); | 951 | SetDefaultBackupPath(); |
| 904 | ImGui::SameLine(); | 952 | ImGui::SameLine(); |
| @@ -922,8 +970,9 @@ static void DrawWalletSafetyDialog() | |||
| 922 | TopUpKeyPool(); | 970 | TopUpKeyPool(); |
| 923 | if (BackupWallet(path)) | 971 | if (BackupWallet(path)) |
| 924 | { | 972 | { |
| 925 | g_lastWalletBackup = GetTime(); | 973 | // BackupWallet records the time itself, so a backup taken |
| 926 | CWalletDB().WriteSetting("nLastWalletBackup", g_lastWalletBackup); | 974 | // with /backupwallet counts the same as one taken here. |
| 975 | CWalletDB("r").ReadSetting("nLastWalletBackup", g_lastWalletBackup); | ||
| 927 | g_backupStatus = "Backup written: " + path; | 976 | g_backupStatus = "Backup written: " + path; |
| 928 | SetDefaultBackupPath(); | 977 | SetDefaultBackupPath(); |
| 929 | } | 978 | } |