dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Copyright (c) 2007 D. Richard Hipp dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is free software; you can redistribute it and/or dbda8d6ce9 2007-07-21 drh: ** modify it under the terms of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License version 2 as published by the Free Software Foundation. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This program is distributed in the hope that it will be useful, dbda8d6ce9 2007-07-21 drh: ** but WITHOUT ANY WARRANTY; without even the implied warranty of dbda8d6ce9 2007-07-21 drh: ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU dbda8d6ce9 2007-07-21 drh: ** General Public License for more details. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** You should have received a copy of the GNU General Public dbda8d6ce9 2007-07-21 drh: ** License along with this library; if not, write to the dbda8d6ce9 2007-07-21 drh: ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, dbda8d6ce9 2007-07-21 drh: ** Boston, MA 02111-1307, USA. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Author contact information: dbda8d6ce9 2007-07-21 drh: ** drh@hwaci.com dbda8d6ce9 2007-07-21 drh: ** http://www.hwaci.com/drh/ dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ******************************************************************************* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** This file contains code used to help verify the integrity of the dbda8d6ce9 2007-07-21 drh: ** the repository dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: #include "config.h" dbda8d6ce9 2007-07-21 drh: #include "verify.h" dbda8d6ce9 2007-07-21 drh: #include <assert.h> dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Load the record identify by rid. Make sure we can reproduce it dbda8d6ce9 2007-07-21 drh: ** without error. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Panic if anything goes wrong. If this procedure returns it means dbda8d6ce9 2007-07-21 drh: ** that everything is OK. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static void verify_rid(int rid){ dbda8d6ce9 2007-07-21 drh: Blob uuid, hash, content; dbda8d6ce9 2007-07-21 drh: blob_zero(&uuid); dbda8d6ce9 2007-07-21 drh: db_blob(&uuid, "SELECT uuid FROM blob WHERE rid=%d", rid); dbda8d6ce9 2007-07-21 drh: if( blob_size(&uuid)!=UUID_SIZE ){ dbda8d6ce9 2007-07-21 drh: fossil_panic("not a valid rid: %d", rid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: content_get(rid, &content); dbda8d6ce9 2007-07-21 drh: sha1sum_blob(&content, &hash); 75c476ccd1 2007-07-23 drh: /* blob_reset(&content); */ dbda8d6ce9 2007-07-21 drh: if( blob_compare(&uuid, &hash) ){ 75c476ccd1 2007-07-23 drh: printf("content=[%s]\n", blob_str(&content)); 75c476ccd1 2007-07-23 drh: fossil_panic("hash of rid %d (%b) does not match its uuid (%b)", 75c476ccd1 2007-07-23 drh: rid, &hash, &uuid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: blob_reset(&uuid); dbda8d6ce9 2007-07-21 drh: blob_reset(&hash); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: static int verify_at_commit(void *notUsed){ dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT rid FROM toverify"); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int rid = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: verify_rid(rid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: db_multi_exec("DELETE FROM toverify"); dbda8d6ce9 2007-07-21 drh: return 0; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** Arrange to verify a particular record prior to committing. dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** If the record rid is less than 1, then just initialize the dbda8d6ce9 2007-07-21 drh: ** verification system but do not record anything as needing dbda8d6ce9 2007-07-21 drh: ** verification. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void verify_before_commit(int rid){ dbda8d6ce9 2007-07-21 drh: static int isInit = 0; dbda8d6ce9 2007-07-21 drh: if( !isInit ){ dbda8d6ce9 2007-07-21 drh: db_multi_exec( dbda8d6ce9 2007-07-21 drh: "CREATE TEMP TABLE toverify(rid INTEGER PRIMARY KEY);" dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: sqlite3_commit_hook(g.db, verify_at_commit, 0); dbda8d6ce9 2007-07-21 drh: isInit = 1; dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: if( rid>0 ){ dbda8d6ce9 2007-07-21 drh: db_multi_exec( dbda8d6ce9 2007-07-21 drh: "INSERT OR IGNORE INTO toverify VALUES(%d)", rid dbda8d6ce9 2007-07-21 drh: ); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: dbda8d6ce9 2007-07-21 drh: /* dbda8d6ce9 2007-07-21 drh: ** COMMAND: test-verify-all dbda8d6ce9 2007-07-21 drh: ** dbda8d6ce9 2007-07-21 drh: ** Verify all records in the repository. dbda8d6ce9 2007-07-21 drh: */ dbda8d6ce9 2007-07-21 drh: void verify_all_cmd(void){ dbda8d6ce9 2007-07-21 drh: Stmt q; dbda8d6ce9 2007-07-21 drh: db_must_be_within_tree(); dbda8d6ce9 2007-07-21 drh: db_prepare(&q, "SELECT rid FROM blob"); dbda8d6ce9 2007-07-21 drh: while( db_step(&q)==SQLITE_ROW ){ dbda8d6ce9 2007-07-21 drh: int rid = db_column_int(&q, 0); dbda8d6ce9 2007-07-21 drh: verify_rid(rid); dbda8d6ce9 2007-07-21 drh: } dbda8d6ce9 2007-07-21 drh: db_finalize(&q); dbda8d6ce9 2007-07-21 drh: }