Lagrange [work/v1.15]

More robust saving of bookmarks and identities

=> 884d31a3a8231d760a6c6be70d52e1676daef306

diff --git a/src/app.c b/src/app.c
index 5e4d7489..331f84d9 100644
--- a/src/app.c
+++ b/src/app.c
@@ -846,10 +846,16 @@ static void saveState_App_(const iApp *d) {
     }
     /* Copy it over to the real file. This avoids truncation if the app for any reason crashes
        before the state file is fully written. */
-    const char *tempName = concatPath_CStr(dataDir_App_(), tempStateFileName_App_);
-    const char *finalName = concatPath_CStr(dataDir_App_(), stateFileName_App_);
-    remove(finalName);
-    rename(tempName, finalName);
+    commitFile_App(concatPath_CStr(dataDir_App_(), stateFileName_App_),
+                   concatPath_CStr(dataDir_App_(), tempStateFileName_App_));
+}
+
+void commitFile_App(const char *path, const char *tempPathWithNewContents) {
+    iString *oldPath = collectNewCStr_String(path);
+    appendCStr_String(oldPath, ".old");
+    rename(path, cstr_String(oldPath));
+    rename(tempPathWithNewContents, path);
+    remove(cstr_String(oldPath));
 }
 
 #if defined (LAGRANGE_ENABLE_IDLE_SLEEP)
diff --git a/src/app.h b/src/app.h
index d5a49c73..ce59bb87 100644
--- a/src/app.h
+++ b/src/app.h
@@ -166,3 +166,4 @@ void            revealPath_App          (const iString *path);
 void            updateCACertificates_App(void);
 void            resetFonts_App          (void);
 void            availableFontsChanged_App(void);
+void            commitFile_App          (const char *path, const char *tempPathWithNewContents); /* latter will be removed */
diff --git a/src/bookmarks.c b/src/bookmarks.c
index 51d1005e..bfc47783 100644
--- a/src/bookmarks.c
+++ b/src/bookmarks.c
@@ -154,8 +154,9 @@ iBool filterInsideFolder_Bookmark(void *context, const iBookmark *bm) {
 
 /*----------------------------------------------------------------------------------------------*/
 
-static const char *oldFileName_Bookmarks_ = "bookmarks.txt";
-static const char *fileName_Bookmarks_    = "bookmarks.ini"; /* since v1.7 (TOML subset) */
+static const char *oldFileName_Bookmarks_  = "bookmarks.txt";
+static const char *fileName_Bookmarks_     = "bookmarks.ini"; /* since v1.7 (TOML subset) */
+static const char *tempFileName_Bookmarks_ = "bookmarks.ini.tmp";
 
 struct Impl_Bookmarks {
     iMutex *  mtx;
@@ -491,13 +492,16 @@ void serialize_Bookmarks(const iBookmarks *d, iStream *out) {
 }
 
 void save_Bookmarks(const iBookmarks *d, const char *dirPath) {
+    const char *tempPath = concatPath_CStr(dirPath, tempFileName_Bookmarks_);
+    const char *finalPath = concatPath_CStr(dirPath, fileName_Bookmarks_);
     lock_Mutex(d->mtx);
-    iFile *f = newCStr_File(concatPath_CStr(dirPath, fileName_Bookmarks_));
+    iFile *f = newCStr_File(tempPath);
     if (open_File(f, writeOnly_FileMode | text_FileMode)) {
         serialize_Bookmarks(d, stream_File(f));
     }
     iRelease(f);
     unlock_Mutex(d->mtx);
+    commitFile_App(finalPath, tempPath);
 }
 
 static iRangei orderRange_Bookmarks_(const iBookmarks *d) {
diff --git a/src/gmcerts.c b/src/gmcerts.c
index f8f2ebc5..31cd8c9b 100644
--- a/src/gmcerts.c
+++ b/src/gmcerts.c
@@ -40,6 +40,7 @@ static const char *trustedFilename_GmCerts_   = "trusted.2.txt";
 static const char *identsDir_GmCerts_         = "idents";
 static const char *oldIdentsFilename_GmCerts_ = "idents.binary";
 static const char *identsFilename_GmCerts_    = "idents.lgr";
+static const char *tempIdentsFilename_GmCerts_= "idents.lgr.tmp";
 
 iDeclareClass(TrustEntry)
 
@@ -277,11 +278,15 @@ void serialize_GmCerts(const iGmCerts *d, iStream *trusted, iStream *identsMeta)
 }
 
 void saveIdentities_GmCerts(const iGmCerts *d) {
-    iFile *f = new_File(collect_String(concatCStr_Path(&d->saveDir, identsFilename_GmCerts_)));
+    const iString *tempPath = collect_String(
+            concatCStr_Path(&d->saveDir, tempIdentsFilename_GmCerts_));
+    iFile *f = new_File(tempPath);
     if (open_File(f, writeOnly_FileMode)) {
         serialize_GmCerts(d, NULL, stream_File(f));
     }
     iRelease(f);
+    commitFile_App(cstrCollect_String(concatCStr_Path(&d->saveDir, identsFilename_GmCerts_)),
+                   cstr_String(tempPath));
 }
 
 static void save_GmCerts_(const iGmCerts *d) {
Proxy Information
Original URL
gemini://git.skyjake.fi/lagrange/work%2Fv1.15/cdiff/884d31a3a8231d760a6c6be70d52e1676daef306
Status Code
Success (20)
Meta
text/gemini; charset=utf-8
Capsule Response Time
64.555378 milliseconds
Gemini-to-HTML Time
0.362703 milliseconds

This content has been proxied by September (3851b).