*
* 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "defs.h"
#include "procmsg.h"
#include "codeconv.h"
+#if G_BYTE_ORDER == G_BIG_ENDIAN
+#define bswap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+#else
+#define bswap_32(x) (x)
+#endif
+
+static gboolean swapping = TRUE;
+
typedef enum
{
DATA_READ,
* Cache saving functions
*/
-#define READ_CACHE_DATA(data, fp) \
+#define READ_CACHE_DATA(data, fp, total_len) \
{ \
- if (msgcache_read_cache_data_str(fp, &data, conv) < 0) { \
+ if ((tmp_len = msgcache_read_cache_data_str(fp, &data, conv)) < 0) { \
procmsg_msginfo_free(msginfo); \
error = TRUE; \
break; \
} \
+ total_len += tmp_len; \
}
#define READ_CACHE_DATA_INT(n, fp) \
guint32 idata; \
size_t ni; \
\
- if ((ni = fread(&idata, 1, sizeof(idata), fp)) != sizeof(idata)) { \
+ if ((ni = fread(&idata, sizeof(idata), 1, fp)) != 1) { \
g_warning("read_int: Cache data corrupted, read %d of %d at " \
- "offset %d\n", ni, sizeof(idata), ftell(fp)); \
+ "offset %ld\n", ni, sizeof(idata), ftell(fp)); \
procmsg_msginfo_free(msginfo); \
error = TRUE; \
break; \
} else \
- n = idata;\
+ n = swapping ? bswap_32(idata) : (idata);\
}
#define WRITE_CACHE_DATA_INT(n, fp) \
{ \
guint32 idata; \
\
- idata = (guint32)n; \
+ idata = (guint32)bswap_32(n); \
fwrite(&idata, sizeof(idata), 1, fp); \
}
g_return_val_if_fail(file != NULL, NULL);
if (mode == DATA_WRITE) {
- if ((fp = fopen(file, "wb")) == NULL) {
+ if ((fp = g_fopen(file, "wb")) == NULL) {
FILE_OP_ERROR(file, "fopen");
return NULL;
}
}
/* check version */
- if ((fp = fopen(file, "rb")) == NULL)
+ if ((fp = g_fopen(file, "rb")) == NULL)
debug_print("Mark/Cache file '%s' not found\n", file);
else {
if (buf && buf_size > 0)
setvbuf(fp, buf, _IOFBF, buf_size);
if (fread(&data_ver, sizeof(data_ver), 1, fp) != 1 ||
- version != data_ver) {
- g_message("%s: Mark/Cache version is different (%u != %u). Discarding it.\n",
- file, data_ver, version);
+ version != bswap_32(data_ver)) {
+ g_message("%s: Mark/Cache version is different (%u != %u).\n",
+ file, bswap_32(data_ver), version);
fclose(fp);
fp = NULL;
}
+ data_ver = bswap_32(data_ver);
}
-
+
if (mode == DATA_READ)
return fp;
if (fp) {
/* reopen with append mode */
fclose(fp);
- if ((fp = fopen(file, "ab")) == NULL)
+ if ((fp = g_fopen(file, "ab")) == NULL)
FILE_OP_ERROR(file, "fopen");
} else {
/* open with overwrite mode if mark file doesn't exist or
guint32 len;
*str = NULL;
- if ((ni = fread(&len, 1, sizeof(len), fp) != sizeof(len)) ||
- len > G_MAXINT) {
- g_warning("read_data_str: Cache data (len) corrupted, read %d "
- "of %d bytes at offset %d\n", ni, sizeof(len),
- ftell(fp));
- return -1;
+ if (!swapping) {
+ if ((ni = fread(&len, sizeof(len), 1, fp) != 1) ||
+ len > G_MAXINT) {
+ g_warning("read_data_str: Cache data (len) corrupted, read %d "
+ "of %d bytes at offset %ld\n", ni, sizeof(len),
+ ftell(fp));
+ return -1;
+ }
+ } else {
+ if ((ni = fread(&len, sizeof(len), 1, fp) != 1) ||
+ bswap_32(len) > G_MAXINT) {
+ g_warning("read_data_str: Cache data (len) corrupted, read %d "
+ "of %d bytes at offset %ld\n", ni, sizeof(len),
+ ftell(fp));
+ return -1;
+ }
+ len = bswap_32(len);
}
if (len == 0)
if ((ni = fread(tmpstr, 1, len, fp)) != len) {
g_warning("read_data_str: Cache data corrupted, read %d of %d "
- "bytes at offset %d\n",
+ "bytes at offset %ld\n",
ni, len, ftell(fp));
g_free(tmpstr);
return -1;
} else
*str = tmpstr;
- return 0;
+ return len;
}
gchar *strconv_strdup_convert(StringConverter *conv, gchar *srcstr)
StringConverter *conv = NULL;
gchar *srccharset = NULL;
const gchar *dstcharset = NULL;
-
+ gchar *ref = NULL;
+ guint memusage = 0;
+ guint tmp_len = 0;
+#if 0
+ struct timeval start;
+ struct timeval end;
+ struct timeval diff;
+ gettimeofday(&start, NULL);
+#endif
g_return_val_if_fail(cache_file != NULL, NULL);
g_return_val_if_fail(item != NULL, NULL);
+ swapping = TRUE;
+
+ /* In case we can't open the mark file with MARK_VERSION, check if we can open it with the
+ * swapped MARK_VERSION. As msgcache_open_data_file swaps it too, if this succeeds,
+ * it means it's the old version (not little-endian) on a big-endian machine. The code has
+ * no effect on x86 as their file doesn't change. */
+
if ((fp = msgcache_open_data_file
- (cache_file, CACHE_VERSION, DATA_READ, file_buf, sizeof(file_buf))) == NULL)
- return NULL;
+ (cache_file, CACHE_VERSION, DATA_READ, file_buf, sizeof(file_buf))) == NULL) {
+ if ((fp = msgcache_open_data_file
+ (cache_file, bswap_32(CACHE_VERSION), DATA_READ, file_buf, sizeof(file_buf))) == NULL)
+ return NULL;
+ else
+ swapping = FALSE;
+ }
- debug_print("\tReading message cache from %s...\n", cache_file);
+ debug_print("\tReading %sswapped message cache from %s...\n", swapping?"":"un", cache_file);
- if (item->stype == F_QUEUE) {
+ if (folder_has_parent_of_type(item, F_QUEUE)) {
tmp_flags |= MSG_QUEUED;
- } else if (item->stype == F_DRAFT) {
+ } else if (folder_has_parent_of_type(item, F_DRAFT)) {
tmp_flags |= MSG_DRAFT;
}
if (srccharset == NULL || dstcharset == NULL) {
conv = NULL;
} else if (strcmp(srccharset, dstcharset) == 0) {
- StrdupConverter *strdupconv;
-
- debug_print("using StrdupConverter\n");
-
- strdupconv = g_new0(StrdupConverter, 1);
- strdupconv->converter.convert = strconv_strdup_convert;
- strdupconv->converter.free = NULL;
+ debug_print("using Noop Converter\n");
- conv = (StringConverter *) strdupconv;
+ conv = NULL;
} else {
CharsetConverter *charsetconv;
g_free(srccharset);
cache = msgcache_new();
- g_hash_table_freeze(cache->msgnum_table);
while (fread(&num, sizeof(num), 1, fp) == 1) {
+ if (swapping)
+ num = bswap_32(num);
+
msginfo = procmsg_msginfo_new();
msginfo->msgnum = num;
+ memusage += sizeof(MsgInfo);
+
READ_CACHE_DATA_INT(msginfo->size, fp);
READ_CACHE_DATA_INT(msginfo->mtime, fp);
READ_CACHE_DATA_INT(msginfo->date_t, fp);
READ_CACHE_DATA_INT(msginfo->flags.tmp_flags, fp);
-
- READ_CACHE_DATA(msginfo->fromname, fp);
-
- READ_CACHE_DATA(msginfo->date, fp);
- READ_CACHE_DATA(msginfo->from, fp);
- READ_CACHE_DATA(msginfo->to, fp);
- READ_CACHE_DATA(msginfo->cc, fp);
- READ_CACHE_DATA(msginfo->newsgroups, fp);
- READ_CACHE_DATA(msginfo->subject, fp);
- READ_CACHE_DATA(msginfo->msgid, fp);
- READ_CACHE_DATA(msginfo->inreplyto, fp);
- READ_CACHE_DATA(msginfo->xref, fp);
+
+ READ_CACHE_DATA(msginfo->fromname, fp, memusage);
+
+ READ_CACHE_DATA(msginfo->date, fp, memusage);
+ READ_CACHE_DATA(msginfo->from, fp, memusage);
+ READ_CACHE_DATA(msginfo->to, fp, memusage);
+ READ_CACHE_DATA(msginfo->cc, fp, memusage);
+ READ_CACHE_DATA(msginfo->newsgroups, fp, memusage);
+ READ_CACHE_DATA(msginfo->subject, fp, memusage);
+ READ_CACHE_DATA(msginfo->msgid, fp, memusage);
+ READ_CACHE_DATA(msginfo->inreplyto, fp, memusage);
+ READ_CACHE_DATA(msginfo->xref, fp, memusage);
+
READ_CACHE_DATA_INT(msginfo->planned_download, fp);
READ_CACHE_DATA_INT(msginfo->total_size, fp);
-
READ_CACHE_DATA_INT(refnum, fp);
+
for (; refnum != 0; refnum--) {
- gchar *ref;
+ ref = NULL;
- READ_CACHE_DATA(ref, fp);
- msginfo->references =
- g_slist_prepend(msginfo->references, ref);
+ READ_CACHE_DATA(ref, fp, memusage);
+
+ if (ref && strlen(ref))
+ msginfo->references =
+ g_slist_prepend(msginfo->references, ref);
}
if (msginfo->references)
msginfo->references =
g_hash_table_insert(cache->msgnum_table, &msginfo->msgnum, msginfo);
if(msginfo->msgid)
g_hash_table_insert(cache->msgid_table, msginfo->msgid, msginfo);
- cache->memusage += procmsg_msginfo_memusage(msginfo);
}
fclose(fp);
- g_hash_table_thaw(cache->msgnum_table);
if (conv != NULL) {
if (conv->free != NULL)
}
cache->last_access = time(NULL);
+ cache->memusage = memusage;
debug_print("done. (%d items read)\n", g_hash_table_size(cache->msgnum_table));
debug_print("Cache size: %d messages, %d byte\n", g_hash_table_size(cache->msgnum_table), cache->memusage);
-
+#if 0
+ gettimeofday(&end, NULL);
+ timersub(&end, &start, &diff);
+ printf("spent %d seconds %d usages %d;%d\n", diff.tv_sec, diff.tv_usec, cache->memusage, memusage);
+#endif
return cache;
}
MsgInfo *msginfo;
MsgPermFlags perm_flags;
guint32 num;
-
- if ((fp = msgcache_open_data_file(mark_file, MARK_VERSION, DATA_READ, NULL, 0)) == NULL)
- return;
-
- debug_print("\tReading message marks from %s...\n", mark_file);
-
+
+ swapping = TRUE;
+
+ /* In case we can't open the mark file with MARK_VERSION, check if we can open it with the
+ * swapped MARK_VERSION. As msgcache_open_data_file swaps it too, if this succeeds,
+ * it means it's the old version (not little-endian) on a big-endian machine. The code has
+ * no effect on x86 as their file doesn't change. */
+
+ if ((fp = msgcache_open_data_file(mark_file, MARK_VERSION, DATA_READ, NULL, 0)) == NULL) {
+ /* see if it isn't swapped ? */
+ if ((fp = msgcache_open_data_file(mark_file, bswap_32(MARK_VERSION), DATA_READ, NULL, 0)) == NULL)
+ return;
+ else
+ swapping = FALSE; /* yay */
+ }
+ debug_print("reading %sswapped mark file.\n", swapping?"":"un");
while (fread(&num, sizeof(num), 1, fp) == 1) {
+ if (swapping)
+ num = bswap_32(num);
if (fread(&perm_flags, sizeof(perm_flags), 1, fp) != 1) break;
-
+ if (swapping)
+ perm_flags = bswap_32(perm_flags);
msginfo = g_hash_table_lookup(cache->msgnum_table, &num);
if(msginfo) {
msginfo->flags.perm_flags = perm_flags;
}
- }
+ }
fclose(fp);
}
WRITE_CACHE_DATA_INT(msginfo->total_size, fp);
WRITE_CACHE_DATA_INT(g_slist_length(msginfo->references), fp);
+
for (cur = msginfo->references; cur != NULL; cur = cur->next) {
WRITE_CACHE_DATA((gchar *)cur->data, fp);
}