2009-03-16 [colin] 3.7.1cvs14
authorColin Leroy <colin@colino.net>
Mon, 16 Mar 2009 17:59:26 +0000 (17:59 +0000)
committerColin Leroy <colin@colino.net>
Mon, 16 Mar 2009 17:59:26 +0000 (17:59 +0000)
* src/compose.c
* src/folder.c
* src/folder.h
* src/msgcache.c
* src/common/prefs.c
Add fsync calls to make sure we don't
lose data on system crashes. (to do:
add a pref to allow people choosing raw
speed)

ChangeLog
PATCHSETS
configure.ac
src/common/prefs.c
src/compose.c
src/folder.c
src/folder.h
src/msgcache.c

index ff034c115d170695f4564075bea09dacb638be09..3a2a3fa426a25bf2846f398ccb3fda7fa0fb1d4b 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2009-03-16 [colin]     3.7.1cvs14
+
+       * src/compose.c
+       * src/folder.c
+       * src/folder.h
+       * src/msgcache.c
+       * src/common/prefs.c
+               Add fsync calls to make sure we don't
+               lose data on system crashes. (to do:
+               add a pref to allow people choosing raw
+               speed)
+
 2009-03-15 [colin]     3.7.1cvs13
 
        * src/gtk/gtkaspell.c
index b12b95652c2d15bc1658823d24cc4236da3db22d..405f050ff7ec6c2eadf19a0b791db343641cbdfe 100644 (file)
--- a/PATCHSETS
+++ b/PATCHSETS
 ( cvs diff -u -r 1.60.2.57 -r 1.60.2.58 po/es.po;  ) > 3.7.1cvs11.patchset
 ( cvs diff -u -r 1.36.2.166 -r 1.36.2.167 src/common/utils.c;  ) > 3.7.1cvs12.patchset
 ( cvs diff -u -r 1.9.2.67 -r 1.9.2.68 src/gtk/gtkaspell.c;  ) > 3.7.1cvs13.patchset
+( cvs diff -u -r 1.382.2.503 -r 1.382.2.504 src/compose.c;  cvs diff -u -r 1.213.2.190 -r 1.213.2.191 src/folder.c;  cvs diff -u -r 1.87.2.58 -r 1.87.2.59 src/folder.h;  cvs diff -u -r 1.16.2.65 -r 1.16.2.66 src/msgcache.c;  cvs diff -u -r 1.5.2.15 -r 1.5.2.16 src/common/prefs.c;  ) > 3.7.1cvs14.patchset
index 71b3d48d90ff1b4704cbc7fc8619138181d7ad77..c2664e08ef1f03df35ee79f6d1fa1991a92e65ec 100644 (file)
@@ -11,7 +11,7 @@ MINOR_VERSION=7
 MICRO_VERSION=1
 INTERFACE_AGE=0
 BINARY_AGE=0
-EXTRA_VERSION=13
+EXTRA_VERSION=14
 EXTRA_RELEASE=
 EXTRA_GTK2_VERSION=
 
index fb2cae6423ec44c29d5a6cb4a67cc779a88b223e..5b420419e06b91b1905ccfc368144940877adc99 100644 (file)
@@ -162,6 +162,17 @@ gint prefs_file_close(PrefFile *pfile)
        }
 
        tmppath = g_strconcat(path, ".tmp", NULL);
+
+       
+       if (fsync(fileno(fp)) < 0) {
+               FILE_OP_ERROR(tmppath, "fsync");
+               fclose(fp);
+               claws_unlink(tmppath);
+               g_free(path);
+               g_free(tmppath);
+               return -1;
+       }
+
        if (fclose(fp) == EOF) {
                FILE_OP_ERROR(tmppath, "fclose");
                claws_unlink(tmppath);
index dc7a7fcd9c3ecc25f001f23731598cae00f30556..76cacd72f56c4e7f38251ef78e2fc20ddad96de5 100644 (file)
@@ -10702,8 +10702,10 @@ static void compose_reply_from_messageview_real(MessageView *msgview, GSList *ms
 
                                tmp_msginfo->folder = orig_msginfo->folder;
                                tmp_msginfo->msgnum = orig_msginfo->msgnum; 
-                               if (orig_msginfo->tags)
+                               if (orig_msginfo->tags) {
                                        tmp_msginfo->tags = g_slist_copy(orig_msginfo->tags);
+                                       tmp_msginfo->folder->tags_dirty = TRUE;
+                               }
                        }
                }
        }
