Fossil SCM

Add the db_fingerprint() interface for computing a repository fingerprint.

drh 2019-01-10 19:54 UTC trunk
Commit f5043617c0f725a2c88084f923def46e52693c64ec372085533e3e527dcccc11
1 file changed +65
+65
--- src/db.c
+++ src/db.c
@@ -3704,5 +3704,70 @@
37043704
db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
37053705
fossil_print("Repository database: %s\n", g.zRepositoryName);
37063706
fossil_print("Local database: %s\n", g.zLocalDbName);
37073707
fossil_print("Config database: %s\n", g.zConfigDbName);
37083708
}
3709
+
3710
+/*
3711
+** Compute a "fingerprint" on the repository. A fingerprint is used
3712
+** to verify that that the repository has not been replaced by a clone
3713
+** of the same repository. More precisely, a fingerprint are used to
3714
+** verify that the mapping between SHA3 hashes and RID values is unchanged.
3715
+**
3716
+** The checkout database ("localdb") stores RID values. When associating
3717
+** a checkout database against a repository database, it is useful to verify
3718
+** the fingerprint so that we know tha the RID values in the checkout
3719
+** database still correspond to the correct entries in the BLOB table of
3720
+** the repository.
3721
+**
3722
+** The fingerprint is based on the RCVFROM table. When constructing a
3723
+** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
3724
+** accomplish this.) When verifying an old fingerprint, use the same
3725
+** RCVFROM entry that generated the fingerprint in the first place.
3726
+**
3727
+** The fingerprint consists of the rcvid, a "/", and the MD5 checksum of
3728
+** the remaining fields of the RCVFROM table entry.
3729
+*/
3730
+char *db_fingerprint(int rcvid){
3731
+ char *z = 0;
3732
+ Blob sql = BLOB_INITIALIZER;
3733
+ Stmt q;
3734
+ blob_append_sql(&sql,
3735
+ "SELECT rcvid, quote(uid), quote(mtime), quote(nonce), quote(ipaddr)"
3736
+ " FROM rcvfrom"
3737
+ );
3738
+ if( rcvid<=0 ){
3739
+ blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
3740
+ }else{
3741
+ blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
3742
+ }
3743
+ db_prepare_blob(&q, &sql);
3744
+ blob_reset(&sql);
3745
+ if( db_step(&q)==SQLITE_ROW ){
3746
+ int i;
3747
+ md5sum_init();
3748
+ for(i=1; i<=4; i++){
3749
+ md5sum_step_text(db_column_text(&q,i),-1);
3750
+ }
3751
+ z = mprintf("%d/%s",db_column_int(&q,0),md5sum_finish(0));
3752
+ }
3753
+ db_finalize(&q);
3754
+ return z;
3755
+}
3756
+
3757
+/*
3758
+** COMMAND: test-fingerprint
3759
+**
3760
+** Usage: %fossil test-fingerprint ?RCVID?
3761
+**
3762
+** Display the repository fingerprint.
3763
+*/
3764
+void test_fingerprint(void){
3765
+ int rcvid = 0;
3766
+ db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
3767
+ if( g.argc==3 ){
3768
+ rcvid = atoi(g.argv[2]);
3769
+ }else if( g.argc!=2 ){
3770
+ fossil_fatal("wrong number of arguments");
3771
+ }
3772
+ fossil_print("%z\n", db_fingerprint(rcvid));
3773
+}
37093774
--- src/db.c
+++ src/db.c
@@ -3704,5 +3704,70 @@
3704 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
3705 fossil_print("Repository database: %s\n", g.zRepositoryName);
3706 fossil_print("Local database: %s\n", g.zLocalDbName);
3707 fossil_print("Config database: %s\n", g.zConfigDbName);
3708 }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3709
--- src/db.c
+++ src/db.c
@@ -3704,5 +3704,70 @@
3704 db_find_and_open_repository(OPEN_ANY_SCHEMA, 0);
3705 fossil_print("Repository database: %s\n", g.zRepositoryName);
3706 fossil_print("Local database: %s\n", g.zLocalDbName);
3707 fossil_print("Config database: %s\n", g.zConfigDbName);
3708 }
3709
3710 /*
3711 ** Compute a "fingerprint" on the repository. A fingerprint is used
3712 ** to verify that that the repository has not been replaced by a clone
3713 ** of the same repository. More precisely, a fingerprint are used to
3714 ** verify that the mapping between SHA3 hashes and RID values is unchanged.
3715 **
3716 ** The checkout database ("localdb") stores RID values. When associating
3717 ** a checkout database against a repository database, it is useful to verify
3718 ** the fingerprint so that we know tha the RID values in the checkout
3719 ** database still correspond to the correct entries in the BLOB table of
3720 ** the repository.
3721 **
3722 ** The fingerprint is based on the RCVFROM table. When constructing a
3723 ** new fingerprint, use the most recent RCVFROM entry. (Set rcvid==0 to
3724 ** accomplish this.) When verifying an old fingerprint, use the same
3725 ** RCVFROM entry that generated the fingerprint in the first place.
3726 **
3727 ** The fingerprint consists of the rcvid, a "/", and the MD5 checksum of
3728 ** the remaining fields of the RCVFROM table entry.
3729 */
3730 char *db_fingerprint(int rcvid){
3731 char *z = 0;
3732 Blob sql = BLOB_INITIALIZER;
3733 Stmt q;
3734 blob_append_sql(&sql,
3735 "SELECT rcvid, quote(uid), quote(mtime), quote(nonce), quote(ipaddr)"
3736 " FROM rcvfrom"
3737 );
3738 if( rcvid<=0 ){
3739 blob_append_sql(&sql, " ORDER BY rcvid DESC LIMIT 1");
3740 }else{
3741 blob_append_sql(&sql, " WHERE rcvid=%d", rcvid);
3742 }
3743 db_prepare_blob(&q, &sql);
3744 blob_reset(&sql);
3745 if( db_step(&q)==SQLITE_ROW ){
3746 int i;
3747 md5sum_init();
3748 for(i=1; i<=4; i++){
3749 md5sum_step_text(db_column_text(&q,i),-1);
3750 }
3751 z = mprintf("%d/%s",db_column_int(&q,0),md5sum_finish(0));
3752 }
3753 db_finalize(&q);
3754 return z;
3755 }
3756
3757 /*
3758 ** COMMAND: test-fingerprint
3759 **
3760 ** Usage: %fossil test-fingerprint ?RCVID?
3761 **
3762 ** Display the repository fingerprint.
3763 */
3764 void test_fingerprint(void){
3765 int rcvid = 0;
3766 db_find_and_open_repository(OPEN_ANY_SCHEMA,0);
3767 if( g.argc==3 ){
3768 rcvid = atoi(g.argv[2]);
3769 }else if( g.argc!=2 ){
3770 fossil_fatal("wrong number of arguments");
3771 }
3772 fossil_print("%z\n", db_fingerprint(rcvid));
3773 }
3774

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button