X-Git-Url: http://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ftdb%2Ftest%2Frun-corrupt.c;h=6f753ea6d46c81c9dbd3f9e388c1f3078c98e30e;hp=6d190c2aff976547272dd1f6326155c4f6c90a5b;hb=ab3df365ce9bcd76379cda8d3a7c188baa3e0a05;hpb=6f05c2b8ad782f7f602bddad8b72b42c55c32bf9 diff --git a/ccan/tdb/test/run-corrupt.c b/ccan/tdb/test/run-corrupt.c index 6d190c2a..6f753ea6 100644 --- a/ccan/tdb/test/run-corrupt.c +++ b/ccan/tdb/test/run-corrupt.c @@ -1,17 +1,19 @@ #define _XOPEN_SOURCE 500 -#include "tdb/tdb.h" -#include "tdb/io.c" -#include "tdb/tdb.c" -#include "tdb/lock.c" -#include "tdb/freelist.c" -#include "tdb/traverse.c" -#include "tdb/transaction.c" -#include "tdb/error.c" -#include "tdb/open.c" -#include "tdb/check.c" -#include "tap/tap.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include +#include "logging.h" static int check(TDB_DATA key, TDB_DATA data, void *private) { @@ -32,18 +34,28 @@ static int check(TDB_DATA key, TDB_DATA data, void *private) return 0; } -int main(int argc, char *argv[]) +static void tdb_flip_bit(struct tdb_context *tdb, unsigned int bit) +{ + unsigned int off = bit / CHAR_BIT; + unsigned char mask = (1 << (bit % CHAR_BIT)); + + if (tdb->map_ptr) + ((unsigned char *)tdb->map_ptr)[off] ^= mask; + else { + unsigned char c; + if (pread(tdb->fd, &c, 1, off) != 1) + err(1, "pread"); + c ^= mask; + if (pwrite(tdb->fd, &c, 1, off) != 1) + err(1, "pwrite"); + } +} + +static void check_test(struct tdb_context *tdb) { - struct tdb_context *tdb; TDB_DATA key, data; unsigned int i, verifiable, corrupt, sizes[2], dsize, ksize; - plan_tests(2); - tdb = tdb_open("/tmp/test6.tdb", 2, TDB_CLEAR_IF_FIRST, - O_CREAT|O_TRUNC|O_RDWR, 0600); - - if (!tdb) - abort(); ok1(tdb_check(tdb, NULL, NULL) == 0); key.dptr = (void *)"hello"; @@ -64,29 +76,53 @@ int main(int argc, char *argv[]) /* This is how many bytes we expect to be verifiable. */ /* From the file header. */ verifiable = strlen(TDB_MAGIC_FOOD) + 1 - + 2 * sizeof(uint32_t) + 2 * sizeof(tdb_off_t); + + 2 * sizeof(uint32_t) + 2 * sizeof(tdb_off_t) + + 2 * sizeof(uint32_t); /* From the free list chain and hash chains. */ verifiable += 3 * sizeof(tdb_off_t); /* From the record headers & tailer */ - verifiable += 5 * (sizeof(struct list_struct) + sizeof(uint32_t)); + verifiable += 5 * (sizeof(struct tdb_record) + sizeof(uint32_t)); /* The free block: we ignore datalen, keylen, full_hash. */ - verifiable += sizeof(struct list_struct) - 3*sizeof(uint32_t) + + verifiable += sizeof(struct tdb_record) - 3*sizeof(uint32_t) + sizeof(uint32_t); /* Our check function verifies the key and data. */ verifiable += ksize + dsize; /* Flip one bit at a time, make sure it detects verifiable bytes. */ for (i = 0, corrupt = 0; i < tdb->map_size * CHAR_BIT; i++) { - bit_flip(tdb->map_ptr, i); + tdb_flip_bit(tdb, i); memset(sizes, 0, sizeof(sizes)); if (tdb_check(tdb, check, sizes) != 0) corrupt++; else if (sizes[0] != ksize || sizes[1] != dsize) corrupt++; - bit_flip(tdb->map_ptr, i); + tdb_flip_bit(tdb, i); } ok(corrupt == verifiable * CHAR_BIT, "corrupt %u should be %u", corrupt, verifiable * CHAR_BIT); +} + +int main(int argc, char *argv[]) +{ + struct tdb_context *tdb; + + plan_tests(4); + /* This should use mmap. */ + tdb = tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + if (!tdb) + abort(); + check_test(tdb); + tdb_close(tdb); + + /* This should not. */ + tdb = tdb_open_ex("run-corrupt.tdb", 2, TDB_CLEAR_IF_FIRST|TDB_NOMMAP, + O_CREAT|O_TRUNC|O_RDWR, 0600, &taplogctx, NULL); + + if (!tdb) + abort(); + check_test(tdb); tdb_close(tdb); return exit_status();