index 7a434b67deb37f34cbda1420e843bfd3a6cbec22..7b0554e02bd140ed31740901809ac94ed784b985 100644 (file)
@@ -2573,13 +2573,17 @@ static void folder_item_read_cache(FolderItem *item)
        } else {
                item->cache = msgcache_new();
        }
+       item->cache_dirty = FALSE;
+       item->mark_dirty = FALSE;
+       item->tags_dirty = FALSE;
+
        END_TIMING();
        folder_clean_cache_memory(item);
 }
 
 void folder_item_write_cache(FolderItem *item)
 {
-       gchar *cache_file, *mark_file, *tags_file;
+       gchar *cache_file = NULL, *mark_file = NULL, *tags_file = NULL;
        FolderItemPrefs *prefs;
        gint filemode = 0;
        gchar *id;
@@ -2599,9 +2603,12 @@ void folder_item_write_cache(FolderItem *item)
        debug_print("Save cache for folder %s\n", id);
        g_free(id);
 
-       cache_file = folder_item_get_cache_file(item);
-       mark_file = folder_item_get_mark_file(item);
-       tags_file = folder_item_get_tags_file(item);
+       if (item->cache_dirty)
+               cache_file = folder_item_get_cache_file(item);
+       if (item->cache_dirty || item->mark_dirty)
+               mark_file = folder_item_get_mark_file(item);
+       if (item->cache_dirty || item->tags_dirty)
+               tags_file = folder_item_get_tags_file(item);
        if (msgcache_write(cache_file, mark_file, tags_file, item->cache) < 0) {
                prefs = item->prefs;
                if (prefs && prefs->enable_folder_chmod && prefs->folder_chmod) {
@@ -2611,7 +2618,11 @@ void folder_item_write_cache(FolderItem *item)
                        if (filemode & S_IROTH) filemode |= S_IWOTH;
                        chmod(cache_file, filemode);
                }
-        }
+        } else {
+               item->cache_dirty = FALSE;
+               item->mark_dirty = FALSE;
+               item->tags_dirty = FALSE;
+       }
 
        if (!need_scan && item->folder->klass->set_mtime) {
                if (item->mtime == last_mtime) {
@@ -3678,6 +3689,9 @@ void folder_item_change_msg_flags(FolderItem *item, MsgInfo *msginfo, MsgPermFla
 {
        cm_return_if_fail(item != NULL);
        cm_return_if_fail(msginfo != NULL);
+       
+       item->mark_dirty = TRUE;
+
        if (item->no_select)
                return;
        
@@ -3703,6 +3717,8 @@ void folder_item_commit_tags(FolderItem *item, MsgInfo *msginfo, GSList *tags_se
        if (!folder)
                return;
        
+       item->tags_dirty = TRUE;
+
        if (folder->klass->commit_tags == NULL)
                return;
        
index b656bd07511acfd0239e038ed143ac64dab4515d..adb9dadd108dfcbe9af509eb11122c3c5a557d9a 100644 (file)
@@ -656,6 +656,9 @@ struct _FolderItem
        gint last_num;
 
        MsgCache *cache;
+       gboolean cache_dirty;
+       gboolean mark_dirty;
+       gboolean tags_dirty;
 
        /* special flags */
        guint no_sub         : 1; /* no child allowed?    */
index 717f70ff051f881aa7182174f593cd4a321f7fda..798f95833644a5f1456cd56799de94a4eb55ac39 100644 (file)
@@ -70,7 +70,6 @@
         ((x[3]&0xff) << 24))
 
 static gboolean msgcache_use_mmap_read = TRUE;
-static gboolean msgcache_use_mmap_write = FALSE;
 
 #else
 #define bswap_32(x) (x)
@@ -88,7 +87,6 @@ static gboolean msgcache_use_mmap_write = FALSE;
         ((x[3]&0xff) << 24))
 
 static gboolean msgcache_use_mmap_read = TRUE;
-static gboolean msgcache_use_mmap_write = FALSE;
 #endif
 
 static gboolean swapping = TRUE;
@@ -168,6 +166,8 @@ void msgcache_add_msg(MsgCache *cache, MsgInfo *msginfo)
        cache->memusage += procmsg_msginfo_memusage(msginfo);
        cache->last_access = time(NULL);
 
+       msginfo->folder->cache_dirty = TRUE;
+
        debug_print("Cache size: %d messages, %u bytes\n", g_hash_table_size(cache->msgnum_table), cache->memusage);
 }
 
@@ -189,6 +189,8 @@ void msgcache_remove_msg(MsgCache *cache, guint msgnum)
        procmsg_msginfo_free(msginfo);
        cache->last_access = time(NULL);
 
+       msginfo->folder->cache_dirty = TRUE;
+
        debug_print("Cache size: %d messages, %u bytes\n", g_hash_table_size(cache->msgnum_table), cache->memusage);
 }
 
@@ -217,6 +219,8 @@ void msgcache_update_msg(MsgCache *cache, MsgInfo *msginfo)
        
        debug_print("Cache size: %d messages, %u bytes\n", g_hash_table_size(cache->msgnum_table), cache->memusage);
 
+       msginfo->folder->cache_dirty = TRUE;
+
        return;
 }
 
