1 #include "../common/tdb_private.h"
2 #include "../common/io.c"
3 #include "../common/tdb.c"
4 #include "../common/lock.c"
5 #include "../common/freelist.c"
6 #include "../common/traverse.c"
7 #include "../common/transaction.c"
8 #include "../common/error.c"
9 #include "../common/open.c"
10 #include "../common/check.c"
11 #include "../common/hash.c"
12 #include "tap-interface.h"
17 static int check(TDB_DATA key
, TDB_DATA data
, void *private)
19 unsigned int *sizes
= private;
21 if (key
.dsize
> strlen("hello"))
23 if (memcmp(key
.dptr
, "hello", key
.dsize
) != 0)
26 if (data
.dsize
!= strlen("world"))
28 if (memcmp(data
.dptr
, "world", data
.dsize
) != 0)
31 sizes
[0] += key
.dsize
;
32 sizes
[1] += data
.dsize
;
36 static void tdb_flip_bit(struct tdb_context
*tdb
, unsigned int bit
)
38 unsigned int off
= bit
/ CHAR_BIT
;
39 unsigned char mask
= (1 << (bit
% CHAR_BIT
));
42 ((unsigned char *)tdb
->map_ptr
)[off
] ^= mask
;
45 if (pread(tdb
->fd
, &c
, 1, off
) != 1)
48 if (pwrite(tdb
->fd
, &c
, 1, off
) != 1)
53 static void check_test(struct tdb_context
*tdb
)
56 unsigned int i
, verifiable
, corrupt
, sizes
[2], dsize
, ksize
;
58 ok1(tdb_check(tdb
, NULL
, NULL
) == 0);
60 key
.dptr
= (void *)"hello";
61 data
.dsize
= strlen("world");
62 data
.dptr
= (void *)"world";
64 /* Key and data size respectively. */
67 /* 5 keys in hash size 2 means we'll have multichains. */
68 for (key
.dsize
= 1; key
.dsize
<= 5; key
.dsize
++) {
71 if (tdb_store(tdb
, key
, data
, TDB_INSERT
) != 0)
75 /* This is how many bytes we expect to be verifiable. */
76 /* From the file header. */
77 verifiable
= strlen(TDB_MAGIC_FOOD
) + 1
78 + 2 * sizeof(uint32_t) + 2 * sizeof(tdb_off_t
)
79 + 2 * sizeof(uint32_t);
80 /* From the free list chain and hash chains. */
81 verifiable
+= 3 * sizeof(tdb_off_t
);
82 /* From the record headers & tailer */
83 verifiable
+= 5 * (sizeof(struct tdb_record
) + sizeof(uint32_t));
84 /* The free block: we ignore datalen, keylen, full_hash. */
85 verifiable
+= sizeof(struct tdb_record
) - 3*sizeof(uint32_t) +
87 /* Our check function verifies the key and data. */
88 verifiable
+= ksize
+ dsize
;
90 /* Flip one bit at a time, make sure it detects verifiable bytes. */
91 for (i
= 0, corrupt
= 0; i
< tdb
->map_size
* CHAR_BIT
; i
++) {
93 memset(sizes
, 0, sizeof(sizes
));
94 if (tdb_check(tdb
, check
, sizes
) != 0)
96 else if (sizes
[0] != ksize
|| sizes
[1] != dsize
)
100 ok(corrupt
== verifiable
* CHAR_BIT
, "corrupt %u should be %u",
101 corrupt
, verifiable
* CHAR_BIT
);
104 int main(int argc
, char *argv
[])
106 struct tdb_context
*tdb
;
109 /* This should use mmap. */
110 tdb
= tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST
,
111 O_CREAT
|O_TRUNC
|O_RDWR
, 0600, &taplogctx
, NULL
);
118 /* This should not. */
119 tdb
= tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST
|TDB_NOMMAP
,
120 O_CREAT
|O_TRUNC
|O_RDWR
, 0600, &taplogctx
, NULL
);
127 return exit_status();