2 * Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
4 * This file is part of GnuPG.
6 * GnuPG is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * GnuPG is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
28 #include <sys/types.h>
43 #if defined(HAVE_DOSISH_SYSTEM)
44 #define ftruncate chsize
47 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
48 #define MY_O_BINARY O_BINARY
55 * Yes, this is a very simple implementation. We should really
56 * use a page aligned buffer and read complete pages.
57 * To implement a simple trannsaction system, this is sufficient.
59 typedef struct cache_ctrl_struct
*CACHE_CTRL
;
60 struct cache_ctrl_struct
{
67 char data
[TRUST_RECORD_LEN
];
70 #define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased while in a */
71 #define MAX_CACHE_ENTRIES_HARD 10000 /* transaction to this one */
72 static CACHE_CTRL cache_list
;
73 static int cache_entries
;
74 static int cache_is_dirty
;
76 /* a type used to pass infomation to cmp_krec_fpr */
77 struct cmp_krec_fpr_struct
{
83 /* a type used to pass infomation to cmp_[s]dir */
84 struct cmp_xdir_struct
{
91 static DOTLOCK lockhandle
;
93 static int db_fd
= -1;
94 static int in_transaction
;
96 static void open_db(void);
97 static void migrate_from_v2 (void);
101 /*************************************
102 ************* record cache **********
103 *************************************/
106 * Get the data from therecord cache and return a
107 * pointer into that cache. Caller should copy
108 * the return data. NULL is returned on a cache miss.
111 get_record_from_cache( ulong recno
)
115 for( r
= cache_list
; r
; r
= r
->next
) {
116 if( r
->flags
.used
&& r
->recno
== recno
)
124 write_cache_item( CACHE_CTRL r
)
128 if( lseek( db_fd
, r
->recno
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
129 log_error(_("trustdb rec %lu: lseek failed: %s\n"),
130 r
->recno
, strerror(errno
) );
131 return G10ERR_WRITE_FILE
;
133 n
= write( db_fd
, r
->data
, TRUST_RECORD_LEN
);
134 if( n
!= TRUST_RECORD_LEN
) {
135 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
136 r
->recno
, n
, strerror(errno
) );
137 return G10ERR_WRITE_FILE
;
144 * Put data into the cache. This function may flush the
145 * some cache entries if there is not enough space available.
148 put_record_into_cache( ulong recno
, const char *data
)
150 CACHE_CTRL r
, unused
;
154 /* see whether we already cached this one */
155 for( unused
= NULL
, r
= cache_list
; r
; r
= r
->next
) {
156 if( !r
->flags
.used
) {
160 else if( r
->recno
== recno
) {
161 if( !r
->flags
.dirty
) {
162 /* Hmmm: should we use a a copy and compare? */
163 if( memcmp(r
->data
, data
, TRUST_RECORD_LEN
) ) {
168 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
171 if( r
->flags
.used
) {
178 /* not in the cache: add a new entry */
179 if( unused
) { /* reuse this entry */
183 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
189 /* see whether we reached the limit */
190 if( cache_entries
< MAX_CACHE_ENTRIES_SOFT
) { /* no */
191 r
= xmalloc( sizeof *r
);
194 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
196 r
->next
= cache_list
;
202 /* cache is full: discard some clean entries */
204 int n
= clean_count
/ 3; /* discard a third of the clean entries */
207 for( unused
= NULL
, r
= cache_list
; r
; r
= r
->next
) {
208 if( r
->flags
.used
&& !r
->flags
.dirty
) {
221 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
227 /* no clean entries: have to flush some dirty entries */
228 if( in_transaction
) {
229 /* but we can't do this while in a transaction
230 * we increase the cache size instead */
231 if( cache_entries
< MAX_CACHE_ENTRIES_HARD
) { /* no */
232 if( opt
.debug
&& !(cache_entries
% 100) )
233 log_debug("increasing tdbio cache size\n");
234 r
= xmalloc( sizeof *r
);
237 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
239 r
->next
= cache_list
;
245 log_info(_("trustdb transaction too large\n"));
246 return G10ERR_RESOURCE_LIMIT
;
249 int n
= dirty_count
/ 5; /* discard some dirty entries */
253 if( make_dotlock( lockhandle
, -1 ) )
254 log_fatal("can't acquire lock - giving up\n");
258 for( unused
= NULL
, r
= cache_list
; r
; r
= r
->next
) {
259 if( r
->flags
.used
&& r
->flags
.dirty
) {
260 int rc
= write_cache_item( r
);
271 if( !opt
.lock_once
) {
272 if( !release_dotlock( lockhandle
) )
279 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
292 return cache_is_dirty
;
297 * Flush the cache. This cannot be used while in a transaction.
308 log_bug("tdbio: syncing while in transaction\n");
310 if( !cache_is_dirty
)
314 if( make_dotlock( lockhandle
, -1 ) )
315 log_fatal("can't acquire lock - giving up\n");
320 for( r
= cache_list
; r
; r
= r
->next
) {
321 if( r
->flags
.used
&& r
->flags
.dirty
) {
322 int rc
= write_cache_item( r
);
328 if( did_lock
&& !opt
.lock_once
) {
329 if( !release_dotlock( lockhandle
) )
337 /* The transaction code is disabled in the 1.2.x branch, as it is not
338 yet used. It will be enabled in 1.3.x. */
341 * Simple transactions system:
342 * Everything between begin_transaction and end/cancel_transaction
343 * is not immediatly written but at the time of end_transaction.
347 tdbio_begin_transaction()
352 log_bug("tdbio: nested transactions\n");
353 /* flush everything out */
362 tdbio_end_transaction()
366 if( !in_transaction
)
367 log_bug("tdbio: no active transaction\n");
369 if( make_dotlock( lockhandle
, -1 ) )
370 log_fatal("can't acquire lock - giving up\n");
377 unblock_all_signals();
378 if( !opt
.lock_once
) {
379 if( !release_dotlock( lockhandle
) )
386 tdbio_cancel_transaction()
390 if( !in_transaction
)
391 log_bug("tdbio: no active transaction\n");
393 /* remove all dirty marked entries, so that the original ones
394 * are read back the next time */
395 if( cache_is_dirty
) {
396 for( r
= cache_list
; r
; r
= r
->next
) {
397 if( r
->flags
.used
&& r
->flags
.dirty
) {
411 /********************************************************
412 **************** cached I/O functions ******************
413 ********************************************************/
419 if( !release_dotlock(lockhandle
) )
424 /* Caller must sync */
426 tdbio_update_version_record (void)
431 memset( &rec
, 0, sizeof rec
);
433 rc
=tdbio_read_record( 0, &rec
, RECTYPE_VER
);
436 rec
.r
.ver
.created
= make_timestamp();
437 rec
.r
.ver
.marginals
= opt
.marginals_needed
;
438 rec
.r
.ver
.completes
= opt
.completes_needed
;
439 rec
.r
.ver
.cert_depth
= opt
.max_cert_depth
;
440 rec
.r
.ver
.trust_model
= opt
.trust_model
;
441 rc
=tdbio_write_record(&rec
);
448 create_version_record (void)
453 memset( &rec
, 0, sizeof rec
);
454 rec
.r
.ver
.version
= 3;
455 rec
.r
.ver
.created
= make_timestamp();
456 rec
.r
.ver
.marginals
= opt
.marginals_needed
;
457 rec
.r
.ver
.completes
= opt
.completes_needed
;
458 rec
.r
.ver
.cert_depth
= opt
.max_cert_depth
;
459 if(opt
.trust_model
==TM_PGP
|| opt
.trust_model
==TM_CLASSIC
)
460 rec
.r
.ver
.trust_model
= opt
.trust_model
;
462 rec
.r
.ver
.trust_model
= TM_PGP
;
463 rec
.rectype
= RECTYPE_VER
;
465 rc
= tdbio_write_record( &rec
);
474 tdbio_set_dbname( const char *new_dbname
, int create
)
477 static int initialized
= 0;
485 fname
=make_filename(opt
.homedir
,"trustdb" EXTSEP_S
"gpg", NULL
);
486 else if (*new_dbname
!= DIRSEP_C
)
488 if (strchr(new_dbname
, DIRSEP_C
) )
489 fname
= make_filename (new_dbname
, NULL
);
491 fname
= make_filename (opt
.homedir
, new_dbname
, NULL
);
494 fname
= xstrdup (new_dbname
);
496 if( access( fname
, R_OK
) ) {
497 if( errno
!= ENOENT
) {
498 log_error( _("can't access `%s': %s\n"), fname
, strerror(errno
) );
500 return G10ERR_TRUSTDB
;
506 char *p
= strrchr( fname
, DIRSEP_C
);
511 if( access( fname
, F_OK
) ) {
512 try_make_homedir( fname
);
513 log_fatal( _("%s: directory does not exist!\n"), fname
);
521 lockhandle
= create_dotlock( db_name
);
523 log_fatal( _("can't create lock for `%s'\n"), db_name
);
524 if( make_dotlock( lockhandle
, -1 ) )
525 log_fatal( _("can't lock `%s'\n"), db_name
);
526 #endif /* __riscos__ */
528 if (is_secured_filename (fname
)) {
533 fp
=fopen( fname
, "wb" );
536 log_fatal( _("can't create `%s': %s\n"), fname
, strerror(errno
) );
538 db_fd
= open( db_name
, O_RDWR
| MY_O_BINARY
);
540 log_fatal( _("can't open `%s': %s\n"), db_name
, strerror(errno
) );
544 lockhandle
= create_dotlock( db_name
);
546 log_fatal( _("can't create lock for `%s'\n"), db_name
);
547 #endif /* !__riscos__ */
549 rc
= create_version_record ();
551 log_fatal( _("%s: failed to create version record: %s"),
552 fname
, g10_errstr(rc
));
553 /* and read again to check that we are okay */
554 if( tdbio_read_record( 0, &rec
, RECTYPE_VER
) )
555 log_fatal( _("%s: invalid trustdb created\n"), db_name
);
558 log_info(_("%s: trustdb created\n"), db_name
);
584 assert( db_fd
== -1 );
587 lockhandle
= create_dotlock( db_name
);
589 log_fatal( _("can't create lock for `%s'\n"), db_name
);
591 if (make_dotlock( lockhandle
, -1 ) )
592 log_fatal( _("can't lock `%s'\n"), db_name
);
593 #endif /* __riscos__ */
594 db_fd
= open (db_name
, O_RDWR
| MY_O_BINARY
);
595 if (db_fd
== -1 && (errno
== EACCES
600 db_fd
= open (db_name
, O_RDONLY
| MY_O_BINARY
);
602 log_info (_("NOTE: trustdb not writable\n"));
605 log_fatal( _("can't open `%s': %s\n"), db_name
, strerror(errno
) );
606 register_secured_file (db_name
);
608 /* check whether we need to do a version migration */
610 n
= read (db_fd
, buf
, 5);
611 while (n
==-1 && errno
== EINTR
);
612 if (n
== 5 && !memcmp (buf
, "\x01gpg\x02", 5))
617 /* read the version record */
618 if (tdbio_read_record (0, &rec
, RECTYPE_VER
) )
619 log_fatal( _("%s: invalid trustdb\n"), db_name
);
624 * Make a hashtable: type 0 = trust hash
627 create_hashtable( TRUSTREC
*vr
, int type
)
634 offset
= lseek( db_fd
, 0, SEEK_END
);
636 log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno
) );
637 recnum
= offset
/ TRUST_RECORD_LEN
;
638 assert(recnum
); /* this is will never be the first record */
641 vr
->r
.ver
.trusthashtbl
= recnum
;
643 /* Now write the records */
644 n
= (256+ITEMS_PER_HTBL_RECORD
-1) / ITEMS_PER_HTBL_RECORD
;
645 for(i
=0; i
< n
; i
++, recnum
++ ) {
646 memset( &rec
, 0, sizeof rec
);
647 rec
.rectype
= RECTYPE_HTBL
;
649 rc
= tdbio_write_record( &rec
);
651 log_fatal( _("%s: failed to create hashtable: %s\n"),
652 db_name
, g10_errstr(rc
));
654 /* update the version record */
655 rc
= tdbio_write_record( vr
);
659 log_fatal( _("%s: error updating version record: %s\n"),
660 db_name
, g10_errstr(rc
));
665 tdbio_db_matches_options()
667 static int yes_no
= -1;
674 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
676 log_fatal( _("%s: error reading version record: %s\n"),
677 db_name
, g10_errstr(rc
) );
679 yes_no
= vr
.r
.ver
.marginals
== opt
.marginals_needed
680 && vr
.r
.ver
.completes
== opt
.completes_needed
681 && vr
.r
.ver
.cert_depth
== opt
.max_cert_depth
682 && vr
.r
.ver
.trust_model
== opt
.trust_model
;
689 tdbio_read_model(void)
694 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
696 log_fatal( _("%s: error reading version record: %s\n"),
697 db_name
, g10_errstr(rc
) );
698 return vr
.r
.ver
.trust_model
;
702 * Return the nextstamp value.
705 tdbio_read_nextcheck ()
710 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
712 log_fatal( _("%s: error reading version record: %s\n"),
713 db_name
, g10_errstr(rc
) );
714 return vr
.r
.ver
.nextcheck
;
717 /* Return true when the stamp was actually changed. */
719 tdbio_write_nextcheck (ulong stamp
)
724 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
726 log_fatal( _("%s: error reading version record: %s\n"),
727 db_name
, g10_errstr(rc
) );
729 if (vr
.r
.ver
.nextcheck
== stamp
)
732 vr
.r
.ver
.nextcheck
= stamp
;
733 rc
= tdbio_write_record( &vr
);
735 log_fatal( _("%s: error writing version record: %s\n"),
736 db_name
, g10_errstr(rc
) );
743 * Return the record number of the trusthash tbl or create a new one.
746 get_trusthashrec(void)
748 static ulong trusthashtbl
; /* record number of the trust hashtable */
750 if( !trusthashtbl
) {
754 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
756 log_fatal( _("%s: error reading version record: %s\n"),
757 db_name
, g10_errstr(rc
) );
758 if( !vr
.r
.ver
.trusthashtbl
)
759 create_hashtable( &vr
, 0 );
761 trusthashtbl
= vr
.r
.ver
.trusthashtbl
;
769 * Update a hashtable.
770 * table gives the start of the table, key and keylen is the key,
771 * newrecnum is the record number to insert.
774 upd_hashtable( ulong table
, byte
*key
, int keylen
, ulong newrecnum
)
776 TRUSTREC lastrec
, rec
;
785 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
786 rc
= tdbio_read_record( hashrec
, &rec
, RECTYPE_HTBL
);
788 log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc
) );
792 item
= rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
793 if( !item
) { /* insert a new item into the hash table */
794 rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = newrecnum
;
795 rc
= tdbio_write_record( &rec
);
797 log_error("upd_hashtable: write htbl failed: %s\n",
802 else if( item
!= newrecnum
) { /* must do an update */
804 rc
= tdbio_read_record( item
, &rec
, 0 );
806 log_error( "upd_hashtable: read item failed: %s\n",
811 if( rec
.rectype
== RECTYPE_HTBL
) {
814 if( level
>= keylen
) {
815 log_error( "hashtable has invalid indirections.\n");
816 return G10ERR_TRUSTDB
;
820 else if( rec
.rectype
== RECTYPE_HLST
) { /* extend list */
821 /* see whether the key is already in this list */
823 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
824 if( rec
.r
.hlst
.rnum
[i
] == newrecnum
) {
825 return 0; /* okay, already in the list */
828 if( rec
.r
.hlst
.next
) {
829 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
832 log_error( "upd_hashtable: read hlst failed: %s\n",
838 break; /* not there */
840 /* find the next free entry and put it in */
842 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
843 if( !rec
.r
.hlst
.rnum
[i
] ) {
844 rec
.r
.hlst
.rnum
[i
] = newrecnum
;
845 rc
= tdbio_write_record( &rec
);
847 log_error( "upd_hashtable: write hlst failed: %s\n",
849 return rc
; /* done */
852 if( rec
.r
.hlst
.next
) {
853 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
854 &rec
, RECTYPE_HLST
);
856 log_error( "upd_hashtable: read hlst failed: %s\n",
861 else { /* add a new list record */
862 rec
.r
.hlst
.next
= item
= tdbio_new_recnum();
863 rc
= tdbio_write_record( &rec
);
865 log_error( "upd_hashtable: write hlst failed: %s\n",
869 memset( &rec
, 0, sizeof rec
);
870 rec
.rectype
= RECTYPE_HLST
;
872 rec
.r
.hlst
.rnum
[0] = newrecnum
;
873 rc
= tdbio_write_record( &rec
);
875 log_error( "upd_hashtable: write ext hlst failed: %s\n",
877 return rc
; /* done */
879 } /* end loop over hlst slots */
881 else if( rec
.rectype
== RECTYPE_TRUST
) { /* insert a list record */
882 if( rec
.recnum
== newrecnum
) {
885 item
= rec
.recnum
; /* save number of key record */
886 memset( &rec
, 0, sizeof rec
);
887 rec
.rectype
= RECTYPE_HLST
;
888 rec
.recnum
= tdbio_new_recnum();
889 rec
.r
.hlst
.rnum
[0] = item
; /* old keyrecord */
890 rec
.r
.hlst
.rnum
[1] = newrecnum
; /* and new one */
891 rc
= tdbio_write_record( &rec
);
893 log_error( "upd_hashtable: write new hlst failed: %s\n",
897 /* update the hashtable record */
898 lastrec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = rec
.recnum
;
899 rc
= tdbio_write_record( &lastrec
);
901 log_error( "upd_hashtable: update htbl failed: %s\n",
903 return rc
; /* ready */
906 log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
907 table
, hashrec
, (msb
% ITEMS_PER_HTBL_RECORD
), item
);
909 return G10ERR_TRUSTDB
;
918 * Drop an entry from a hashtable
919 * table gives the start of the table, key and keylen is the key,
922 drop_from_hashtable( ulong table
, byte
*key
, int keylen
, ulong recnum
)
933 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
934 rc
= tdbio_read_record( hashrec
, &rec
, RECTYPE_HTBL
);
936 log_error("drop_from_hashtable: read failed: %s\n",
941 item
= rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
942 if( !item
) /* not found - forget about it */
945 if( item
== recnum
) { /* tables points direct to the record */
946 rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = 0;
947 rc
= tdbio_write_record( &rec
);
949 log_error("drop_from_hashtable: write htbl failed: %s\n",
954 rc
= tdbio_read_record( item
, &rec
, 0 );
956 log_error( "drop_from_hashtable: read item failed: %s\n",
961 if( rec
.rectype
== RECTYPE_HTBL
) {
964 if( level
>= keylen
) {
965 log_error( "hashtable has invalid indirections.\n");
966 return G10ERR_TRUSTDB
;
971 if( rec
.rectype
== RECTYPE_HLST
) {
973 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
974 if( rec
.r
.hlst
.rnum
[i
] == recnum
) {
975 rec
.r
.hlst
.rnum
[i
] = 0; /* drop */
976 rc
= tdbio_write_record( &rec
);
978 log_error("drop_from_hashtable: write htbl failed: %s\n",
983 if( rec
.r
.hlst
.next
) {
984 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
987 log_error( "drop_from_hashtable: read hlst failed: %s\n",
993 return 0; /* key not in table */
997 log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n",
998 table
, hashrec
, (msb
% ITEMS_PER_HTBL_RECORD
), item
);
999 return G10ERR_TRUSTDB
;
1005 * Lookup a record via the hashtable tablewith key/keylen and return the
1006 * result in rec. cmp() should return if the record is the desired one.
1007 * Returns -1 if not found, 0 if found or another errocode
1010 lookup_hashtable( ulong table
, const byte
*key
, size_t keylen
,
1011 int (*cmpfnc
)(void*, const TRUSTREC
*), void *cmpdata
,
1015 ulong hashrec
, item
;
1022 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
1023 rc
= tdbio_read_record( hashrec
, rec
, RECTYPE_HTBL
);
1025 log_error("lookup_hashtable failed: %s\n", g10_errstr(rc
) );
1029 item
= rec
->r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
1031 return -1; /* not found */
1033 rc
= tdbio_read_record( item
, rec
, 0 );
1035 log_error( "hashtable read failed: %s\n", g10_errstr(rc
) );
1038 if( rec
->rectype
== RECTYPE_HTBL
) {
1041 if( level
>= keylen
) {
1042 log_error("hashtable has invalid indirections\n");
1043 return G10ERR_TRUSTDB
;
1047 else if( rec
->rectype
== RECTYPE_HLST
) {
1051 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1052 if( rec
->r
.hlst
.rnum
[i
] ) {
1055 rc
= tdbio_read_record( rec
->r
.hlst
.rnum
[i
], &tmp
, 0 );
1057 log_error( "lookup_hashtable: read item failed: %s\n",
1061 if( (*cmpfnc
)( cmpdata
, &tmp
) ) {
1067 if( rec
->r
.hlst
.next
) {
1068 rc
= tdbio_read_record( rec
->r
.hlst
.next
, rec
, RECTYPE_HLST
);
1070 log_error( "lookup_hashtable: read hlst failed: %s\n",
1076 return -1; /* not found */
1081 if( (*cmpfnc
)( cmpdata
, rec
) )
1082 return 0; /* really found */
1084 return -1; /* no: not found */
1089 * Update the trust hashtbl or create the table if it does not exist
1092 update_trusthashtbl( TRUSTREC
*tr
)
1094 return upd_hashtable( get_trusthashrec(),
1095 tr
->r
.trust
.fingerprint
, 20, tr
->recnum
);
1101 tdbio_dump_record( TRUSTREC
*rec
, FILE *fp
)
1104 ulong rnum
= rec
->recnum
;
1106 fprintf(fp
, "rec %5lu, ", rnum
);
1108 switch( rec
->rectype
) {
1109 case 0: fprintf(fp
, "blank\n");
1111 case RECTYPE_VER
: fprintf(fp
,
1112 "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d nc=%lu (%s)\n",
1113 rec
->r
.ver
.trusthashtbl
,
1114 rec
->r
.ver
.firstfree
,
1115 rec
->r
.ver
.marginals
,
1116 rec
->r
.ver
.completes
,
1117 rec
->r
.ver
.cert_depth
,
1118 rec
->r
.ver
.trust_model
,
1119 rec
->r
.ver
.nextcheck
,
1120 strtimestamp(rec
->r
.ver
.nextcheck
)
1123 case RECTYPE_FREE
: fprintf(fp
, "free, next=%lu\n", rec
->r
.free
.next
);
1126 fprintf(fp
, "htbl,");
1127 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ )
1128 fprintf(fp
, " %lu", rec
->r
.htbl
.item
[i
] );
1132 fprintf(fp
, "hlst, next=%lu,", rec
->r
.hlst
.next
);
1133 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ )
1134 fprintf(fp
, " %lu", rec
->r
.hlst
.rnum
[i
] );
1138 fprintf(fp
, "trust ");
1139 for(i
=0; i
< 20; i
++ )
1140 fprintf(fp
, "%02X", rec
->r
.trust
.fingerprint
[i
] );
1141 fprintf (fp
, ", ot=%d, d=%d, vl=%lu\n", rec
->r
.trust
.ownertrust
,
1142 rec
->r
.trust
.depth
, rec
->r
.trust
.validlist
);
1145 fprintf(fp
, "valid ");
1146 for(i
=0; i
< 20; i
++ )
1147 fprintf(fp
, "%02X", rec
->r
.valid
.namehash
[i
] );
1148 fprintf (fp
, ", v=%d, next=%lu\n", rec
->r
.valid
.validity
,
1152 fprintf(fp
, "unknown type %d\n", rec
->rectype
);
1158 * read the record with number recnum
1159 * returns: -1 on error, 0 on success
1162 tdbio_read_record( ulong recnum
, TRUSTREC
*rec
, int expected
)
1164 byte readbuf
[TRUST_RECORD_LEN
];
1165 const byte
*buf
, *p
;
1171 buf
= get_record_from_cache( recnum
);
1173 if( lseek( db_fd
, recnum
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
1174 log_error(_("trustdb: lseek failed: %s\n"), strerror(errno
) );
1175 return G10ERR_READ_FILE
;
1177 n
= read( db_fd
, readbuf
, TRUST_RECORD_LEN
);
1179 return -1; /* eof */
1181 else if( n
!= TRUST_RECORD_LEN
) {
1182 log_error(_("trustdb: read failed (n=%d): %s\n"), n
,
1184 return G10ERR_READ_FILE
;
1188 rec
->recnum
= recnum
;
1191 rec
->rectype
= *p
++;
1192 if( expected
&& rec
->rectype
!= expected
) {
1193 log_error("%lu: read expected rec type %d, got %d\n",
1194 recnum
, expected
, rec
->rectype
);
1195 return G10ERR_TRUSTDB
;
1197 p
++; /* skip reserved byte */
1198 switch( rec
->rectype
) {
1199 case 0: /* unused (free) record */
1201 case RECTYPE_VER
: /* version record */
1202 if( memcmp(buf
+1, "gpg", 3 ) ) {
1203 log_error( _("%s: not a trustdb file\n"), db_name
);
1204 rc
= G10ERR_TRUSTDB
;
1206 p
+= 2; /* skip "gpg" */
1207 rec
->r
.ver
.version
= *p
++;
1208 rec
->r
.ver
.marginals
= *p
++;
1209 rec
->r
.ver
.completes
= *p
++;
1210 rec
->r
.ver
.cert_depth
= *p
++;
1211 rec
->r
.ver
.trust_model
= *p
++;
1213 rec
->r
.ver
.created
= buftoulong(p
); p
+= 4;
1214 rec
->r
.ver
.nextcheck
= buftoulong(p
); p
+= 4;
1217 rec
->r
.ver
.firstfree
=buftoulong(p
); p
+= 4;
1219 rec
->r
.ver
.trusthashtbl
=buftoulong(p
); p
+= 4;
1221 log_error( _("%s: version record with recnum %lu\n"), db_name
,
1223 rc
= G10ERR_TRUSTDB
;
1225 else if( rec
->r
.ver
.version
!= 3 ) {
1226 log_error( _("%s: invalid file version %d\n"), db_name
,
1227 rec
->r
.ver
.version
);
1228 rc
= G10ERR_TRUSTDB
;
1232 rec
->r
.free
.next
= buftoulong(p
); p
+= 4;
1235 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ ) {
1236 rec
->r
.htbl
.item
[i
] = buftoulong(p
); p
+= 4;
1240 rec
->r
.hlst
.next
= buftoulong(p
); p
+= 4;
1241 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1242 rec
->r
.hlst
.rnum
[i
] = buftoulong(p
); p
+= 4;
1246 memcpy( rec
->r
.trust
.fingerprint
, p
, 20); p
+=20;
1247 rec
->r
.trust
.ownertrust
= *p
++;
1248 rec
->r
.trust
.depth
= *p
++;
1249 rec
->r
.trust
.min_ownertrust
= *p
++;
1251 rec
->r
.trust
.validlist
= buftoulong(p
); p
+= 4;
1254 memcpy( rec
->r
.valid
.namehash
, p
, 20); p
+=20;
1255 rec
->r
.valid
.validity
= *p
++;
1256 rec
->r
.valid
.next
= buftoulong(p
); p
+= 4;
1257 rec
->r
.valid
.full_count
= *p
++;
1258 rec
->r
.valid
.marginal_count
= *p
++;
1261 log_error( "%s: invalid record type %d at recnum %lu\n",
1262 db_name
, rec
->rectype
, (ulong
)recnum
);
1263 rc
= G10ERR_TRUSTDB
;
1271 * Write the record at RECNUM
1274 tdbio_write_record( TRUSTREC
*rec
)
1276 byte buf
[TRUST_RECORD_LEN
], *p
;
1279 ulong recnum
= rec
->recnum
;
1284 memset(buf
, 0, TRUST_RECORD_LEN
);
1286 *p
++ = rec
->rectype
; p
++;
1287 switch( rec
->rectype
) {
1288 case 0: /* unused record */
1290 case RECTYPE_VER
: /* version record */
1293 memcpy(p
-1, "gpg", 3 ); p
+= 2;
1294 *p
++ = rec
->r
.ver
.version
;
1295 *p
++ = rec
->r
.ver
.marginals
;
1296 *p
++ = rec
->r
.ver
.completes
;
1297 *p
++ = rec
->r
.ver
.cert_depth
;
1298 *p
++ = rec
->r
.ver
.trust_model
;
1300 ulongtobuf(p
, rec
->r
.ver
.created
); p
+= 4;
1301 ulongtobuf(p
, rec
->r
.ver
.nextcheck
); p
+= 4;
1304 ulongtobuf(p
, rec
->r
.ver
.firstfree
); p
+= 4;
1306 ulongtobuf(p
, rec
->r
.ver
.trusthashtbl
); p
+= 4;
1310 ulongtobuf(p
, rec
->r
.free
.next
); p
+= 4;
1315 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ ) {
1316 ulongtobuf( p
, rec
->r
.htbl
.item
[i
]); p
+= 4;
1321 ulongtobuf( p
, rec
->r
.hlst
.next
); p
+= 4;
1322 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1323 ulongtobuf( p
, rec
->r
.hlst
.rnum
[i
]); p
+= 4;
1328 memcpy( p
, rec
->r
.trust
.fingerprint
, 20); p
+= 20;
1329 *p
++ = rec
->r
.trust
.ownertrust
;
1330 *p
++ = rec
->r
.trust
.depth
;
1331 *p
++ = rec
->r
.trust
.min_ownertrust
;
1333 ulongtobuf( p
, rec
->r
.trust
.validlist
); p
+= 4;
1337 memcpy( p
, rec
->r
.valid
.namehash
, 20); p
+= 20;
1338 *p
++ = rec
->r
.valid
.validity
;
1339 ulongtobuf( p
, rec
->r
.valid
.next
); p
+= 4;
1340 *p
++ = rec
->r
.valid
.full_count
;
1341 *p
++ = rec
->r
.valid
.marginal_count
;
1348 rc
= put_record_into_cache( recnum
, buf
);
1351 else if( rec
->rectype
== RECTYPE_TRUST
)
1352 rc
= update_trusthashtbl( rec
);
1358 tdbio_delete_record( ulong recnum
)
1363 /* Must read the record fist, so we can drop it from the hash tables */
1364 rc
= tdbio_read_record( recnum
, &rec
, 0 );
1367 else if( rec
.rectype
== RECTYPE_TRUST
) {
1368 rc
= drop_from_hashtable( get_trusthashrec(),
1369 rec
.r
.trust
.fingerprint
, 20, rec
.recnum
);
1375 /* now we can chnage it to a free record */
1376 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
1378 log_fatal( _("%s: error reading version record: %s\n"),
1379 db_name
, g10_errstr(rc
) );
1381 rec
.recnum
= recnum
;
1382 rec
.rectype
= RECTYPE_FREE
;
1383 rec
.r
.free
.next
= vr
.r
.ver
.firstfree
;
1384 vr
.r
.ver
.firstfree
= recnum
;
1385 rc
= tdbio_write_record( &rec
);
1387 rc
= tdbio_write_record( &vr
);
1392 * create a new record and return its record number
1402 /* look for unused records */
1403 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
1405 log_fatal( _("%s: error reading version record: %s\n"),
1406 db_name
, g10_errstr(rc
) );
1407 if( vr
.r
.ver
.firstfree
) {
1408 recnum
= vr
.r
.ver
.firstfree
;
1409 rc
= tdbio_read_record( recnum
, &rec
, RECTYPE_FREE
);
1411 log_error( _("%s: error reading free record: %s\n"),
1412 db_name
, g10_errstr(rc
) );
1415 /* update dir record */
1416 vr
.r
.ver
.firstfree
= rec
.r
.free
.next
;
1417 rc
= tdbio_write_record( &vr
);
1419 log_error( _("%s: error writing dir record: %s\n"),
1420 db_name
, g10_errstr(rc
) );
1423 /*zero out the new record */
1424 memset( &rec
, 0, sizeof rec
);
1425 rec
.rectype
= 0; /* unused record */
1426 rec
.recnum
= recnum
;
1427 rc
= tdbio_write_record( &rec
);
1429 log_fatal(_("%s: failed to zero a record: %s\n"),
1430 db_name
, g10_errstr(rc
));
1432 else { /* not found, append a new record */
1433 offset
= lseek( db_fd
, 0, SEEK_END
);
1435 log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno
) );
1436 recnum
= offset
/ TRUST_RECORD_LEN
;
1437 assert(recnum
); /* this is will never be the first record */
1438 /* we must write a record, so that the next call to this function
1439 * returns another recnum */
1440 memset( &rec
, 0, sizeof rec
);
1441 rec
.rectype
= 0; /* unused record */
1442 rec
.recnum
= recnum
;
1444 if( lseek( db_fd
, recnum
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
1445 log_error(_("trustdb rec %lu: lseek failed: %s\n"),
1446 recnum
, strerror(errno
) );
1447 rc
= G10ERR_WRITE_FILE
;
1450 int n
= write( db_fd
, &rec
, TRUST_RECORD_LEN
);
1451 if( n
!= TRUST_RECORD_LEN
) {
1452 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
1453 recnum
, n
, strerror(errno
) );
1454 rc
= G10ERR_WRITE_FILE
;
1459 log_fatal(_("%s: failed to append a record: %s\n"),
1460 db_name
, g10_errstr(rc
));
1468 cmp_trec_fpr ( void *fpr
, const TRUSTREC
*rec
)
1470 return rec
->rectype
== RECTYPE_TRUST
1471 && !memcmp( rec
->r
.trust
.fingerprint
, fpr
, 20);
1476 tdbio_search_trust_byfpr( const byte
*fingerprint
, TRUSTREC
*rec
)
1480 /* locate the trust record using the hash table */
1481 rc
= lookup_hashtable( get_trusthashrec(), fingerprint
, 20,
1482 cmp_trec_fpr
, (void*)fingerprint
, rec
);
1487 tdbio_search_trust_bypk (PKT_public_key
*pk
, TRUSTREC
*rec
)
1489 byte fingerprint
[MAX_FINGERPRINT_LEN
];
1492 fingerprint_from_pk( pk
, fingerprint
, &fingerlen
);
1493 for (; fingerlen
< 20; fingerlen
++ )
1494 fingerprint
[fingerlen
] = 0;
1495 return tdbio_search_trust_byfpr (fingerprint
, rec
);
1504 "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") );
1509 * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2)
1510 * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs
1511 * only to scan the tdb and insert new the new trust records. The old ones are
1512 * obsolte from now on
1525 int ottable_size
, ottable_used
;
1531 ottable
= xmalloc (ottable_size
* sizeof *ottable
);
1534 /* We have some restrictions here. We can't use the version record
1535 * and we can't use any of the old hashtables because we dropped the
1536 * code. So we first collect all ownertrusts and then use a second
1537 * pass fo find the associated keys. We have to do this all without using
1538 * the regular record read functions.
1541 /* get all the ownertrusts */
1542 if (lseek (db_fd
, 0, SEEK_SET
) == -1 )
1543 log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno
));
1544 for (recno
=0;;recno
++)
1547 n
= read (db_fd
, oldbuf
, 40);
1548 while (n
==-1 && errno
== EINTR
);
1552 log_fatal ("migrate_vfrom_v2: read error or short read\n");
1558 if (ottable_used
== ottable_size
)
1560 ottable_size
+= 1000;
1561 ottable
= xrealloc (ottable
, ottable_size
* sizeof *ottable
);
1563 ottable
[ottable_used
].keyrecno
= buftoulong (oldbuf
+6);
1564 ottable
[ottable_used
].ot
= oldbuf
[18];
1565 ottable
[ottable_used
].okay
= 0;
1566 memset (ottable
[ottable_used
].fpr
,0, 20);
1567 if (ottable
[ottable_used
].keyrecno
&& ottable
[ottable_used
].ot
)
1570 log_info ("found %d ownertrust records\n", ottable_used
);
1572 /* Read again and find the fingerprints */
1573 if (lseek (db_fd
, 0, SEEK_SET
) == -1 )
1574 log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno
));
1575 for (recno
=0;;recno
++)
1578 n
= read (db_fd
, oldbuf
, 40);
1579 while (n
==-1 && errno
== EINTR
);
1583 log_fatal ("migrate_from_v2: read error or short read\n");
1589 for (i
=0; i
< ottable_used
; i
++)
1591 if (ottable
[i
].keyrecno
== recno
)
1593 memcpy (ottable
[i
].fpr
, oldbuf
+20, 20);
1594 ottable
[i
].okay
= 1;
1600 /* got everything - create the v3 trustdb */
1601 if (ftruncate (db_fd
, 0))
1602 log_fatal ("can't truncate `%s': %s\n", db_name
, strerror (errno
) );
1603 if (create_version_record ())
1604 log_fatal ("failed to recreate version record of `%s'\n", db_name
);
1606 /* access the hash table, so it is store just after the version record,
1607 * this is not needed put a dump is more pretty */
1608 get_trusthashrec ();
1610 /* And insert the old ownertrust values */
1612 for (i
=0; i
< ottable_used
; i
++)
1614 if (!ottable
[i
].okay
)
1617 memset (&rec
, 0, sizeof rec
);
1618 rec
.recnum
= tdbio_new_recnum ();
1619 rec
.rectype
= RECTYPE_TRUST
;
1620 memcpy(rec
.r
.trust
.fingerprint
, ottable
[i
].fpr
, 20);
1621 rec
.r
.trust
.ownertrust
= ottable
[i
].ot
;
1622 if (tdbio_write_record (&rec
))
1623 log_fatal ("failed to write trust record of `%s'\n", db_name
);
1627 revalidation_mark ();
1630 log_fatal ("failed to sync `%s'\n", db_name
);
1631 log_info ("migrated %d version 2 ownertrusts\n", count
);