@@ -775,6 +779,7 @@ bail_err:
 
        debug_print("done. (%d items read)\n", g_hash_table_size(cache->msgnum_table));
        debug_print("Cache size: %d messages, %u bytes\n", g_hash_table_size(cache->msgnum_table), cache->memusage);
+
        return cache;
 }
 
@@ -1002,39 +1007,6 @@ static int msgcache_write_cache(MsgInfo *msginfo, FILE *fp)
        return w_err ? -1 : wrote;
 }
 
-static int msgcache_write_mmap_cache(MsgInfo *msginfo, char *walk_data)
-{
-       MsgTmpFlags flags = msginfo->flags.tmp_flags & MSG_CACHED_FLAG_MASK;
-       GSList *cur;
-       int wrote = 0;
-
-       PUT_CACHE_DATA_INT(msginfo->msgnum);
-       PUT_CACHE_DATA_INT(msginfo->size);
-       PUT_CACHE_DATA_INT(msginfo->mtime);
-       PUT_CACHE_DATA_INT(msginfo->date_t);
-       PUT_CACHE_DATA_INT(flags);
-       PUT_CACHE_DATA(msginfo->fromname);
-
-       PUT_CACHE_DATA(msginfo->date);
-       PUT_CACHE_DATA(msginfo->from);
-       PUT_CACHE_DATA(msginfo->to);
-       PUT_CACHE_DATA(msginfo->cc);
-       PUT_CACHE_DATA(msginfo->newsgroups);
-       PUT_CACHE_DATA(msginfo->subject);
-       PUT_CACHE_DATA(msginfo->msgid);
-       PUT_CACHE_DATA(msginfo->inreplyto);
-       PUT_CACHE_DATA(msginfo->xref);
-       PUT_CACHE_DATA_INT(msginfo->planned_download);
-       PUT_CACHE_DATA_INT(msginfo->total_size);
-        
-       PUT_CACHE_DATA_INT(g_slist_length(msginfo->references));
-
-       for (cur = msginfo->references; cur != NULL; cur = cur->next) {
-               PUT_CACHE_DATA((gchar *)cur->data);
-       }
-       return wrote;
-}
-
 static int msgcache_write_flags(MsgInfo *msginfo, FILE *fp)
 {
        MsgPermFlags flags = msginfo->flags.perm_flags;
@@ -1061,40 +1033,11 @@ static int msgcache_write_tags(MsgInfo *msginfo, FILE *fp)
        return w_err ? -1 : wrote;
 }
 
-static int msgcache_write_mmap_flags(MsgInfo *msginfo, char *walk_data)
-{
-       MsgPermFlags flags = msginfo->flags.perm_flags;
-       int wrote = 0;
-
-       PUT_CACHE_DATA_INT(msginfo->msgnum);
-       PUT_CACHE_DATA_INT(flags);
-       return wrote;
-}
-
-static int msgcache_write_mmap_tags(MsgInfo *msginfo, char *walk_data)
-{
-       GSList *cur = msginfo->tags;
-       int wrote = 0;
-       
-       PUT_CACHE_DATA_INT(msginfo->msgnum);
-       for (; cur; cur = cur->next) {
-               gint id = GPOINTER_TO_INT(cur->data);
-               if (tags_get_tag(id) != NULL) {
-                       PUT_CACHE_DATA_INT(id);
-               }
-       }
-       PUT_CACHE_DATA_INT(-1);
-       return wrote;
-}
-
 struct write_fps
 {
        FILE *cache_fp;
        FILE *mark_fp;
        FILE *tags_fp;
-       char *cache_data;
-       char *mark_data;
-       char *tags_data;
        int error;
        guint cache_size;
        guint mark_size;
@@ -1110,41 +1053,27 @@ static void msgcache_write_func(gpointer key, gpointer value, gpointer user_data
        msginfo = (MsgInfo *)value;
        write_fps = user_data;
 
-       tmp = msgcache_write_cache(msginfo, write_fps->cache_fp);
-       if (tmp < 0)
-               write_fps->error = 1;
-       else
-               write_fps->cache_size += tmp;
+       if (write_fps->cache_fp) {
+               tmp = msgcache_write_cache(msginfo, write_fps->cache_fp);
+               if (tmp < 0)
+                       write_fps->error = 1;
+               else
+                       write_fps->cache_size += tmp;
+       }
+       if (write_fps->mark_fp) {
        tmp= msgcache_write_flags(msginfo, write_fps->mark_fp);
-       if (tmp < 0)
-               write_fps->error = 1;
-       else
-               write_fps->mark_size += tmp;
-       tmp = msgcache_write_tags(msginfo, write_fps->tags_fp);
-       if (tmp < 0)
-               write_fps->error = 1;
-       else
-               write_fps->tags_size += tmp;
-}
-
-static void msgcache_write_mmap_func(gpointer key, gpointer value, gpointer user_data)
-{
-       MsgInfo *msginfo;
-       struct write_fps *write_fps;
-       int tmp;
-
-       msginfo = (MsgInfo *)value;
-       write_fps = user_data;
-
-       tmp = msgcache_write_mmap_cache(msginfo, write_fps->cache_data);
-       write_fps->cache_size += tmp;
-       write_fps->cache_data += tmp;
-       tmp = msgcache_write_mmap_flags(msginfo, write_fps->mark_data);
-       write_fps->mark_size += tmp;
-       write_fps->mark_data += tmp;
-       tmp = msgcache_write_mmap_tags(msginfo, write_fps->tags_data);
-       write_fps->tags_size += tmp;
-       write_fps->tags_data += tmp;
+               if (tmp < 0)
+                       write_fps->error = 1;
+               else
+                       write_fps->mark_size += tmp;
+               }
+       if (write_fps->tags_fp) {
+               tmp = msgcache_write_tags(msginfo, write_fps->tags_fp);
+               if (tmp < 0)
+                       write_fps->error = 1;
+               else
+                       write_fps->tags_size += tmp;
+       }
 }
 
 gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar *tags_file, MsgCache *cache)
@@ -1152,15 +1081,8 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
        struct write_fps write_fps;
        gchar *new_cache, *new_mark, *new_tags;
        int w_err = 0, wrote = 0;
-       gint map_len = -1;
-       char *cache_data = NULL;
-       char *mark_data = NULL;
-       char *tags_data = NULL;
 
        START_TIMING("");
-       cm_return_val_if_fail(cache_file != NULL, -1);
-       cm_return_val_if_fail(mark_file != NULL, -1);
-       cm_return_val_if_fail(tags_file != NULL, -1);
        cm_return_val_if_fail(cache != NULL, -1);
 
        new_cache = g_strconcat(cache_file, ".new", NULL);
