2007-08-13 [wwp] 2.10.0cvs118
[claws.git] / src / msgcache.c
index 0ee9da9687e92f65e55c72aa994ada3fa4c89461..84bdb67145090e7995b4780b58e7e0299f33ee1f 100644 (file)
@@ -4,7 +4,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * the Free Software Foundation; either version 3 of the License, or
  * (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful,
@@ -13,8 +13,8 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * 
  */
 
 #ifdef HAVE_CONFIG_H
 
 #include <glib.h>
 #include <glib/gi18n.h>
-#include <sys/mman.h>
+#ifdef _WIN32
+# include <w32lib.h>
+# define MAP_FAILED    ((char *) -1)
+#else
+# include <sys/mman.h>
+#endif
 #include <sys/types.h>
 #include <sys/stat.h>
 
@@ -390,7 +395,7 @@ static FILE *msgcache_open_data_file(const gchar *file, guint version,
 
        if (mode == DATA_WRITE) {
                int w_err = 0, wrote = 0;
-               if ((fp = g_fopen(file, "w+")) == NULL) {
+               if ((fp = g_fopen(file, "wb")) == NULL) {
                        FILE_OP_ERROR(file, "fopen");
                        return NULL;
                }
@@ -591,8 +596,10 @@ MsgCache *msgcache_read_cache(FolderItem *item, const gchar *cache_file)
                tmp_flags |= MSG_DRAFT;
        }
 
-       if (msgcache_read_cache_data_str(fp, &srccharset, NULL) < 0)
+       if (msgcache_read_cache_data_str(fp, &srccharset, NULL) < 0) {
+               fclose(fp);
                return NULL;
+       }
        dstcharset = CS_UTF_8;
        if (srccharset == NULL || dstcharset == NULL) {
                conv = NULL;
@@ -622,8 +629,24 @@ MsgCache *msgcache_read_cache(FolderItem *item, const gchar *cache_file)
                        map_len = st.st_size;
                else
                        map_len = -1;
-               if (map_len > 0)
+               if (map_len > 0) {
+#ifdef G_OS_WIN32
+                       cache_data = NULL;
+                       HANDLE hFile, hMapping;
+                       hFile = (HANDLE) _get_osfhandle (fileno(fp));
+                       if (hFile == (HANDLE) -1)
+                               goto w32_fail;
+                       hMapping = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL);
+                       if (!hMapping)
+                               goto w32_fail;
+                       cache_data = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_COPY, 0, 0, 0);
+                       CloseHandle (hMapping);
+               w32_fail:
+                       ;
+#else
                        cache_data = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE, fileno(fp), 0);
+#endif
+               }
        } else {
                cache_data = NULL;
        }
@@ -679,8 +702,12 @@ MsgCache *msgcache_read_cache(FolderItem *item, const gchar *cache_file)
                        if(msginfo->msgid)
                                g_hash_table_insert(cache->msgid_table, msginfo->msgid, msginfo);
                }
-               
+
+#ifdef G_OS_WIN32
+               UnmapViewOfFile((void*) cache_data);
+#else
                munmap(cache_data, map_len);
+#endif
        } else {
                while (fread(&num, sizeof(num), 1, fp) == 1) {
                        if (swapping)
@@ -785,8 +812,24 @@ void msgcache_read_mark(MsgCache *cache, const gchar *mark_file)
                        map_len = st.st_size;
                else
                        map_len = -1;
-               if (map_len > 0)
+               if (map_len > 0) {
+#ifdef G_OS_WIN32
+                       cache_data = NULL;
+                       HANDLE hFile, hMapping;
+                       hFile = (HANDLE) _get_osfhandle (fileno(fp));
+                       if (hFile == (HANDLE) -1)
+                               goto w32_fail2;
+                       hMapping = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL);
+                       if (!hMapping)
+                               goto w32_fail2;
+                       cache_data = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_COPY, 0, 0, 0);
+                       CloseHandle (hMapping);
+               w32_fail2:
+                       ;
+#else
                        cache_data = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE, fileno(fp), 0);
+#endif
+               }
        } else {
                cache_data = NULL;
        }
@@ -802,7 +845,11 @@ void msgcache_read_mark(MsgCache *cache, const gchar *mark_file)
                                msginfo->flags.perm_flags = perm_flags;
                        }
                }
+#ifdef G_OS_WIN32
+               UnmapViewOfFile((void*) cache_data);
+#else
                munmap(cache_data, map_len);
+#endif
        } else {
                while (fread(&num, sizeof(num), 1, fp) == 1) {
                        if (swapping)
@@ -849,8 +896,24 @@ void msgcache_read_tags(MsgCache *cache, const gchar *tags_file)
                        map_len = st.st_size;
                else
                        map_len = -1;
-               if (map_len > 0)
+               if (map_len > 0) {
+#ifdef G_OS_WIN32
+                       cache_data = NULL;
+                       HANDLE hFile, hMapping;
+                       hFile = (HANDLE) _get_osfhandle (fileno(fp));
+                       if (hFile == (HANDLE) -1)
+                               goto w32_fail6;
+                       hMapping = CreateFileMapping(hFile, NULL, PAGE_WRITECOPY, 0, 0, NULL);
+                       if (!hMapping)
+                               goto w32_fail6;
+                       cache_data = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_COPY, 0, 0, 0);
+                       CloseHandle (hMapping);
+               w32_fail6:
+                       ;
+#else
                        cache_data = mmap(NULL, map_len, PROT_READ, MAP_PRIVATE, fileno(fp), 0);
+#endif
+               }
        } else {
                cache_data = NULL;
        }
@@ -876,7 +939,11 @@ void msgcache_read_tags(MsgCache *cache, const gchar *tags_file)
                                msginfo->tags = g_slist_reverse(msginfo->tags);
                        }
                }
+#ifdef G_OS_WIN32
+               UnmapViewOfFile((void*) cache_data);
+#else
                munmap(cache_data, map_len);
+#endif
        } else {
                while (fread(&num, sizeof(num), 1, fp) == 1) {
                        gint id = -1;
@@ -1113,6 +1180,7 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
        if (write_fps.cache_fp == NULL) {
                g_free(new_cache);
                g_free(new_mark);
+               g_free(new_tags);
                return -1;
        }
 
@@ -1164,26 +1232,81 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
        if (msgcache_use_mmap_write && cache->memusage > 0) {
                map_len = cache->memusage;
                if (ftruncate(fileno(write_fps.cache_fp), (off_t)map_len) == 0) {
+
+#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);
-                                       cache_data = NULL;
                                        munmap(mark_data, map_len);
+#endif
+                                       cache_data = NULL;
                                        mark_data = NULL;
                                } 
                        }
@@ -1195,9 +1318,15 @@ gint msgcache_write(const gchar *cache_file, const gchar *mark_file, const gchar
                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);