1 /* tdbio.c - trust databse I/O operations
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 3 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, see <http://www.gnu.org/licenses/>.
26 #include <sys/types.h>
41 #if defined(HAVE_DOSISH_SYSTEM)
42 #define ftruncate chsize
45 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
46 #define MY_O_BINARY O_BINARY
53 * Yes, this is a very simple implementation. We should really
54 * use a page aligned buffer and read complete pages.
55 * To implement a simple trannsaction system, this is sufficient.
57 typedef struct cache_ctrl_struct
*CACHE_CTRL
;
58 struct cache_ctrl_struct
{
65 char data
[TRUST_RECORD_LEN
];
68 #define MAX_CACHE_ENTRIES_SOFT 200 /* may be increased while in a */
69 #define MAX_CACHE_ENTRIES_HARD 10000 /* transaction to this one */
70 static CACHE_CTRL cache_list
;
71 static int cache_entries
;
72 static int cache_is_dirty
;
74 /* a type used to pass infomation to cmp_krec_fpr */
75 struct cmp_krec_fpr_struct
{
81 /* a type used to pass infomation to cmp_[s]dir */
82 struct cmp_xdir_struct
{
89 static DOTLOCK lockhandle
;
91 static int db_fd
= -1;
92 static int in_transaction
;
94 static void open_db(void);
98 /*************************************
99 ************* record cache **********
100 *************************************/
103 * Get the data from therecord cache and return a
104 * pointer into that cache. Caller should copy
105 * the return data. NULL is returned on a cache miss.
108 get_record_from_cache( ulong recno
)
112 for( r
= cache_list
; r
; r
= r
->next
) {
113 if( r
->flags
.used
&& r
->recno
== recno
)
121 write_cache_item( CACHE_CTRL r
)
126 if( lseek( db_fd
, r
->recno
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
127 err
= gpg_error_from_syserror ();
128 log_error(_("trustdb rec %lu: lseek failed: %s\n"),
129 r
->recno
, strerror(errno
) );
132 n
= write( db_fd
, r
->data
, TRUST_RECORD_LEN
);
133 if( n
!= TRUST_RECORD_LEN
) {
134 err
= gpg_error_from_syserror ();
135 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
136 r
->recno
, n
, strerror(errno
) );
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
);
512 /* Windows may either have a slash or a backslash. Take
514 char *pp
= strrchr (fname
, '/');
518 #endif /*HAVE_W32_SYSTEM*/
522 if( access( fname
, F_OK
) ) {
523 try_make_homedir( fname
);
524 log_fatal( _("%s: directory does not exist!\n"), fname
);
532 lockhandle
= create_dotlock( db_name
);
534 log_fatal( _("can't create lock for `%s'\n"), db_name
);
535 if( make_dotlock( lockhandle
, -1 ) )
536 log_fatal( _("can't lock `%s'\n"), db_name
);
537 #endif /* __riscos__ */
539 if (is_secured_filename (fname
)) {
544 fp
=fopen( fname
, "wb" );
547 log_fatal( _("can't create `%s': %s\n"), fname
, strerror(errno
) );
549 db_fd
= open( db_name
, O_RDWR
| MY_O_BINARY
);
551 log_fatal( _("can't open `%s': %s\n"), db_name
, strerror(errno
) );
555 lockhandle
= create_dotlock( db_name
);
557 log_fatal( _("can't create lock for `%s'\n"), db_name
);
558 #endif /* !__riscos__ */
560 rc
= create_version_record ();
562 log_fatal( _("%s: failed to create version record: %s"),
563 fname
, g10_errstr(rc
));
564 /* and read again to check that we are okay */
565 if( tdbio_read_record( 0, &rec
, RECTYPE_VER
) )
566 log_fatal( _("%s: invalid trustdb created\n"), db_name
);
569 log_info(_("%s: trustdb created\n"), db_name
);
593 assert( db_fd
== -1 );
596 lockhandle
= create_dotlock( db_name
);
598 log_fatal( _("can't create lock for `%s'\n"), db_name
);
600 if (make_dotlock( lockhandle
, -1 ) )
601 log_fatal( _("can't lock `%s'\n"), db_name
);
602 #endif /* __riscos__ */
603 db_fd
= open (db_name
, O_RDWR
| MY_O_BINARY
);
604 if (db_fd
== -1 && (errno
== EACCES
610 db_fd
= open (db_name
, O_RDONLY
| MY_O_BINARY
);
612 log_info (_("NOTE: trustdb not writable\n"));
615 log_fatal( _("can't open `%s': %s\n"), db_name
, strerror(errno
) );
616 register_secured_file (db_name
);
618 /* Read the version record. */
619 if (tdbio_read_record (0, &rec
, RECTYPE_VER
) )
620 log_fatal( _("%s: invalid trustdb\n"), db_name
);
625 * Make a hashtable: type 0 = trust hash
628 create_hashtable( TRUSTREC
*vr
, int type
)
635 offset
= lseek( db_fd
, 0, SEEK_END
);
637 log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno
) );
638 recnum
= offset
/ TRUST_RECORD_LEN
;
639 assert(recnum
); /* this is will never be the first record */
642 vr
->r
.ver
.trusthashtbl
= recnum
;
644 /* Now write the records */
645 n
= (256+ITEMS_PER_HTBL_RECORD
-1) / ITEMS_PER_HTBL_RECORD
;
646 for(i
=0; i
< n
; i
++, recnum
++ ) {
647 memset( &rec
, 0, sizeof rec
);
648 rec
.rectype
= RECTYPE_HTBL
;
650 rc
= tdbio_write_record( &rec
);
652 log_fatal( _("%s: failed to create hashtable: %s\n"),
653 db_name
, g10_errstr(rc
));
655 /* update the version record */
656 rc
= tdbio_write_record( vr
);
660 log_fatal( _("%s: error updating version record: %s\n"),
661 db_name
, g10_errstr(rc
));
666 tdbio_db_matches_options()
668 static int yes_no
= -1;
675 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
677 log_fatal( _("%s: error reading version record: %s\n"),
678 db_name
, g10_errstr(rc
) );
680 yes_no
= vr
.r
.ver
.marginals
== opt
.marginals_needed
681 && vr
.r
.ver
.completes
== opt
.completes_needed
682 && vr
.r
.ver
.cert_depth
== opt
.max_cert_depth
683 && vr
.r
.ver
.trust_model
== opt
.trust_model
;
690 tdbio_read_model(void)
695 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
697 log_fatal( _("%s: error reading version record: %s\n"),
698 db_name
, g10_errstr(rc
) );
699 return vr
.r
.ver
.trust_model
;
703 * Return the nextstamp value.
706 tdbio_read_nextcheck ()
711 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
713 log_fatal( _("%s: error reading version record: %s\n"),
714 db_name
, g10_errstr(rc
) );
715 return vr
.r
.ver
.nextcheck
;
718 /* Return true when the stamp was actually changed. */
720 tdbio_write_nextcheck (ulong stamp
)
725 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
727 log_fatal( _("%s: error reading version record: %s\n"),
728 db_name
, g10_errstr(rc
) );
730 if (vr
.r
.ver
.nextcheck
== stamp
)
733 vr
.r
.ver
.nextcheck
= stamp
;
734 rc
= tdbio_write_record( &vr
);
736 log_fatal( _("%s: error writing version record: %s\n"),
737 db_name
, g10_errstr(rc
) );
744 * Return the record number of the trusthash tbl or create a new one.
747 get_trusthashrec(void)
749 static ulong trusthashtbl
; /* record number of the trust hashtable */
751 if( !trusthashtbl
) {
755 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
757 log_fatal( _("%s: error reading version record: %s\n"),
758 db_name
, g10_errstr(rc
) );
759 if( !vr
.r
.ver
.trusthashtbl
)
760 create_hashtable( &vr
, 0 );
762 trusthashtbl
= vr
.r
.ver
.trusthashtbl
;
770 * Update a hashtable.
771 * table gives the start of the table, key and keylen is the key,
772 * newrecnum is the record number to insert.
775 upd_hashtable( ulong table
, byte
*key
, int keylen
, ulong newrecnum
)
777 TRUSTREC lastrec
, rec
;
786 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
787 rc
= tdbio_read_record( hashrec
, &rec
, RECTYPE_HTBL
);
789 log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc
) );
793 item
= rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
794 if( !item
) { /* insert a new item into the hash table */
795 rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = newrecnum
;
796 rc
= tdbio_write_record( &rec
);
798 log_error("upd_hashtable: write htbl failed: %s\n",
803 else if( item
!= newrecnum
) { /* must do an update */
805 rc
= tdbio_read_record( item
, &rec
, 0 );
807 log_error( "upd_hashtable: read item failed: %s\n",
812 if( rec
.rectype
== RECTYPE_HTBL
) {
815 if( level
>= keylen
) {
816 log_error( "hashtable has invalid indirections.\n");
817 return G10ERR_TRUSTDB
;
821 else if( rec
.rectype
== RECTYPE_HLST
) { /* extend list */
822 /* see whether the key is already in this list */
824 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
825 if( rec
.r
.hlst
.rnum
[i
] == newrecnum
) {
826 return 0; /* okay, already in the list */
829 if( rec
.r
.hlst
.next
) {
830 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
833 log_error( "upd_hashtable: read hlst failed: %s\n",
839 break; /* not there */
841 /* find the next free entry and put it in */
843 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
844 if( !rec
.r
.hlst
.rnum
[i
] ) {
845 rec
.r
.hlst
.rnum
[i
] = newrecnum
;
846 rc
= tdbio_write_record( &rec
);
848 log_error( "upd_hashtable: write hlst failed: %s\n",
850 return rc
; /* done */
853 if( rec
.r
.hlst
.next
) {
854 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
855 &rec
, RECTYPE_HLST
);
857 log_error( "upd_hashtable: read hlst failed: %s\n",
862 else { /* add a new list record */
863 rec
.r
.hlst
.next
= item
= tdbio_new_recnum();
864 rc
= tdbio_write_record( &rec
);
866 log_error( "upd_hashtable: write hlst failed: %s\n",
870 memset( &rec
, 0, sizeof rec
);
871 rec
.rectype
= RECTYPE_HLST
;
873 rec
.r
.hlst
.rnum
[0] = newrecnum
;
874 rc
= tdbio_write_record( &rec
);
876 log_error( "upd_hashtable: write ext hlst failed: %s\n",
878 return rc
; /* done */
880 } /* end loop over hlst slots */
882 else if( rec
.rectype
== RECTYPE_TRUST
) { /* insert a list record */
883 if( rec
.recnum
== newrecnum
) {
886 item
= rec
.recnum
; /* save number of key record */
887 memset( &rec
, 0, sizeof rec
);
888 rec
.rectype
= RECTYPE_HLST
;
889 rec
.recnum
= tdbio_new_recnum();
890 rec
.r
.hlst
.rnum
[0] = item
; /* old keyrecord */
891 rec
.r
.hlst
.rnum
[1] = newrecnum
; /* and new one */
892 rc
= tdbio_write_record( &rec
);
894 log_error( "upd_hashtable: write new hlst failed: %s\n",
898 /* update the hashtable record */
899 lastrec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = rec
.recnum
;
900 rc
= tdbio_write_record( &lastrec
);
902 log_error( "upd_hashtable: update htbl failed: %s\n",
904 return rc
; /* ready */
907 log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
908 table
, hashrec
, (msb
% ITEMS_PER_HTBL_RECORD
), item
);
910 return G10ERR_TRUSTDB
;
919 * Drop an entry from a hashtable
920 * table gives the start of the table, key and keylen is the key,
923 drop_from_hashtable( ulong table
, byte
*key
, int keylen
, ulong recnum
)
934 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
935 rc
= tdbio_read_record( hashrec
, &rec
, RECTYPE_HTBL
);
937 log_error("drop_from_hashtable: read failed: %s\n",
942 item
= rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
943 if( !item
) /* not found - forget about it */
946 if( item
== recnum
) { /* tables points direct to the record */
947 rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = 0;
948 rc
= tdbio_write_record( &rec
);
950 log_error("drop_from_hashtable: write htbl failed: %s\n",
955 rc
= tdbio_read_record( item
, &rec
, 0 );
957 log_error( "drop_from_hashtable: read item failed: %s\n",
962 if( rec
.rectype
== RECTYPE_HTBL
) {
965 if( level
>= keylen
) {
966 log_error( "hashtable has invalid indirections.\n");
967 return G10ERR_TRUSTDB
;
972 if( rec
.rectype
== RECTYPE_HLST
) {
974 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
975 if( rec
.r
.hlst
.rnum
[i
] == recnum
) {
976 rec
.r
.hlst
.rnum
[i
] = 0; /* drop */
977 rc
= tdbio_write_record( &rec
);
979 log_error("drop_from_hashtable: write htbl failed: %s\n",
984 if( rec
.r
.hlst
.next
) {
985 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
988 log_error( "drop_from_hashtable: read hlst failed: %s\n",
994 return 0; /* key not in table */
998 log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n",
999 table
, hashrec
, (msb
% ITEMS_PER_HTBL_RECORD
), item
);
1000 return G10ERR_TRUSTDB
;
1006 * Lookup a record via the hashtable tablewith key/keylen and return the
1007 * result in rec. cmp() should return if the record is the desired one.
1008 * Returns -1 if not found, 0 if found or another errocode
1011 lookup_hashtable( ulong table
, const byte
*key
, size_t keylen
,
1012 int (*cmpfnc
)(const void*, const TRUSTREC
*),
1013 const void *cmpdata
, TRUSTREC
*rec
)
1016 ulong hashrec
, item
;
1023 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
1024 rc
= tdbio_read_record( hashrec
, rec
, RECTYPE_HTBL
);
1026 log_error("lookup_hashtable failed: %s\n", g10_errstr(rc
) );
1030 item
= rec
->r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
1032 return -1; /* not found */
1034 rc
= tdbio_read_record( item
, rec
, 0 );
1036 log_error( "hashtable read failed: %s\n", g10_errstr(rc
) );
1039 if( rec
->rectype
== RECTYPE_HTBL
) {
1042 if( level
>= keylen
) {
1043 log_error("hashtable has invalid indirections\n");
1044 return G10ERR_TRUSTDB
;
1048 else if( rec
->rectype
== RECTYPE_HLST
) {
1052 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1053 if( rec
->r
.hlst
.rnum
[i
] ) {
1056 rc
= tdbio_read_record( rec
->r
.hlst
.rnum
[i
], &tmp
, 0 );
1058 log_error( "lookup_hashtable: read item failed: %s\n",
1062 if( (*cmpfnc
)( cmpdata
, &tmp
) ) {
1068 if( rec
->r
.hlst
.next
) {
1069 rc
= tdbio_read_record( rec
->r
.hlst
.next
, rec
, RECTYPE_HLST
);
1071 log_error( "lookup_hashtable: read hlst failed: %s\n",
1077 return -1; /* not found */
1082 if( (*cmpfnc
)( cmpdata
, rec
) )
1083 return 0; /* really found */
1085 return -1; /* no: not found */
1090 * Update the trust hashtbl or create the table if it does not exist
1093 update_trusthashtbl( TRUSTREC
*tr
)
1095 return upd_hashtable( get_trusthashrec(),
1096 tr
->r
.trust
.fingerprint
, 20, tr
->recnum
);
1102 tdbio_dump_record( TRUSTREC
*rec
, FILE *fp
)
1105 ulong rnum
= rec
->recnum
;
1107 fprintf(fp
, "rec %5lu, ", rnum
);
1109 switch( rec
->rectype
) {
1110 case 0: fprintf(fp
, "blank\n");
1112 case RECTYPE_VER
: fprintf(fp
,
1113 "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d nc=%lu (%s)\n",
1114 rec
->r
.ver
.trusthashtbl
,
1115 rec
->r
.ver
.firstfree
,
1116 rec
->r
.ver
.marginals
,
1117 rec
->r
.ver
.completes
,
1118 rec
->r
.ver
.cert_depth
,
1119 rec
->r
.ver
.trust_model
,
1120 rec
->r
.ver
.nextcheck
,
1121 strtimestamp(rec
->r
.ver
.nextcheck
)
1124 case RECTYPE_FREE
: fprintf(fp
, "free, next=%lu\n", rec
->r
.free
.next
);
1127 fprintf(fp
, "htbl,");
1128 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ )
1129 fprintf(fp
, " %lu", rec
->r
.htbl
.item
[i
] );
1133 fprintf(fp
, "hlst, next=%lu,", rec
->r
.hlst
.next
);
1134 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ )
1135 fprintf(fp
, " %lu", rec
->r
.hlst
.rnum
[i
] );
1139 fprintf(fp
, "trust ");
1140 for(i
=0; i
< 20; i
++ )
1141 fprintf(fp
, "%02X", rec
->r
.trust
.fingerprint
[i
] );
1142 fprintf (fp
, ", ot=%d, d=%d, vl=%lu\n", rec
->r
.trust
.ownertrust
,
1143 rec
->r
.trust
.depth
, rec
->r
.trust
.validlist
);
1146 fprintf(fp
, "valid ");
1147 for(i
=0; i
< 20; i
++ )
1148 fprintf(fp
, "%02X", rec
->r
.valid
.namehash
[i
] );
1149 fprintf (fp
, ", v=%d, next=%lu\n", rec
->r
.valid
.validity
,
1153 fprintf(fp
, "unknown type %d\n", rec
->rectype
);
1159 * read the record with number recnum
1160 * returns: -1 on error, 0 on success
1163 tdbio_read_record( ulong recnum
, TRUSTREC
*rec
, int expected
)
1165 byte readbuf
[TRUST_RECORD_LEN
];
1166 const byte
*buf
, *p
;
1167 gpg_error_t err
= 0;
1172 buf
= get_record_from_cache( recnum
);
1174 if( lseek( db_fd
, recnum
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
1175 err
= gpg_error_from_syserror ();
1176 log_error(_("trustdb: lseek failed: %s\n"), strerror(errno
) );
1179 n
= read( db_fd
, readbuf
, TRUST_RECORD_LEN
);
1181 return -1; /* eof */
1183 else if( n
!= TRUST_RECORD_LEN
) {
1184 err
= gpg_error_from_syserror ();
1185 log_error(_("trustdb: read failed (n=%d): %s\n"), n
,
1191 rec
->recnum
= recnum
;
1194 rec
->rectype
= *p
++;
1195 if( expected
&& rec
->rectype
!= expected
) {
1196 log_error("%lu: read expected rec type %d, got %d\n",
1197 recnum
, expected
, rec
->rectype
);
1198 return gpg_error (GPG_ERR_TRUSTDB
);
1200 p
++; /* skip reserved byte */
1201 switch( rec
->rectype
) {
1202 case 0: /* unused (free) record */
1204 case RECTYPE_VER
: /* version record */
1205 if( memcmp(buf
+1, "gpg", 3 ) ) {
1206 log_error( _("%s: not a trustdb file\n"), db_name
);
1207 err
= gpg_error (GPG_ERR_TRUSTDB
);
1209 p
+= 2; /* skip "gpg" */
1210 rec
->r
.ver
.version
= *p
++;
1211 rec
->r
.ver
.marginals
= *p
++;
1212 rec
->r
.ver
.completes
= *p
++;
1213 rec
->r
.ver
.cert_depth
= *p
++;
1214 rec
->r
.ver
.trust_model
= *p
++;
1216 rec
->r
.ver
.created
= buftoulong(p
); p
+= 4;
1217 rec
->r
.ver
.nextcheck
= buftoulong(p
); p
+= 4;
1220 rec
->r
.ver
.firstfree
=buftoulong(p
); p
+= 4;
1222 rec
->r
.ver
.trusthashtbl
=buftoulong(p
); p
+= 4;
1224 log_error( _("%s: version record with recnum %lu\n"), db_name
,
1226 err
= gpg_error (GPG_ERR_TRUSTDB
);
1228 else if( rec
->r
.ver
.version
!= 3 ) {
1229 log_error( _("%s: invalid file version %d\n"), db_name
,
1230 rec
->r
.ver
.version
);
1231 err
= gpg_error (GPG_ERR_TRUSTDB
);
1235 rec
->r
.free
.next
= buftoulong(p
); p
+= 4;
1238 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ ) {
1239 rec
->r
.htbl
.item
[i
] = buftoulong(p
); p
+= 4;
1243 rec
->r
.hlst
.next
= buftoulong(p
); p
+= 4;
1244 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1245 rec
->r
.hlst
.rnum
[i
] = buftoulong(p
); p
+= 4;
1249 memcpy( rec
->r
.trust
.fingerprint
, p
, 20); p
+=20;
1250 rec
->r
.trust
.ownertrust
= *p
++;
1251 rec
->r
.trust
.depth
= *p
++;
1252 rec
->r
.trust
.min_ownertrust
= *p
++;
1254 rec
->r
.trust
.validlist
= buftoulong(p
); p
+= 4;
1257 memcpy( rec
->r
.valid
.namehash
, p
, 20); p
+=20;
1258 rec
->r
.valid
.validity
= *p
++;
1259 rec
->r
.valid
.next
= buftoulong(p
); p
+= 4;
1260 rec
->r
.valid
.full_count
= *p
++;
1261 rec
->r
.valid
.marginal_count
= *p
++;
1264 log_error( "%s: invalid record type %d at recnum %lu\n",
1265 db_name
, rec
->rectype
, (ulong
)recnum
);
1266 err
= gpg_error (GPG_ERR_TRUSTDB
);
1274 * Write the record at RECNUM
1277 tdbio_write_record( TRUSTREC
*rec
)
1279 byte buf
[TRUST_RECORD_LEN
], *p
;
1282 ulong recnum
= rec
->recnum
;
1287 memset(buf
, 0, TRUST_RECORD_LEN
);
1289 *p
++ = rec
->rectype
; p
++;
1290 switch( rec
->rectype
) {
1291 case 0: /* unused record */
1293 case RECTYPE_VER
: /* version record */
1296 memcpy(p
-1, "gpg", 3 ); p
+= 2;
1297 *p
++ = rec
->r
.ver
.version
;
1298 *p
++ = rec
->r
.ver
.marginals
;
1299 *p
++ = rec
->r
.ver
.completes
;
1300 *p
++ = rec
->r
.ver
.cert_depth
;
1301 *p
++ = rec
->r
.ver
.trust_model
;
1303 ulongtobuf(p
, rec
->r
.ver
.created
); p
+= 4;
1304 ulongtobuf(p
, rec
->r
.ver
.nextcheck
); p
+= 4;
1307 ulongtobuf(p
, rec
->r
.ver
.firstfree
); p
+= 4;
1309 ulongtobuf(p
, rec
->r
.ver
.trusthashtbl
); p
+= 4;
1313 ulongtobuf(p
, rec
->r
.free
.next
); p
+= 4;
1318 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ ) {
1319 ulongtobuf( p
, rec
->r
.htbl
.item
[i
]); p
+= 4;
1324 ulongtobuf( p
, rec
->r
.hlst
.next
); p
+= 4;
1325 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1326 ulongtobuf( p
, rec
->r
.hlst
.rnum
[i
]); p
+= 4;
1331 memcpy( p
, rec
->r
.trust
.fingerprint
, 20); p
+= 20;
1332 *p
++ = rec
->r
.trust
.ownertrust
;
1333 *p
++ = rec
->r
.trust
.depth
;
1334 *p
++ = rec
->r
.trust
.min_ownertrust
;
1336 ulongtobuf( p
, rec
->r
.trust
.validlist
); p
+= 4;
1340 memcpy( p
, rec
->r
.valid
.namehash
, 20); p
+= 20;
1341 *p
++ = rec
->r
.valid
.validity
;
1342 ulongtobuf( p
, rec
->r
.valid
.next
); p
+= 4;
1343 *p
++ = rec
->r
.valid
.full_count
;
1344 *p
++ = rec
->r
.valid
.marginal_count
;
1351 rc
= put_record_into_cache( recnum
, buf
);
1354 else if( rec
->rectype
== RECTYPE_TRUST
)
1355 rc
= update_trusthashtbl( rec
);
1361 tdbio_delete_record( ulong recnum
)
1366 /* Must read the record fist, so we can drop it from the hash tables */
1367 rc
= tdbio_read_record( recnum
, &rec
, 0 );
1370 else if( rec
.rectype
== RECTYPE_TRUST
) {
1371 rc
= drop_from_hashtable( get_trusthashrec(),
1372 rec
.r
.trust
.fingerprint
, 20, rec
.recnum
);
1378 /* now we can chnage it to a free record */
1379 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
1381 log_fatal( _("%s: error reading version record: %s\n"),
1382 db_name
, g10_errstr(rc
) );
1384 rec
.recnum
= recnum
;
1385 rec
.rectype
= RECTYPE_FREE
;
1386 rec
.r
.free
.next
= vr
.r
.ver
.firstfree
;
1387 vr
.r
.ver
.firstfree
= recnum
;
1388 rc
= tdbio_write_record( &rec
);
1390 rc
= tdbio_write_record( &vr
);
1395 * create a new record and return its record number
1405 /* look for unused records */
1406 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
1408 log_fatal( _("%s: error reading version record: %s\n"),
1409 db_name
, g10_errstr(rc
) );
1410 if( vr
.r
.ver
.firstfree
) {
1411 recnum
= vr
.r
.ver
.firstfree
;
1412 rc
= tdbio_read_record( recnum
, &rec
, RECTYPE_FREE
);
1414 log_error( _("%s: error reading free record: %s\n"),
1415 db_name
, g10_errstr(rc
) );
1418 /* update dir record */
1419 vr
.r
.ver
.firstfree
= rec
.r
.free
.next
;
1420 rc
= tdbio_write_record( &vr
);
1422 log_error( _("%s: error writing dir record: %s\n"),
1423 db_name
, g10_errstr(rc
) );
1426 /*zero out the new record */
1427 memset( &rec
, 0, sizeof rec
);
1428 rec
.rectype
= 0; /* unused record */
1429 rec
.recnum
= recnum
;
1430 rc
= tdbio_write_record( &rec
);
1432 log_fatal(_("%s: failed to zero a record: %s\n"),
1433 db_name
, g10_errstr(rc
));
1435 else { /* not found, append a new record */
1436 offset
= lseek( db_fd
, 0, SEEK_END
);
1438 log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno
) );
1439 recnum
= offset
/ TRUST_RECORD_LEN
;
1440 assert(recnum
); /* this is will never be the first record */
1441 /* we must write a record, so that the next call to this function
1442 * returns another recnum */
1443 memset( &rec
, 0, sizeof rec
);
1444 rec
.rectype
= 0; /* unused record */
1445 rec
.recnum
= recnum
;
1447 if( lseek( db_fd
, recnum
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
1448 rc
= gpg_error_from_syserror ();
1449 log_error(_("trustdb rec %lu: lseek failed: %s\n"),
1450 recnum
, strerror(errno
) );
1453 int n
= write( db_fd
, &rec
, TRUST_RECORD_LEN
);
1454 if( n
!= TRUST_RECORD_LEN
) {
1455 rc
= gpg_error_from_syserror ();
1456 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
1457 recnum
, n
, strerror(errno
) );
1462 log_fatal(_("%s: failed to append a record: %s\n"),
1463 db_name
, g10_errstr(rc
));
1471 cmp_trec_fpr ( const void *fpr
, const TRUSTREC
*rec
)
1473 return (rec
->rectype
== RECTYPE_TRUST
1474 && !memcmp (rec
->r
.trust
.fingerprint
, fpr
, 20));
1479 tdbio_search_trust_byfpr( const byte
*fingerprint
, TRUSTREC
*rec
)
1483 /* locate the trust record using the hash table */
1484 rc
= lookup_hashtable( get_trusthashrec(), fingerprint
, 20,
1485 cmp_trec_fpr
, fingerprint
, rec
);
1490 tdbio_search_trust_bypk (PKT_public_key
*pk
, TRUSTREC
*rec
)
1492 byte fingerprint
[MAX_FINGERPRINT_LEN
];
1495 fingerprint_from_pk( pk
, fingerprint
, &fingerlen
);
1496 for (; fingerlen
< 20; fingerlen
++ )
1497 fingerprint
[fingerlen
] = 0;
1498 return tdbio_search_trust_byfpr (fingerprint
, rec
);
1505 log_error (_("Error: The trustdb is corrupted.\n"));
1506 how_to_fix_the_trustdb ();