@@ -1172,16 +1094,21 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
        write_fps.mark_size = 0;
        write_fps.tags_size = 0;
 
-       write_fps.cache_fp = msgcache_open_data_file(new_cache, CACHE_VERSION,
-               DATA_WRITE, NULL, 0);
-       if (write_fps.cache_fp == NULL) {
-               g_free(new_cache);
-               g_free(new_mark);
-               g_free(new_tags);
-               return -1;
-       }
+       /* open files and write headers */
 
-       WRITE_CACHE_DATA(CS_UTF_8, write_fps.cache_fp);
+       if (cache_file) {
+               write_fps.cache_fp = msgcache_open_data_file(new_cache, CACHE_VERSION,
+                       DATA_WRITE, NULL, 0);
+               if (write_fps.cache_fp == NULL) {
+                       g_free(new_cache);
+                       g_free(new_mark);
+                       g_free(new_tags);
+                       return -1;
+               }
+               WRITE_CACHE_DATA(CS_UTF_8, write_fps.cache_fp);
+       } else {
+               write_fps.cache_fp = NULL;
+       }
 
        if (w_err != 0) {
                g_warning("failed to write charset\n");
@@ -1193,170 +1120,98 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
                return -1;
        }
 
-       write_fps.mark_fp = msgcache_open_data_file(new_mark, MARK_VERSION,
-               DATA_WRITE, NULL, 0);
-       if (write_fps.mark_fp == NULL) {
-               fclose(write_fps.cache_fp);
-               claws_unlink(new_cache);
-               g_free(new_cache);
-               g_free(new_mark);
-               g_free(new_tags);
-               return -1;
+       if (mark_file) {
+               write_fps.mark_fp = msgcache_open_data_file(new_mark, MARK_VERSION,
+                       DATA_WRITE, NULL, 0);
+               if (write_fps.mark_fp == NULL) {
+                       fclose(write_fps.cache_fp);
+                       claws_unlink(new_cache);
+                       g_free(new_cache);
+                       g_free(new_mark);
+                       g_free(new_tags);
+                       return -1;
+               }
+       } else {
+               write_fps.mark_fp = NULL;
        }
 
-       write_fps.tags_fp = msgcache_open_data_file(new_tags, TAGS_VERSION,
-               DATA_WRITE, NULL, 0);
-       if (write_fps.tags_fp == NULL) {
-               fclose(write_fps.cache_fp);
-               fclose(write_fps.mark_fp);
-               claws_unlink(new_cache);
-               claws_unlink(new_mark);
-               g_free(new_cache);
-               g_free(new_mark);
-               g_free(new_tags);
-               return -1;
+       if (tags_file) {
+               write_fps.tags_fp = msgcache_open_data_file(new_tags, TAGS_VERSION,
+                       DATA_WRITE, NULL, 0);
+               if (write_fps.tags_fp == NULL) {
+                       fclose(write_fps.cache_fp);
+                       fclose(write_fps.mark_fp);
+                       claws_unlink(new_cache);
+                       claws_unlink(new_mark);
+                       g_free(new_cache);
+                       g_free(new_mark);
+                       g_free(new_tags);
+                       return -1;
+               }
+       } else {
+               write_fps.tags_fp = NULL;
        }
 
        debug_print("\tWriting message cache to %s and %s...\n", new_cache, new_mark);
 
-       if (change_file_mode_rw(write_fps.cache_fp, new_cache) < 0)
+       if (write_fps.cache_fp && change_file_mode_rw(write_fps.cache_fp, new_cache) < 0)
                FILE_OP_ERROR(new_cache, "chmod");
 
-       write_fps.cache_size = ftell(write_fps.cache_fp);
-       write_fps.mark_size = ftell(write_fps.mark_fp);
-       write_fps.tags_size = ftell(write_fps.tags_fp);
-
-       if (msgcache_use_mmap_write && cache->memusage > 0) {
-               map_len = cache->memusage;
-               if (ftruncate(fileno(write_fps.cache_fp), (off_t)map_len) == 0) {
+       /* headers written, note file size */
+       if (write_fps.cache_fp)
+               write_fps.cache_size = ftell(write_fps.cache_fp);
+       if (write_fps.mark_fp)
+               write_fps.mark_size = ftell(write_fps.mark_fp);
+       if (write_fps.tags_fp)
+               write_fps.tags_size = ftell(write_fps.tags_fp);
 
-#ifdef G_OS_WIN32
-                       cache_data = NULL;
-                       HANDLE hFile, hMapping;
-                       hFile = (HANDLE) _get_osfhandle (fileno(write_fps.cache_fp));
-                       if (hFile == (HANDLE) -1)
-                               goto w32_fail3;
-                       hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
-                       if (!hMapping)
-                               goto w32_fail3;
-                       cache_data = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_COPY, 0, 0, 0);
-                       CloseHandle (hMapping);
-               w32_fail3:
-                       ;
-#else
-                       cache_data = mmap(NULL, map_len, PROT_WRITE, MAP_SHARED, 
-                               fileno(write_fps.cache_fp), 0);
-#endif
-               }
-               if (cache_data != NULL && cache_data != MAP_FAILED) {
-                       if (ftruncate(fileno(write_fps.mark_fp), (off_t)map_len) == 0) {
-#ifdef G_OS_WIN32
-                               mark_data = NULL;
-                               HANDLE hFile, hMapping;
-                               hFile = (HANDLE) _get_osfhandle (fileno(write_fps.mark_fp));
-                               if (hFile == (HANDLE) -1)
-                                       goto w32_fail4;
-                               hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
-                               if (!hMapping)
-                                       goto w32_fail4;
-                               mark_data = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_COPY, 0, 0, 0);
-                               CloseHandle (hMapping);
-                       w32_fail4:
-                               ;
-#else
-                               mark_data = mmap(NULL, map_len, PROT_WRITE, MAP_SHARED, 
-                                       fileno(write_fps.mark_fp), 0);
-#endif
-                       } 
-                       if (mark_data == NULL || mark_data == MAP_FAILED) {
-#ifdef G_OS_WIN32
-                               UnmapViewOfFile((void*) cache_data);
-#else
-                               munmap(cache_data, map_len);
-#endif
-                               cache_data = NULL;
-                       } else {
-                               if (ftruncate(fileno(write_fps.tags_fp), (off_t)map_len) == 0) {
-#ifdef G_OS_WIN32
-                                               tags_data = NULL;
-                                               HANDLE hFile, hMapping;
-                                               hFile = (HANDLE) _get_osfhandle (fileno(write_fps.tags_fp));
-                                               if (hFile == (HANDLE) -1)
-                                                       goto w32_fail5;
-                                               hMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL);
-                                               if (!hMapping)
-                                                       goto w32_fail5;
-                                               tags_data = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_COPY, 0, 0, 0);
-                                               CloseHandle (hMapping);
-                                       w32_fail5:
-                                               ;
-#else
-                                       tags_data = mmap(NULL, map_len, PROT_WRITE, MAP_SHARED, 
-                                               fileno(write_fps.tags_fp), 0);
-#endif
-                               } 
-                               if (tags_data == NULL || tags_data == MAP_FAILED) {
-#ifdef G_OS_WIN32
-                                       UnmapViewOfFile((void*) cache_data);
-                                       UnmapViewOfFile((void*) mark_data);
-#else
-                                       munmap(cache_data, map_len);
-                                       munmap(mark_data, map_len);
-#endif
-                                       cache_data = NULL;
-                                       mark_data = NULL;
-                               } 
-                       }
-               }
-       }
-
-       if (cache_data != NULL && cache_data != MAP_FAILED) {
-               write_fps.cache_data = cache_data + ftell(write_fps.cache_fp);
-               write_fps.mark_data = mark_data + ftell(write_fps.mark_fp);
-               write_fps.tags_data = mark_data + ftell(write_fps.tags_fp);
-               g_hash_table_foreach(cache->msgnum_table, msgcache_write_mmap_func, (gpointer)&write_fps);
-#ifdef G_OS_WIN32
-               UnmapViewOfFile((void*) cache_data);
-               UnmapViewOfFile((void*) mark_data);
-               UnmapViewOfFile((void*) tags_data);
-#else
-               munmap(cache_data, map_len);
-               munmap(mark_data, map_len);
-               munmap(tags_data, map_len);
-#endif
-               ftruncate(fileno(write_fps.cache_fp), write_fps.cache_size);
-               ftruncate(fileno(write_fps.mark_fp), write_fps.mark_size);
-               ftruncate(fileno(write_fps.tags_fp), write_fps.tags_size);
-       } else {
 #ifdef HAVE_FWRITE_UNLOCKED
+       /* lock files for write once (instead of once per fwrite) */
+       if (write_fps.cache_fp)
                flockfile(write_fps.cache_fp);
+       if (write_fps.mark_fp)
                flockfile(write_fps.mark_fp);
+       if (write_fps.tags_fp)
                flockfile(write_fps.tags_fp);
 #endif
-               g_hash_table_foreach(cache->msgnum_table, msgcache_write_func, (gpointer)&write_fps);
+       /* write data to the files */
+       g_hash_table_foreach(cache->msgnum_table, msgcache_write_func, (gpointer)&write_fps);
 #ifdef HAVE_FWRITE_UNLOCKED
-               funlockfile(write_fps.mark_fp);
+       /* unlock files */
+       if (write_fps.cache_fp)
                funlockfile(write_fps.cache_fp);
+       if (write_fps.mark_fp)
+               funlockfile(write_fps.mark_fp);
+       if (write_fps.tags_fp)
                funlockfile(write_fps.tags_fp);
 #endif
-       }
-       
-       fflush(write_fps.cache_fp);
-       fflush(write_fps.mark_fp);
-       fflush(write_fps.tags_fp);
-
-#if 0
-       fsync(fileno(write_fps.cache_fp));
-       fsync(fileno(write_fps.mark_fp));
-       fsync(fileno(write_fps.tags_fp));
-#endif
-
-       fclose(write_fps.cache_fp);
-       fclose(write_fps.mark_fp);
-       fclose(write_fps.tags_fp);
+       /* flush buffers */
+       if (write_fps.cache_fp)
+               write_fps.error |= (fflush(write_fps.cache_fp) != 0);
+       if (write_fps.mark_fp)
+               write_fps.error |= (fflush(write_fps.mark_fp) != 0);
+       if (write_fps.tags_fp)
+               write_fps.error |= (fflush(write_fps.tags_fp) != 0);
+
+       /* sync to filesystem */
+       if (write_fps.cache_fp)
+               write_fps.error |= (fsync(fileno(write_fps.cache_fp)) != 0);
+       if (write_fps.mark_fp)
+               write_fps.error |= (fsync(fileno(write_fps.mark_fp)) != 0);
+       if (write_fps.tags_fp)
+               write_fps.error |= (fsync(fileno(write_fps.tags_fp)) != 0);
+
+       /* close files */
+       if (write_fps.cache_fp)
+               write_fps.error |= (fclose(write_fps.cache_fp) != 0);
+       if (write_fps.mark_fp)
+               write_fps.error |= (fclose(write_fps.mark_fp) != 0);
+       if (write_fps.tags_fp)
+               write_fps.error |= (fclose(write_fps.tags_fp) != 0);
 
 
        if (write_fps.error != 0) {
+               /* in case of error, forget all */
                claws_unlink(new_cache);
                claws_unlink(new_mark);
                claws_unlink(new_tags);
@@ -1365,9 +1220,13 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
                g_free(new_tags);
                return -1;
        } else {
-               move_file(new_cache, cache_file, TRUE);
-               move_file(new_mark, mark_file, TRUE);
-               move_file(new_tags, tags_file, TRUE);
+               /* switch files */
+               if (cache_file)
+                       move_file(new_cache, cache_file, TRUE);
+               if (mark_file)
+                       move_file(new_mark, mark_file, TRUE);
+               if (tags_file)
+                       move_file(new_tags, tags_file, TRUE);
                cache->last_access = time(NULL);
        }