~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/doveadm/dsync/dsync-mailbox-state.c

  • Committer: Package Import Robot
  • Author(s): Jaldhar H. Vyas
  • Date: 2013-09-09 00:57:32 UTC
  • mfrom: (1.13.11)
  • mto: (4.8.5 experimental) (1.16.1)
  • mto: This revision was merged to the branch mainline in revision 97.
  • Revision ID: package-import@ubuntu.com-20130909005732-dn1eell8srqbhh0e
Tags: upstream-2.2.5
ImportĀ upstreamĀ versionĀ 2.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2013 Dovecot authors, see the included COPYING file */
 
2
 
 
3
#include "lib.h"
 
4
#include "array.h"
 
5
#include "base64.h"
 
6
#include "crc32.h"
 
7
#include "hash.h"
 
8
#include "dsync-mailbox-state.h"
 
9
 
 
10
#define MAILBOX_SIZE (GUID_128_SIZE + 4 + 4 + 8 + 8)
 
11
 
 
12
static void put_uint32(buffer_t *output, uint32_t num)
 
13
{
 
14
        buffer_append_c(output, num & 0xff);
 
15
        buffer_append_c(output, (num >> 8) & 0xff);
 
16
        buffer_append_c(output, (num >> 16) & 0xff);
 
17
        buffer_append_c(output, (num >> 24) & 0xff);
 
18
}
 
19
 
 
20
static uint32_t get_uint32(const unsigned char *data)
 
21
{
 
22
        return data[0] | (data[1] << 8) | (data[2] << 16) |
 
23
                ((unsigned int)data[3] << 24);
 
24
}
 
25
 
 
26
void dsync_mailbox_states_export(const HASH_TABLE_TYPE(dsync_mailbox_state) states,
 
27
                                 string_t *output)
 
28
{
 
29
        struct hash_iterate_context *iter;
 
30
        struct dsync_mailbox_state *state;
 
31
        uint8_t *guid;
 
32
        buffer_t *buf = buffer_create_dynamic(pool_datastack_create(), 128);
 
33
        uint32_t crc = 0;
 
34
 
 
35
        iter = hash_table_iterate_init(states);
 
36
        while (hash_table_iterate(iter, states, &guid, &state)) {
 
37
                buffer_append(buf, state->mailbox_guid,
 
38
                              sizeof(state->mailbox_guid));
 
39
                put_uint32(buf, state->last_uidvalidity);
 
40
                put_uint32(buf, state->last_common_uid);
 
41
                put_uint32(buf, state->last_common_modseq & 0xffffffffU);
 
42
                put_uint32(buf, state->last_common_modseq >> 32);
 
43
                put_uint32(buf, state->last_common_pvt_modseq & 0xffffffffU);
 
44
                put_uint32(buf, state->last_common_pvt_modseq >> 32);
 
45
                if (buf->used % 3 == 0) {
 
46
                        crc = crc32_data_more(crc, buf->data, buf->used);
 
47
                        base64_encode(buf->data, buf->used, output);
 
48
                        buffer_set_used_size(buf, 0);
 
49
                }
 
50
        }
 
51
        hash_table_iterate_deinit(&iter);
 
52
 
 
53
        crc = crc32_data_more(crc, buf->data, buf->used);
 
54
        put_uint32(buf, crc);
 
55
        base64_encode(buf->data, buf->used, output);
 
56
}
 
57
 
 
58
int dsync_mailbox_states_import(HASH_TABLE_TYPE(dsync_mailbox_state) states,
 
59
                                pool_t pool, const char *input,
 
60
                                const char **error_r)
 
61
{
 
62
        struct dsync_mailbox_state *state;
 
63
        buffer_t *buf;
 
64
        uint8_t *guid_p;
 
65
        const unsigned char *data;
 
66
        size_t pos;
 
67
        unsigned int i, count;
 
68
 
 
69
        buf = buffer_create_dynamic(pool_datastack_create(), strlen(input));
 
70
        if (base64_decode(input, strlen(input), &pos, buf) < 0) {
 
71
                *error_r = "Invalid base64 data";
 
72
                return -1;
 
73
        }
 
74
        if (buf->used < 4) {
 
75
                *error_r = "Input too small";
 
76
                return -1;
 
77
        }
 
78
        if ((buf->used-4) % MAILBOX_SIZE != 0) {
 
79
                *error_r = "Invalid input size";
 
80
                return -1;
 
81
        }
 
82
        data = buf->data;
 
83
        count = (buf->used-4) / MAILBOX_SIZE;
 
84
 
 
85
        if (get_uint32(data + buf->used-4) != crc32_data(data, buf->used-4)) {
 
86
                *error_r = "CRC32 mismatch";
 
87
                return -1;
 
88
        }
 
89
 
 
90
        for (i = 0; i < count; i++, data += MAILBOX_SIZE) {
 
91
                state = p_new(pool, struct dsync_mailbox_state, 1);
 
92
                memcpy(state->mailbox_guid, data, GUID_128_SIZE);
 
93
                state->last_uidvalidity = get_uint32(data + GUID_128_SIZE);
 
94
                state->last_common_uid = get_uint32(data + GUID_128_SIZE + 4);
 
95
                state->last_common_modseq =
 
96
                        get_uint32(data + GUID_128_SIZE + 8) |
 
97
                        (uint64_t)get_uint32(data + GUID_128_SIZE + 12) << 32;
 
98
                state->last_common_pvt_modseq =
 
99
                        get_uint32(data + GUID_128_SIZE + 16) |
 
100
                        (uint64_t)get_uint32(data + GUID_128_SIZE + 20) << 32;
 
101
                guid_p = state->mailbox_guid;
 
102
                hash_table_insert(states, guid_p, state);
 
103
        }
 
104
        return 0;
 
105
}