diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/db.cpp | 40 | ||||
| -rw-r--r-- | src/selftest.cpp | 7 |
2 files changed, 41 insertions, 6 deletions
| @@ -1030,6 +1030,13 @@ bool BackupWallet(const string& strDest) | |||
| 1030 | if (!FileExists(strSrc.c_str())) | 1030 | if (!FileExists(strSrc.c_str())) |
| 1031 | return error("BackupWallet() : %s does not exist\n", strSrc.c_str()); | 1031 | return error("BackupWallet() : %s does not exist\n", strSrc.c_str()); |
| 1032 | 1032 | ||
| 1033 | string strTemp = strprintf("%s.tmp.%lld", strDest.c_str(), GetTime()); | ||
| 1034 | for (int i = 1; FileExists(strTemp.c_str()); i++) | ||
| 1035 | strTemp = strprintf("%s.tmp.%lld.%d", strDest.c_str(), GetTime(), i); | ||
| 1036 | string strOld = strprintf("%s.old.%lld", strDest.c_str(), GetTime()); | ||
| 1037 | for (int i = 1; FileExists(strOld.c_str()); i++) | ||
| 1038 | strOld = strprintf("%s.old.%lld.%d", strDest.c_str(), GetTime(), i); | ||
| 1039 | |||
| 1033 | CRITICAL_BLOCK(cs_db) | 1040 | CRITICAL_BLOCK(cs_db) |
| 1034 | { | 1041 | { |
| 1035 | // Committing first, so the copy is not missing the newest records. | 1042 | // Committing first, so the copy is not missing the newest records. |
| @@ -1044,11 +1051,11 @@ bool BackupWallet(const string& strDest) | |||
| 1044 | FILE* pfIn = fopen(strSrc.c_str(), "rb"); | 1051 | FILE* pfIn = fopen(strSrc.c_str(), "rb"); |
| 1045 | if (!pfIn) | 1052 | if (!pfIn) |
| 1046 | return error("BackupWallet() : cannot read %s\n", strSrc.c_str()); | 1053 | return error("BackupWallet() : cannot read %s\n", strSrc.c_str()); |
| 1047 | FILE* pfOut = fopen(strDest.c_str(), "wb"); | 1054 | FILE* pfOut = fopen(strTemp.c_str(), "wb"); |
| 1048 | if (!pfOut) | 1055 | if (!pfOut) |
| 1049 | { | 1056 | { |
| 1050 | fclose(pfIn); | 1057 | fclose(pfIn); |
| 1051 | return error("BackupWallet() : cannot write %s\n", strDest.c_str()); | 1058 | return error("BackupWallet() : cannot write %s\n", strTemp.c_str()); |
| 1052 | } | 1059 | } |
| 1053 | 1060 | ||
| 1054 | char buf[65536]; | 1061 | char buf[65536]; |
| @@ -1065,18 +1072,39 @@ bool BackupWallet(const string& strDest) | |||
| 1065 | 1072 | ||
| 1066 | if (!fOk) | 1073 | if (!fOk) |
| 1067 | { | 1074 | { |
| 1068 | remove(strDest.c_str()); // half a wallet is worse than none | 1075 | remove(strTemp.c_str()); // half a wallet is worse than none |
| 1069 | return error("BackupWallet() : copy to %s failed\n", strDest.c_str()); | 1076 | return error("BackupWallet() : copy to %s failed\n", strTemp.c_str()); |
| 1070 | } | 1077 | } |
| 1071 | 1078 | ||
| 1072 | // Without this the copy is welded to this node's database/ dir. | 1079 | // Without this the copy is welded to this node's database/ dir. |
| 1073 | int ret = dbenv.lsn_reset(strDest.c_str(), 0); | 1080 | int ret = dbenv.lsn_reset(strTemp.c_str(), 0); |
| 1074 | if (ret != 0) | 1081 | if (ret != 0) |
| 1075 | printf("BackupWallet() : warning -- lsn_reset returned %d; the copy " | 1082 | printf("BackupWallet() : warning -- lsn_reset returned %d; the copy " |
| 1076 | "may only open beside this node's database/ directory\n", ret); | 1083 | "may only open beside this node's database/ directory\n", ret); |
| 1084 | |||
| 1085 | bool fHadOldDest = FileExists(strDest.c_str()); | ||
| 1086 | if (fHadOldDest && rename(strDest.c_str(), strOld.c_str()) != 0) | ||
| 1087 | { | ||
| 1088 | remove(strTemp.c_str()); | ||
| 1089 | return error("BackupWallet() : could not move old %s aside\n", strDest.c_str()); | ||
| 1090 | } | ||
| 1091 | if (rename(strTemp.c_str(), strDest.c_str()) != 0) | ||
| 1092 | { | ||
| 1093 | remove(strTemp.c_str()); | ||
| 1094 | if (fHadOldDest) | ||
| 1095 | rename(strOld.c_str(), strDest.c_str()); | ||
| 1096 | return error("BackupWallet() : could not install %s\n", strDest.c_str()); | ||
| 1097 | } | ||
| 1098 | if (fHadOldDest) | ||
| 1099 | remove(strOld.c_str()); | ||
| 1077 | } | 1100 | } |
| 1078 | catch (const std::exception& e) | 1101 | catch (const std::exception& e) |
| 1079 | { return error("BackupWallet() : %s\n", e.what()); } | 1102 | { |
| 1103 | remove(strTemp.c_str()); | ||
| 1104 | if (FileExists(strOld.c_str()) && !FileExists(strDest.c_str())) | ||
| 1105 | rename(strOld.c_str(), strDest.c_str()); | ||
| 1106 | return error("BackupWallet() : %s\n", e.what()); | ||
| 1107 | } | ||
| 1080 | } | 1108 | } |
| 1081 | 1109 | ||
| 1082 | // Recorded here rather than by whoever called, so that a backup taken with | 1110 | // Recorded here rather than by whoever called, so that a backup taken with |
diff --git a/src/selftest.cpp b/src/selftest.cpp index 638aa66..81c4439 100644 --- a/src/selftest.cpp +++ b/src/selftest.cpp | |||
| @@ -1391,6 +1391,13 @@ static int RunWalletPortabilitySelfTest() | |||
| 1391 | nFail += Check(nBackupRet == 0 && FileExists(strPortableWallet.c_str()), | 1391 | nFail += Check(nBackupRet == 0 && FileExists(strPortableWallet.c_str()), |
| 1392 | "/backupwallet writes a portable wallet.dat") ? 0 : 1; | 1392 | "/backupwallet writes a portable wallet.dat") ? 0 : 1; |
| 1393 | 1393 | ||
| 1394 | string strBackupOut2 = tmp + "/backupwallet-overwrite.txt"; | ||
| 1395 | int nBackupRet2 = RunBitflashChild(strExe, vBackupArgs, NULL, &strBackupOut2); | ||
| 1396 | nFail += Check(nBackupRet2 == 0 && FileExists(strPortableWallet.c_str()) && | ||
| 1397 | !DirectoryHasFileWithPrefix(tmp, "portable-wallet.dat.tmp.") && | ||
| 1398 | !DirectoryHasFileWithPrefix(tmp, "portable-wallet.dat.old."), | ||
| 1399 | "/backupwallet replaces an existing backup without leaving temp files") ? 0 : 1; | ||
| 1400 | |||
| 1394 | nFail += Check(CopyFileLocal(strOriginal + "/wallet.dat", | 1401 | nFail += Check(CopyFileLocal(strOriginal + "/wallet.dat", |
| 1395 | strRawCopy + "/wallet.dat"), | 1402 | strRawCopy + "/wallet.dat"), |
| 1396 | "a raw wallet.dat can be copied without database logs") ? 0 : 1; | 1403 | "a raw wallet.dat can be copied without database logs") ? 0 : 1; |