summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMagnus Ahltorp <map@kth.se>2016-11-30 16:46:37 +0100
committerMagnus Ahltorp <map@kth.se>2016-11-30 16:46:37 +0100
commit47c8ae43bf83b73d16257784e8afc957175489c0 (patch)
tree1a4de284724cd229639eebdffaadfa61c46aab74
parent5fab0fd188242f08431dee0bff62a3028d262b6d (diff)
Recover from extra data at end of index file
-rw-r--r--c_src/filebuffer.c6
-rw-r--r--c_src/filebuffer.h2
-rw-r--r--c_src/permdb.c41
3 files changed, 48 insertions, 1 deletions
diff --git a/c_src/filebuffer.c b/c_src/filebuffer.c
index 40b79ad..d35bfa7 100644
--- a/c_src/filebuffer.c
+++ b/c_src/filebuffer.c
@@ -63,6 +63,12 @@ bf_lastcommit(buffered_file *file)
return file->lastcommit;
}
+void
+bf_setlastcommit(buffered_file *file, uint64_t lastcommit)
+{
+ file->lastcommit = lastcommit;
+}
+
const char *
bf_name(buffered_file *file)
{
diff --git a/c_src/filebuffer.h b/c_src/filebuffer.h
index b2fb7ef..f98d20d 100644
--- a/c_src/filebuffer.h
+++ b/c_src/filebuffer.h
@@ -27,6 +27,8 @@ uint64_t
bf_total_length(buffered_file *file);
uint64_t
bf_lastcommit(buffered_file *file);
+void
+bf_setlastcommit(buffered_file *file, uint64_t lastcommit);
const char *
bf_name(buffered_file *file);
diff --git a/c_src/permdb.c b/c_src/permdb.c
index f92958d..0ce74b6 100644
--- a/c_src/permdb.c
+++ b/c_src/permdb.c
@@ -272,6 +272,27 @@ verify_index_commit(buffered_file *file, node_offset offset)
return validate_checksum(&commit, file);
}
+node_offset
+search_index_commit(buffered_file *file, node_offset startoffset)
+{
+ node_offset offset = startoffset;
+
+ offset -= INDEX_COMMIT_TRAILER_SIZE;
+
+ while (offset > 0) {
+ unsigned char *data =
+ bf_read(file, offset, INDEX_COMMIT_TRAILER_SIZE, NULL);
+ uint64_t cookie =
+ read_be64(data + sizeof(uint64_t) + SHA256_DIGEST_SIZE);
+ if (cookie == index_commit_cookie) {
+ return offset + INDEX_COMMIT_TRAILER_SIZE;
+ }
+ offset -= 8;
+ }
+
+ return 0;
+}
+
int
indexfile_verify_file(buffered_file *file)
{
@@ -283,7 +304,23 @@ indexfile_verify_file(buffered_file *file)
return -1;
}
free(header);
- if (verify_index_commit(file, bf_total_length(file)) < 0) {
+
+ node_offset offset = bf_total_length(file);
+ while (offset) {
+ offset = search_index_commit(file, offset);
+ if (offset) {
+ fprintf(stderr,
+ "verifying index file: found potential commit at %lld\n", (unsigned long long) offset);
+ }
+ if (offset && verify_index_commit(file, offset) == 0) {
+ bf_setlastcommit(file, offset);
+ break;
+ }
+ }
+ fprintf(stderr,
+ "verifying index file: found commit at %lld\n", (unsigned long long) bf_lastcommit(file));
+
+ if (offset == 0) {
fprintf(stderr,
"verifying index file: commit verification failed\n");
return -1;
@@ -468,9 +505,11 @@ try_reload_database(permdb_object *state) {
if (bf_total_length(state->indexfile) == oldindexsize) {
return 0;
} else {
+#if 0
if (datafile_verify_file(state->datafile) < 0) {
warnx("data file verification failed");
}
+#endif
if (indexfile_verify_file(state->indexfile) < 0) {
warnx("cannot rebuild in readonly mode");
}