[prev in list] [next in list] [prev in thread] [next in thread]
List: kmail-devel
Subject: Re: kmail under Solaris and Linux
From: Waldo Bastian <bastian () kde ! org>
Date: 2002-02-02 6:11:48
[Download RAW message or body]
On Thursday 31 January 2002 11:02 pm, Michael Häckel wrote:
> On Thursday 31 January 2002 23:00:23, Waldo Bastian wrote:
> > Can't we add a byte-order indicator at the start of the index file? Then,
> > when the byte order doesn't match we can use a slower compatibility
> > function that fixes the byte order. In 99.9% of the cases this will not
> > be needed but when it is needed it wil be used automagically and hassle
> > free.
> >
> > I can make a patch for it if you like the idea.
>
> This is not only required for the index file but also for the sorted and
> serial number files.
Ok... the previous version screwed up the .ids files rather badly.... this one
should be better.
Cheers,
Waldo
--
bastian@kde.org | SuSE Labs KDE Developer | bastian@suse.com
["kmail.portable2.patch" (text/x-diff)]
Index: kmfolder.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmfolder.cpp,v
retrieving revision 1.215
diff -u -r1.215 kmfolder.cpp
--- kmfolder.cpp 2002/01/20 22:20:08 1.215
+++ kmfolder.cpp 2002/02/02 06:08:06
@@ -22,6 +22,7 @@
#include <errno.h>
#include <assert.h>
#include <unistd.h>
+#include <endian.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
@@ -31,6 +32,22 @@
#include <fcntl.h>
#endif
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+// We define functions as kmail_swap_NN so that we don't get compile errors
+// on platforms where bswap_NN happens to be a function instead of a define.
+
+/* Swap bytes in 32 bit value. */
+#ifdef bswap_32
+#define kmail_swap_32(x) bswap_32(x)
+#else
+#define kmail_swap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+#endif
+
//#define HAVE_MMAP //need to get this into autoconf FIXME --Sam
#ifdef HAVE_MMAP
#include <unistd.h>
@@ -83,6 +100,8 @@
mIndexId = -1;
mIndexStreamPtr = NULL;
mIndexStreamPtrLength = 0;
+ mIndexSwapByteOrder = false;
+ mIndexSizeOfLong = sizeof(long);
mCompactable = TRUE;
mNoContent = FALSE;
expireMessages = FALSE;
@@ -220,11 +239,20 @@
return errno;
fprintf(tmpIndexStream, "# KMail-Index V%d\n", INDEX_VERSION);
+
+ // Header
+ Q_UINT32 byteOrder = 0x12345678;
+ Q_UINT32 sizeOfLong = sizeof(long);
+
+ Q_UINT32 header_length = sizeof(byteOrder)+sizeof(sizeOfLong);
char pad_char = '\0';
- int header_length = 0; // Reserved for future expansion
fwrite(&pad_char, sizeof(pad_char), 1, tmpIndexStream);
fwrite(&header_length, sizeof(header_length), 1, tmpIndexStream);
+ // Write header
+ fwrite(&byteOrder, sizeof(byteOrder), 1, tmpIndexStream);
+ fwrite(&sizeOfLong, sizeof(sizeOfLong), 1, tmpIndexStream);
+
long nho = ftell(tmpIndexStream);
for (i=0; i<mMsgList.high(); i++)
{
@@ -269,6 +297,8 @@
{
int indexVersion;
assert(mIndexStream != NULL);
+ mIndexSwapByteOrder = false;
+ mIndexSizeOfLong = sizeof(long);
fscanf(mIndexStream, "# KMail-Index V%d\n", &indexVersion);
if(gv)
@@ -280,7 +310,6 @@
}
return TRUE;
} else if (indexVersion == 1505) {
- fseek(mIndexStream, sizeof(char), SEEK_CUR );
} else if (indexVersion < INDEX_VERSION) {
kdDebug(5006) << "Index file " << indexLocation() << " is out of date. \
Re-creating it." << endl; createIndexFromContents();
@@ -299,10 +328,42 @@
return FALSE;
}
else {
- int header_length = 0;
+ // Header
+ Q_UINT32 byteOrder = 0;
+ Q_UINT32 sizeOfLong = sizeof(long); // default
+
+ Q_UINT32 header_length = 0;
fseek(mIndexStream, sizeof(char), SEEK_CUR );
fread(&header_length, sizeof(header_length), 1, mIndexStream);
- fseek(mIndexStream, header_length, SEEK_CUR );
+ if (header_length > 0xFFFF)
+ header_length = kmail_swap_32(header_length);
+
+ long endOfHeader = ftell(mIndexStream) + header_length;
+qWarning("header_lenght = %d", header_length);
+
+ // Process available header parts
+ if (header_length >= sizeof(byteOrder))
+ {
+ fread(&byteOrder, sizeof(byteOrder), 1, mIndexStream);
+ mIndexSwapByteOrder = (byteOrder == 0x78563412);
+ header_length -= sizeof(byteOrder);
+
+ if (header_length >= sizeof(sizeOfLong))
+ {
+ fread(&sizeOfLong, sizeof(sizeOfLong), 1, mIndexStream);
+ mIndexSizeOfLong = sizeOfLong;
+ header_length -= sizeof(sizeOfLong);
+ }
+ }
+
+ // Seek to end of header
+ fseek(mIndexStream, endOfHeader, SEEK_SET );
+
+ if (mIndexSwapByteOrder)
+ kdDebug(5006) << "Index File has byte order swapped!" << endl;
+ if (mIndexSizeOfLong != sizeof(long))
+ kdDebug(5006) << "Index File sizeOfLong is " << mIndexSizeOfLong << " while \
sizeof(long) is " << sizeof(long) << " !" << endl; +
}
return TRUE;
}
@@ -311,7 +372,8 @@
//-----------------------------------------------------------------------------
bool KMFolder::readIndex()
{
- int len, offs;
+ Q_INT32 len;
+ int offs;
KMMsgInfo* mi;
assert(mIndexStream != NULL);
@@ -331,10 +393,13 @@
mi = NULL;
if(version >= 1505) {
if(!fread(&len, sizeof(len), 1, mIndexStream))
- break;
+ break;
+ if (mIndexSwapByteOrder)
+ len = kmail_swap_32(len);
+
offs = ftell(mIndexStream);
if(fseek(mIndexStream, len, SEEK_CUR))
- break;
+ break;
mi = new KMMsgInfo(this, offs, len);
} else {
QCString line(MAX_LINE);
Index: kmfolder.h
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmfolder.h,v
retrieving revision 1.79
diff -u -r1.79 kmfolder.h
--- kmfolder.h 2002/01/05 19:57:21 1.79
+++ kmfolder.h 2002/02/02 06:08:08
@@ -306,7 +306,10 @@
/** Returns a string that can be used to identify this folder */
virtual QString idString();
- uchar *indexStreamBasePtr() { return mIndexStreamPtr; }
+ uchar *indexStreamBasePtr() { return mIndexStreamPtr; }
+
+ bool indexSwapByteOrder() { return mIndexSwapByteOrder; }
+ int indexSizeOfLong() { return mIndexSizeOfLong; }
/**
* Set whether this folder automatically expires messages.
@@ -539,6 +542,8 @@
bool mConvertToUtf8;
uchar *mIndexStreamPtr;
int mIndexStreamPtrLength, mIndexId;
+ bool mIndexSwapByteOrder; // Index file was written with swapped byte order
+ int mIndexSizeOfLong; // Index file was written with longs of this size
/** Support for automatic expiry of old messages */
bool expireMessages; // TRUE if old messages are expired
@@ -551,7 +556,6 @@
/** Points at the reverse dictionary for this folder. */
KMMsgDictREntry *mRDict;
-
};
#endif /*kmfolder_h*/
Index: kmheaders.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmheaders.cpp,v
retrieving revision 1.389
diff -u -r1.389 kmheaders.cpp
--- kmheaders.cpp 2002/01/27 10:24:28 1.389
+++ kmheaders.cpp 2002/02/02 06:08:15
@@ -2726,7 +2726,7 @@
}
//Flatten the list and write it to disk
-#define KMAIL_SORT_VERSION 1006
+#define KMAIL_SORT_VERSION 1007
#define KMAIL_SORT_FILE(x) x->indexLocation() + ".sorted"
#define KMAIL_SORT_HEADER "## KMail Sort V%04d\n\t"
#define KMAIL_MAGIC_HEADER_OFFSET 21 //strlen(KMAIL_SORT_HEADER)
@@ -2736,14 +2736,14 @@
{
fwrite(&msgid, sizeof(msgid), 1, sortStream);
fwrite(&parent_id, sizeof(parent_id), 1, sortStream);
- int len = key.length() * 2;
+ Q_INT32 len = key.length() * sizeof(QChar);
fwrite(&len, sizeof(len), 1, sortStream);
if (len)
fwrite(key.unicode(), QMIN(len, KMAIL_MAX_KEY_LEN), 1, sortStream);
if (update_discover) {
//update the discovered change count
- int discovered_count = 0;
+ Q_INT32 discovered_count = 0;
fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);
fread(&discovered_count, sizeof(discovered_count), 1, sortStream);
discovered_count++;
@@ -2773,9 +2773,14 @@
mSortInfo.dirty = FALSE;
fprintf(sortStream, KMAIL_SORT_HEADER, KMAIL_SORT_VERSION);
//magic header information
- int column = mSortCol, ascending=!mSortDescending;
- int threaded = (mNested != mNestedOverride);
- int discovered_count = 0, sorted_count=0, appended=0;
+ Q_INT32 byteOrder = 0x12345678;
+ Q_INT32 column = mSortCol;
+ Q_INT32 ascending= !mSortDescending;
+ Q_INT32 threaded = (mNested != mNestedOverride);
+ Q_INT32 appended=0;
+ Q_INT32 discovered_count = 0;
+ Q_INT32 sorted_count=0;
+ fwrite(&byteOrder, sizeof(byteOrder), 1, sortStream);
fwrite(&column, sizeof(column), 1, sortStream);
fwrite(&ascending, sizeof(ascending), 1, sortStream);
fwrite(&threaded, sizeof(threaded), 1, sortStream);
@@ -2832,6 +2837,7 @@
//magic header twice, case they've changed
fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET, SEEK_SET);
+ fwrite(&byteOrder, sizeof(byteOrder), 1, sortStream);
fwrite(&column, sizeof(column), 1, sortStream);
fwrite(&ascending, sizeof(ascending), 1, sortStream);
fwrite(&threaded, sizeof(threaded), 1, sortStream);
@@ -2867,8 +2873,8 @@
khi->key(mSortCol, !mSortDescending));
//update the appended flag
- int appended = 1;
- fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 12, SEEK_SET);
+ Q_INT32 appended = 1;
+ fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);
fwrite(&appended, sizeof(appended), 1, sortStream);
if (sortStream && ferror(sortStream)) {
@@ -2980,7 +2986,7 @@
bool KMHeaders::readSortOrder(bool set_selection)
{
//all cases
- int column, ascending, threaded, discovered_count, sorted_count, appended;
+ Q_INT32 column, ascending, threaded, discovered_count, sorted_count, appended;
bool unread_exists = false;
QMemArray<KMSortCacheItem *> sortCache(mFolder->count());
KMSortCacheItem root;
@@ -3012,6 +3018,10 @@
int version;
fscanf(sortStream, KMAIL_SORT_HEADER, &version);
if(version == KMAIL_SORT_VERSION) {
+ Q_INT32 byteOrder = 0;
+ fread(&byteOrder, sizeof(byteOrder), 1, sortStream);
+ if (byteOrder == 0x12345678)
+ {
fread(&column, sizeof(column), 1, sortStream);
fread(&ascending, sizeof(ascending), 1, sortStream);
fread(&threaded, sizeof(threaded), 1, sortStream);
@@ -3121,6 +3131,11 @@
fclose(sortStream);
sortStream = NULL;
}
+ }
+ else {
+ fclose(sortStream);
+ sortStream = NULL;
+ }
} else {
fclose(sortStream);
sortStream = NULL;
@@ -3245,7 +3260,7 @@
} else {
//update the appended flag
appended = 0;
- fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 12, SEEK_SET);
+ fseek(sortStream, KMAIL_MAGIC_HEADER_OFFSET + 16, SEEK_SET);
fwrite(&appended, sizeof(appended), 1, sortStream);
}
}
Index: kmmsgbase.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmmsgbase.cpp,v
retrieving revision 1.104
diff -u -r1.104 kmmsgbase.cpp
--- kmmsgbase.cpp 2002/01/16 12:43:35 1.104
+++ kmmsgbase.cpp 2002/02/02 06:08:18
@@ -16,7 +16,47 @@
#include <ctype.h>
#include <stdlib.h>
+#include <config.h>
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+// We define functions as kmail_swap_NN so that we don't get compile errors
+// on platforms where bswap_NN happens to be a function instead of a define.
+
+/* Swap bytes in 16 bit value. */
+#ifdef bswap_16
+#define kmail_swap_16(x) bswap_16(x)
+#else
+#define kmail_swap_16(x) \
+ ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
+#endif
+
+/* Swap bytes in 32 bit value. */
+#ifdef bswap_32
+#define kmail_swap_32(x) bswap_32(x)
+#else
+#define kmail_swap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+#endif
+
+/* Swap bytes in 64 bit value. */
+#ifdef bswap_64
+#define kmail_swap_64(x) bswap_64(x)
+#else
+#define kmail_swap_64(x) \
+ ((((x) & 0xff00000000000000ull) >> 56) \
+ | (((x) & 0x00ff000000000000ull) >> 40) \
+ | (((x) & 0x0000ff0000000000ull) >> 24) \
+ | (((x) & 0x000000ff00000000ull) >> 8) \
+ | (((x) & 0x00000000ff000000ull) << 8) \
+ | (((x) & 0x0000000000ff0000ull) << 24) \
+ | (((x) & 0x000000000000ff00ull) << 40) \
+ | (((x) & 0x00000000000000ffull) << 56))
+#endif
+
static KMMsgStatus sStatusList[] =
{
KMMsgStatusDeleted, KMMsgStatusNew,
@@ -681,7 +721,7 @@
for (uint i = 0; i < len; i++)
{
us = str[i].unicode();
- str[i] = QChar(((us & 0xFF) << 8) + ((us & 0xFF00) >> 8));
+ str[i] = QChar(kmail_swap_16(us));
}
}
@@ -698,8 +738,8 @@
memcpy(x, g_chunk+g_chunk_offset, length); \
g_chunk_offset += length; \
} } while(0)
-#define COPY_HEADER_TYPE(x) Q_ASSERT(sizeof(x) == sizeof(MsgPartType)); \
COPY_DATA(&x, sizeof(x))
-#define COPY_HEADER_LEN(x) Q_ASSERT(sizeof(x) == sizeof(short)); COPY_DATA(&x, \
sizeof(x)); +#define COPY_HEADER_TYPE(x) Q_ASSERT(sizeof(x) == sizeof(Q_UINT32)); \
COPY_DATA(&x, sizeof(x)); +#define COPY_HEADER_LEN(x) Q_ASSERT(sizeof(x) == \
sizeof(Q_UINT16)); COPY_DATA(&x, sizeof(x)); \
//----------------------------------------------------------------------------- \
QString KMMsgBase::getStringPart(MsgPartType t) const {
@@ -707,6 +747,7 @@
g_chunk_offset = 0;
bool using_mmap = FALSE;
+ bool swapByteOrder = mParent->indexSwapByteOrder();
if (mParent->indexStreamBasePtr()) {
if (g_chunk)
free(g_chunk);
@@ -725,15 +766,21 @@
}
MsgPartType type;
- short l;
+ Q_UINT16 l;
while(g_chunk_offset < mIndexLength) {
- COPY_HEADER_TYPE(type);
+ Q_UINT32 tmp;
+ COPY_HEADER_TYPE(tmp);
+ type = (MsgPartType) tmp;
COPY_HEADER_LEN(l);
+ if (swapByteOrder)
+ l = kmail_swap_16(l);
if(g_chunk_offset + l > mIndexLength) {
kdDebug(5006) << "This should never happen.. " << __FILE__ << ":" << __LINE__ << \
endl; break;
}
if(type == t) {
+ // This works because the QString constructor does a memcpy.
+ // Otherwise we would need to be concerned about the alignment.
if(l)
ret = QString((QChar *)(g_chunk + g_chunk_offset), l/2);
break;
@@ -744,7 +791,25 @@
g_chunk_length = 0;
g_chunk = NULL;
}
- swapEndian(ret);
+ // Normally we need to swap the byte order because the QStrings are written
+ // in the style of Qt2 (MSB -> network ordered).
+ // QStrings in Qt3 expect host ordering.
+ // On e.g. Intel host ordering is LSB, on e.g. Sparc it is MSB.
+#ifndef BYTE_ORDER
+ assert(false); // Uh oh.
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+#warning Byte order is little endian (swap is true)
+ bool swap_endian = true;
+#else
+#warning Byte order is big endian (swap is false)
+ bool swap_endian = false;
+#endif
+ swap_endian = swap_endian ^ swapByteOrder; // index-file has non-native byte \
order. +
+ if (swap_endian)
+ swapEndian(ret);
return ret;
}
@@ -755,6 +820,8 @@
g_chunk_offset = 0;
bool using_mmap = FALSE;
+ int sizeOfLong = mParent->indexSizeOfLong();
+ bool swapByteOrder = mParent->indexSwapByteOrder();
if (mParent->indexStreamBasePtr()) {
if (g_chunk)
free(g_chunk);
@@ -774,18 +841,74 @@
}
MsgPartType type;
- short l;
+ Q_UINT16 l;
while (g_chunk_offset < mIndexLength) {
- COPY_HEADER_TYPE(type);
+ Q_UINT32 tmp;
+ COPY_HEADER_TYPE(tmp);
+ type = (MsgPartType) tmp;
COPY_HEADER_LEN(l);
+ if (swapByteOrder)
+ l = kmail_swap_16(l);
if (g_chunk_offset + l > mIndexLength) {
kdDebug(5006) << "This should never happen.. " << __FILE__ << ":" << __LINE__ \
<< endl; break;
}
if(type == t) {
- Q_ASSERT(l == sizeof(unsigned long));
- COPY_DATA(&ret, sizeof(ret));
+ assert(sizeOfLong == l);
+ if (sizeOfLong == sizeof(ret))
+ {
+ COPY_DATA(&ret, sizeof(ret));
+ if (swapByteOrder)
+ {
+ if (sizeof(ret) == 4)
+ ret = kmail_swap_32(ret);
+ else
+ ret = kmail_swap_64(ret);
+ }
+ }
+ else if (sizeOfLong == 4)
+ {
+ // Long is stored as 4 bytes in index file, sizeof(long) = 8
+ Q_UINT32 ret_32;
+ COPY_DATA(&ret_32, sizeof(ret_32));
+ if (swapByteOrder)
+ ret_32 = kmail_swap_32(ret_32);
+ ret = ret_32;
+ }
+ else if (sizeOfLong == 8)
+ {
+ // Long is stored as 8 bytes in index file, sizeof(long) = 4
+ Q_UINT32 ret_1;
+ Q_UINT32 ret_2;
+ COPY_DATA(&ret_1, sizeof(ret_1));
+ COPY_DATA(&ret_2, sizeof(ret_2));
+ if (!swapByteOrder)
+ {
+ // Index file order is the same as the order of this CPU.
+#if BYTE_ORDER == LITTLE_ENDIAN
+ // Index file order is little endian
+ ret = ret_1; // We drop the 4 most significant bytes
+#else
+ // Index file order is big endian
+ ret = ret_2; // We drop the 4 most significant bytes
+#endif
+ }
+ else
+ {
+ // Index file order is different from this CPU.
+#if BYTE_ORDER == LITTLE_ENDIAN
+ // Index file order is big endian
+ ret = ret_2; // We drop the 4 most significant bytes
+#else
+ // Index file order is little endian
+ ret = ret_1; // We drop the 4 most significant bytes
+#endif
+ // We swap the result to host order.
+ ret = kmail_swap_32(ret);
+ }
+
+ }
break;
}
g_chunk_offset += l;
@@ -817,34 +940,41 @@
length += len2 + sizeof(short) + sizeof(MsgPartType); \
} while(0)
#define STORE_DATA(type, x) STORE_DATA_LEN(type, &x, sizeof(x))
+#if BYTE_ORDER == LITTLE_ENDIAN
+#warning Byte order is little endian (call swapEndian)
+#define SWAP_TO_NETWORK_ORDER(x) swapEndian(x)
+#else
+#warning Byte order is big endian
+#define SWAP_TO_NETWORK_ORDER(x)
+#endif
unsigned long tmp;
QString tmp_str;
//these is at the beginning because it is queried quite often
tmp_str = msgIdMD5().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgIdMD5Part, tmp_str.unicode(), tmp_str.length() * 2);
tmp = status();
STORE_DATA(MsgStatusPart, tmp);
//these are completely arbitrary order
tmp_str = fromStrip().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgFromPart, tmp_str.unicode(), tmp_str.length() * 2);
tmp_str = subject().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgSubjectPart, tmp_str.unicode(), tmp_str.length() * 2);
tmp_str = toStrip().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgToPart, tmp_str.unicode(), tmp_str.length() * 2);
tmp_str = replyToIdMD5().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgReplyToIdMD5Part, tmp_str.unicode(), tmp_str.length() * 2);
tmp_str = xmark().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgXMarkPart, tmp_str.unicode(), tmp_str.length() * 2);
tmp_str = fileName().stripWhiteSpace();
- swapEndian(tmp_str);
+ SWAP_TO_NETWORK_ORDER(tmp_str);
STORE_DATA_LEN(MsgFilePart, tmp_str.unicode(), tmp_str.length() * 2);
tmp = msgSize();
STORE_DATA(MsgSizePart, tmp);
Index: kmmsgdict.cpp
===================================================================
RCS file: /home/kde/kdenetwork/kmail/kmmsgdict.cpp,v
retrieving revision 1.10
diff -u -r1.10 kmmsgdict.cpp
--- kmmsgdict.cpp 2002/01/04 11:06:28 1.10
+++ kmmsgdict.cpp 2002/02/02 06:08:19
@@ -15,10 +15,29 @@
#include <errno.h>
+#include <config.h>
+
+#if HAVE_BYTESWAP_H
+#include <byteswap.h>
+#endif
+
+// We define functions as kmail_swap_NN so that we don't get compile errors
+// on platforms where bswap_NN happens to be a function instead of a define.
+
+/* Swap bytes in 32 bit value. */
+#ifdef bswap_32
+#define kmail_swap_32(x) bswap_32(x)
+#else
+#define kmail_swap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+#endif
+
+
//-----------------------------------------------------------------------------
// Current version of the .index.ids files
-#define IDS_VERSION 1001
+#define IDS_VERSION 1002
// The asterisk at the end is important
#define IDS_HEADER "# KMail-Index-IDs V%d\n*"
@@ -46,6 +65,8 @@
for (int i = 0; i < size; i++)
array.at(i) = 0;
fp = NULL;
+ swapByteOrder = false;
+ baseOffset = 0;
}
~KMMsgDictREntry()
@@ -103,6 +124,8 @@
public:
QMemArray<KMMsgDictEntry *> array;
FILE *fp;
+ bool swapByteOrder;
+ int baseOffset;
};
//-----------------------------------------------------------------------------
@@ -283,20 +306,30 @@
fclose(fp);
return -1;
}
+
+ bool swapByteOrder;
+ Q_UINT32 byte_order;
+ if (!fread(&byte_order, sizeof(byte_order), 1, fp)) {
+ fclose(fp);
+ return -1;
+ }
+ swapByteOrder = (byte_order == 0x78563412);
- int count;
+ Q_UINT32 count;
if (!fread(&count, sizeof(count), 1, fp)) {
fclose(fp);
return -1;
}
+ if (swapByteOrder)
+ count = kmail_swap_32(count);
KMMsgDictREntry *rentry = new KMMsgDictREntry(count);
- for (int index = 0; index < count; index++) {
- unsigned long msn;
+ for (unsigned int index = 0; index < count; index++) {
+ Q_UINT32 msn;
if (!fread(&msn, sizeof(msn), 1, fp)) {
- for (int i = 0; i < index; i++) {
+ for (unsigned int i = 0; i < index; i++) {
msn = rentry->getMsn(i);
dict->remove((long)msn);
}
@@ -304,7 +337,10 @@
fclose(fp);
return -1;
}
-
+ if (swapByteOrder)
+ msn = kmail_swap_32(msn);
+
+qWarning("Serial number = %d", msn);
//if (!msn)
//kdDebug(5006) << "Dict found zero serial number in folder " << \
folder->label() << endl;
@@ -334,25 +370,44 @@
if (!rentry->fp) {
QString filename = getFolderIdsLocation(folder);
- rentry->fp = fopen(filename.local8Bit(), "r+");
- if (!rentry->fp)
- rentry->fp = fopen(filename.local8Bit(), "w+");
+ FILE *fp = fopen(filename.local8Bit(), "r+");
+ if (fp)
+ {
+ int version = 0;
+ fscanf(fp, IDS_HEADER, &version);
+ if (version == IDS_VERSION)
+ {
+ Q_UINT32 byte_order = 0;
+ fread(&byte_order, sizeof(byte_order), 1, fp);
+ rentry->swapByteOrder = (byte_order == 0x78563412);
+ }
+ else
+ {
+ fclose(fp);
+ fp = 0;
+ }
+ }
+
+ if (!fp)
+ {
+ fp = fopen(filename.local8Bit(), "w+");
+ if (!fp)
+ {
+ kdDebug(5006) << "Dict cannot open with folder " << folder->label() << ": "
+ << strerror(errno) << " (" << errno << ")" << endl;
+ delete rentry;
+ rentry = 0;
+ return 0;
+ }
+ fprintf(fp, IDS_HEADER, IDS_VERSION);
+ Q_UINT32 byteOrder = 0x12345678;
+ fwrite(&byteOrder, sizeof(byteOrder), 1, fp);
+ rentry->swapByteOrder = false;
+ }
+ rentry->baseOffset = ftell(fp);
+ rentry->fp = fp;
}
- if (rentry->fp) {
- FILE *fp = rentry->fp;
- rewind(fp);
-
- fprintf(fp, IDS_HEADER, IDS_VERSION);
- if (ferror(fp))
- rentry = 0;
-
- } else {
- kdDebug(5006) << "Dict cannot open with folder " << folder->label() << ": "
- << strerror(errno) << " (" << errno << ")" << endl;
- rentry = 0;
- }
-
return rentry;
}
@@ -365,17 +420,17 @@
return 0;
FILE *fp = rentry->fp;
+ fseek(fp, rentry->baseOffset, SEEK_SET);
// kdDebug(5006) << "Dict writing for folder " << folder->label() << endl;
-
- int count = rentry->getRealSize();
+ Q_UINT32 count = rentry->getRealSize();
if (!fwrite(&count, sizeof(count), 1, fp)) {
kdDebug(5006) << "Dict cannot write count with folder " << folder->label() << ": \
" << strerror(errno) << " (" << errno << ")" << endl;
return -1;
}
- for (int index = 0; index < count; index++) {
- unsigned long msn = rentry->getMsn(index);
+ for (unsigned int index = 0; index < count; index++) {
+ Q_UINT32 msn = rentry->getMsn(index);
if (!fwrite(&msn, sizeof(msn), 1, fp))
return -1;
}
@@ -410,14 +465,21 @@
// kdDebug(5006) << "Dict appending for folder " << folder->label() << endl;
- int count;
+ fseek(fp, rentry->baseOffset, SEEK_SET);
+ Q_UINT32 count;
if (!fread(&count, sizeof(count), 1, fp)) {
kdDebug(5006) << "Dict cannot read count for folder " << folder->label() << ": "
<< strerror(errno) << " (" << errno << ")" << endl;
return 0;
}
+ if (rentry->swapByteOrder)
+ kmail_swap_32(count);
+
count++;
- fseek(fp, -4, SEEK_CUR);
+
+ if (rentry->swapByteOrder)
+ kmail_swap_32(count);
+ fseek(fp, rentry->baseOffset, SEEK_SET);
if (!fwrite(&count, sizeof(count), 1, fp)) {
kdDebug(5006) << "Dict cannot write count for folder " << folder->label() << ": \
" << strerror(errno) << " (" << errno << ")" << endl;
@@ -428,7 +490,7 @@
if (ofs > 0)
fseek(rentry->fp, ofs, SEEK_CUR);
- ulong msn = rentry->getMsn(index);
+ Q_UINT32 msn = rentry->getMsn(index);
if (!fwrite(&msn, sizeof(msn), 1, rentry->fp)) {
kdDebug(5006) << "Dict cannot write count for folder " << folder->label() << ": \
" << strerror(errno) << " (" << errno << ")" << endl;
_______________________________________________
kmail Developers mailing list
kmail@mail.kde.org
http://mail.kde.org/mailman/listinfo/kmail
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic