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 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);
100 /*************************************
101 ************* record cache **********
102 *************************************/
105 * Get the data from therecord cache and return a
106 * pointer into that cache. Caller should copy
107 * the return data. NULL is returned on a cache miss.
110 get_record_from_cache( ulong recno
)
114 for( r
= cache_list
; r
; r
= r
->next
) {
115 if( r
->flags
.used
&& r
->recno
== recno
)
123 write_cache_item( CACHE_CTRL r
)
128 if( lseek( db_fd
, r
->recno
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
129 err
= gpg_error_from_syserror ();
130 log_error(_("trustdb rec %lu: lseek failed: %s\n"),
131 r
->recno
, strerror(errno
) );
134 n
= write( db_fd
, r
->data
, TRUST_RECORD_LEN
);
135 if( n
!= TRUST_RECORD_LEN
) {
136 err
= gpg_error_from_syserror ();
137 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
138 r
->recno
, n
, strerror(errno
) );
146 * Put data into the cache. This function may flush the
147 * some cache entries if there is not enough space available.
150 put_record_into_cache( ulong recno
, const char *data
)
152 CACHE_CTRL r
, unused
;
156 /* see whether we already cached this one */
157 for( unused
= NULL
, r
= cache_list
; r
; r
= r
->next
) {
158 if( !r
->flags
.used
) {
162 else if( r
->recno
== recno
) {
163 if( !r
->flags
.dirty
) {
164 /* Hmmm: should we use a a copy and compare? */
165 if( memcmp(r
->data
, data
, TRUST_RECORD_LEN
) ) {
170 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
173 if( r
->flags
.used
) {
180 /* not in the cache: add a new entry */
181 if( unused
) { /* reuse this entry */
185 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
191 /* see whether we reached the limit */
192 if( cache_entries
< MAX_CACHE_ENTRIES_SOFT
) { /* no */
193 r
= xmalloc( sizeof *r
);
196 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
198 r
->next
= cache_list
;
204 /* cache is full: discard some clean entries */
206 int n
= clean_count
/ 3; /* discard a third of the clean entries */
209 for( unused
= NULL
, r
= cache_list
; r
; r
= r
->next
) {
210 if( r
->flags
.used
&& !r
->flags
.dirty
) {
223 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
229 /* no clean entries: have to flush some dirty entries */
230 if( in_transaction
) {
231 /* but we can't do this while in a transaction
232 * we increase the cache size instead */
233 if( cache_entries
< MAX_CACHE_ENTRIES_HARD
) { /* no */
234 if( opt
.debug
&& !(cache_entries
% 100) )
235 log_debug("increasing tdbio cache size\n");
236 r
= xmalloc( sizeof *r
);
239 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
241 r
->next
= cache_list
;
247 log_info(_("trustdb transaction too large\n"));
248 return G10ERR_RESOURCE_LIMIT
;
251 int n
= dirty_count
/ 5; /* discard some dirty entries */
255 if( make_dotlock( lockhandle
, -1 ) )
256 log_fatal("can't acquire lock - giving up\n");
260 for( unused
= NULL
, r
= cache_list
; r
; r
= r
->next
) {
261 if( r
->flags
.used
&& r
->flags
.dirty
) {
262 int rc
= write_cache_item( r
);
273 if( !opt
.lock_once
) {
274 if( !release_dotlock( lockhandle
) )
281 memcpy( r
->data
, data
, TRUST_RECORD_LEN
);
294 return cache_is_dirty
;
299 * Flush the cache. This cannot be used while in a transaction.
310 log_bug("tdbio: syncing while in transaction\n");
312 if( !cache_is_dirty
)
316 if( make_dotlock( lockhandle
, -1 ) )
317 log_fatal("can't acquire lock - giving up\n");
322 for( r
= cache_list
; r
; r
= r
->next
) {
323 if( r
->flags
.used
&& r
->flags
.dirty
) {
324 int rc
= write_cache_item( r
);
330 if( did_lock
&& !opt
.lock_once
) {
331 if( !release_dotlock( lockhandle
) )
339 /* The transaction code is disabled in the 1.2.x branch, as it is not
340 yet used. It will be enabled in 1.3.x. */
343 * Simple transactions system:
344 * Everything between begin_transaction and end/cancel_transaction
345 * is not immediatly written but at the time of end_transaction.
349 tdbio_begin_transaction()
354 log_bug("tdbio: nested transactions\n");
355 /* flush everything out */
364 tdbio_end_transaction()
368 if( !in_transaction
)
369 log_bug("tdbio: no active transaction\n");
371 if( make_dotlock( lockhandle
, -1 ) )
372 log_fatal("can't acquire lock - giving up\n");
379 unblock_all_signals();
380 if( !opt
.lock_once
) {
381 if( !release_dotlock( lockhandle
) )
388 tdbio_cancel_transaction()
392 if( !in_transaction
)
393 log_bug("tdbio: no active transaction\n");
395 /* remove all dirty marked entries, so that the original ones
396 * are read back the next time */
397 if( cache_is_dirty
) {
398 for( r
= cache_list
; r
; r
= r
->next
) {
399 if( r
->flags
.used
&& r
->flags
.dirty
) {
413 /********************************************************
414 **************** cached I/O functions ******************
415 ********************************************************/
421 if( !release_dotlock(lockhandle
) )
426 /* Caller must sync */
428 tdbio_update_version_record (void)
433 memset( &rec
, 0, sizeof rec
);
435 rc
=tdbio_read_record( 0, &rec
, RECTYPE_VER
);
438 rec
.r
.ver
.created
= make_timestamp();
439 rec
.r
.ver
.marginals
= opt
.marginals_needed
;
440 rec
.r
.ver
.completes
= opt
.completes_needed
;
441 rec
.r
.ver
.cert_depth
= opt
.max_cert_depth
;
442 rec
.r
.ver
.trust_model
= opt
.trust_model
;
443 rc
=tdbio_write_record(&rec
);
450 create_version_record (void)
455 memset( &rec
, 0, sizeof rec
);
456 rec
.r
.ver
.version
= 3;
457 rec
.r
.ver
.created
= make_timestamp();
458 rec
.r
.ver
.marginals
= opt
.marginals_needed
;
459 rec
.r
.ver
.completes
= opt
.completes_needed
;
460 rec
.r
.ver
.cert_depth
= opt
.max_cert_depth
;
461 if(opt
.trust_model
==TM_PGP
|| opt
.trust_model
==TM_CLASSIC
)
462 rec
.r
.ver
.trust_model
= opt
.trust_model
;
464 rec
.r
.ver
.trust_model
= TM_PGP
;
465 rec
.rectype
= RECTYPE_VER
;
467 rc
= tdbio_write_record( &rec
);
476 tdbio_set_dbname( const char *new_dbname
, int create
)
479 static int initialized
= 0;
487 fname
=make_filename(opt
.homedir
,"trustdb" EXTSEP_S
"gpg", NULL
);
488 else if (*new_dbname
!= DIRSEP_C
)
490 if (strchr(new_dbname
, DIRSEP_C
) )
491 fname
= make_filename (new_dbname
, NULL
);
493 fname
= make_filename (opt
.homedir
, new_dbname
, NULL
);
496 fname
= xstrdup (new_dbname
);
498 if( access( fname
, R_OK
) ) {
499 if( errno
!= ENOENT
) {
500 log_error( _("can't access `%s': %s\n"), fname
, strerror(errno
) );
502 return G10ERR_TRUSTDB
;
508 char *p
= strrchr( fname
, DIRSEP_C
);
513 if( access( fname
, F_OK
) ) {
514 try_make_homedir( fname
);
515 log_fatal( _("%s: directory does not exist!\n"), fname
);
523 lockhandle
= create_dotlock( db_name
);
525 log_fatal( _("can't create lock for `%s'\n"), db_name
);
526 if( make_dotlock( lockhandle
, -1 ) )
527 log_fatal( _("can't lock `%s'\n"), db_name
);
528 #endif /* __riscos__ */
530 if (is_secured_filename (fname
)) {
535 fp
=fopen( fname
, "wb" );
538 log_fatal( _("can't create `%s': %s\n"), fname
, strerror(errno
) );
540 db_fd
= open( db_name
, O_RDWR
| MY_O_BINARY
);
542 log_fatal( _("can't open `%s': %s\n"), db_name
, strerror(errno
) );
546 lockhandle
= create_dotlock( db_name
);
548 log_fatal( _("can't create lock for `%s'\n"), db_name
);
549 #endif /* !__riscos__ */
551 rc
= create_version_record ();
553 log_fatal( _("%s: failed to create version record: %s"),
554 fname
, g10_errstr(rc
));
555 /* and read again to check that we are okay */
556 if( tdbio_read_record( 0, &rec
, RECTYPE_VER
) )
557 log_fatal( _("%s: invalid trustdb created\n"), db_name
);
560 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 /* Read the version record. */
609 if (tdbio_read_record (0, &rec
, RECTYPE_VER
) )
610 log_fatal( _("%s: invalid trustdb\n"), db_name
);
615 * Make a hashtable: type 0 = trust hash
618 create_hashtable( TRUSTREC
*vr
, int type
)
625 offset
= lseek( db_fd
, 0, SEEK_END
);
627 log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno
) );
628 recnum
= offset
/ TRUST_RECORD_LEN
;
629 assert(recnum
); /* this is will never be the first record */
632 vr
->r
.ver
.trusthashtbl
= recnum
;
634 /* Now write the records */
635 n
= (256+ITEMS_PER_HTBL_RECORD
-1) / ITEMS_PER_HTBL_RECORD
;
636 for(i
=0; i
< n
; i
++, recnum
++ ) {
637 memset( &rec
, 0, sizeof rec
);
638 rec
.rectype
= RECTYPE_HTBL
;
640 rc
= tdbio_write_record( &rec
);
642 log_fatal( _("%s: failed to create hashtable: %s\n"),
643 db_name
, g10_errstr(rc
));
645 /* update the version record */
646 rc
= tdbio_write_record( vr
);
650 log_fatal( _("%s: error updating version record: %s\n"),
651 db_name
, g10_errstr(rc
));
656 tdbio_db_matches_options()
658 static int yes_no
= -1;
665 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
667 log_fatal( _("%s: error reading version record: %s\n"),
668 db_name
, g10_errstr(rc
) );
670 yes_no
= vr
.r
.ver
.marginals
== opt
.marginals_needed
671 && vr
.r
.ver
.completes
== opt
.completes_needed
672 && vr
.r
.ver
.cert_depth
== opt
.max_cert_depth
673 && vr
.r
.ver
.trust_model
== opt
.trust_model
;
680 tdbio_read_model(void)
685 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
687 log_fatal( _("%s: error reading version record: %s\n"),
688 db_name
, g10_errstr(rc
) );
689 return vr
.r
.ver
.trust_model
;
693 * Return the nextstamp value.
696 tdbio_read_nextcheck ()
701 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
703 log_fatal( _("%s: error reading version record: %s\n"),
704 db_name
, g10_errstr(rc
) );
705 return vr
.r
.ver
.nextcheck
;
708 /* Return true when the stamp was actually changed. */
710 tdbio_write_nextcheck (ulong stamp
)
715 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
717 log_fatal( _("%s: error reading version record: %s\n"),
718 db_name
, g10_errstr(rc
) );
720 if (vr
.r
.ver
.nextcheck
== stamp
)
723 vr
.r
.ver
.nextcheck
= stamp
;
724 rc
= tdbio_write_record( &vr
);
726 log_fatal( _("%s: error writing version record: %s\n"),
727 db_name
, g10_errstr(rc
) );
734 * Return the record number of the trusthash tbl or create a new one.
737 get_trusthashrec(void)
739 static ulong trusthashtbl
; /* record number of the trust hashtable */
741 if( !trusthashtbl
) {
745 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
747 log_fatal( _("%s: error reading version record: %s\n"),
748 db_name
, g10_errstr(rc
) );
749 if( !vr
.r
.ver
.trusthashtbl
)
750 create_hashtable( &vr
, 0 );
752 trusthashtbl
= vr
.r
.ver
.trusthashtbl
;
760 * Update a hashtable.
761 * table gives the start of the table, key and keylen is the key,
762 * newrecnum is the record number to insert.
765 upd_hashtable( ulong table
, byte
*key
, int keylen
, ulong newrecnum
)
767 TRUSTREC lastrec
, rec
;
776 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
777 rc
= tdbio_read_record( hashrec
, &rec
, RECTYPE_HTBL
);
779 log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc
) );
783 item
= rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
784 if( !item
) { /* insert a new item into the hash table */
785 rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = newrecnum
;
786 rc
= tdbio_write_record( &rec
);
788 log_error("upd_hashtable: write htbl failed: %s\n",
793 else if( item
!= newrecnum
) { /* must do an update */
795 rc
= tdbio_read_record( item
, &rec
, 0 );
797 log_error( "upd_hashtable: read item failed: %s\n",
802 if( rec
.rectype
== RECTYPE_HTBL
) {
805 if( level
>= keylen
) {
806 log_error( "hashtable has invalid indirections.\n");
807 return G10ERR_TRUSTDB
;
811 else if( rec
.rectype
== RECTYPE_HLST
) { /* extend list */
812 /* see whether the key is already in this list */
814 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
815 if( rec
.r
.hlst
.rnum
[i
] == newrecnum
) {
816 return 0; /* okay, already in the list */
819 if( rec
.r
.hlst
.next
) {
820 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
823 log_error( "upd_hashtable: read hlst failed: %s\n",
829 break; /* not there */
831 /* find the next free entry and put it in */
833 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
834 if( !rec
.r
.hlst
.rnum
[i
] ) {
835 rec
.r
.hlst
.rnum
[i
] = newrecnum
;
836 rc
= tdbio_write_record( &rec
);
838 log_error( "upd_hashtable: write hlst failed: %s\n",
840 return rc
; /* done */
843 if( rec
.r
.hlst
.next
) {
844 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
845 &rec
, RECTYPE_HLST
);
847 log_error( "upd_hashtable: read hlst failed: %s\n",
852 else { /* add a new list record */
853 rec
.r
.hlst
.next
= item
= tdbio_new_recnum();
854 rc
= tdbio_write_record( &rec
);
856 log_error( "upd_hashtable: write hlst failed: %s\n",
860 memset( &rec
, 0, sizeof rec
);
861 rec
.rectype
= RECTYPE_HLST
;
863 rec
.r
.hlst
.rnum
[0] = newrecnum
;
864 rc
= tdbio_write_record( &rec
);
866 log_error( "upd_hashtable: write ext hlst failed: %s\n",
868 return rc
; /* done */
870 } /* end loop over hlst slots */
872 else if( rec
.rectype
== RECTYPE_TRUST
) { /* insert a list record */
873 if( rec
.recnum
== newrecnum
) {
876 item
= rec
.recnum
; /* save number of key record */
877 memset( &rec
, 0, sizeof rec
);
878 rec
.rectype
= RECTYPE_HLST
;
879 rec
.recnum
= tdbio_new_recnum();
880 rec
.r
.hlst
.rnum
[0] = item
; /* old keyrecord */
881 rec
.r
.hlst
.rnum
[1] = newrecnum
; /* and new one */
882 rc
= tdbio_write_record( &rec
);
884 log_error( "upd_hashtable: write new hlst failed: %s\n",
888 /* update the hashtable record */
889 lastrec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = rec
.recnum
;
890 rc
= tdbio_write_record( &lastrec
);
892 log_error( "upd_hashtable: update htbl failed: %s\n",
894 return rc
; /* ready */
897 log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
898 table
, hashrec
, (msb
% ITEMS_PER_HTBL_RECORD
), item
);
900 return G10ERR_TRUSTDB
;
909 * Drop an entry from a hashtable
910 * table gives the start of the table, key and keylen is the key,
913 drop_from_hashtable( ulong table
, byte
*key
, int keylen
, ulong recnum
)
924 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
925 rc
= tdbio_read_record( hashrec
, &rec
, RECTYPE_HTBL
);
927 log_error("drop_from_hashtable: read failed: %s\n",
932 item
= rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
933 if( !item
) /* not found - forget about it */
936 if( item
== recnum
) { /* tables points direct to the record */
937 rec
.r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
] = 0;
938 rc
= tdbio_write_record( &rec
);
940 log_error("drop_from_hashtable: write htbl failed: %s\n",
945 rc
= tdbio_read_record( item
, &rec
, 0 );
947 log_error( "drop_from_hashtable: read item failed: %s\n",
952 if( rec
.rectype
== RECTYPE_HTBL
) {
955 if( level
>= keylen
) {
956 log_error( "hashtable has invalid indirections.\n");
957 return G10ERR_TRUSTDB
;
962 if( rec
.rectype
== RECTYPE_HLST
) {
964 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
965 if( rec
.r
.hlst
.rnum
[i
] == recnum
) {
966 rec
.r
.hlst
.rnum
[i
] = 0; /* drop */
967 rc
= tdbio_write_record( &rec
);
969 log_error("drop_from_hashtable: write htbl failed: %s\n",
974 if( rec
.r
.hlst
.next
) {
975 rc
= tdbio_read_record( rec
.r
.hlst
.next
,
978 log_error( "drop_from_hashtable: read hlst failed: %s\n",
984 return 0; /* key not in table */
988 log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n",
989 table
, hashrec
, (msb
% ITEMS_PER_HTBL_RECORD
), item
);
990 return G10ERR_TRUSTDB
;
996 * Lookup a record via the hashtable tablewith key/keylen and return the
997 * result in rec. cmp() should return if the record is the desired one.
998 * Returns -1 if not found, 0 if found or another errocode
1001 lookup_hashtable( ulong table
, const byte
*key
, size_t keylen
,
1002 int (*cmpfnc
)(void*, const TRUSTREC
*), void *cmpdata
,
1006 ulong hashrec
, item
;
1013 hashrec
+= msb
/ ITEMS_PER_HTBL_RECORD
;
1014 rc
= tdbio_read_record( hashrec
, rec
, RECTYPE_HTBL
);
1016 log_error("lookup_hashtable failed: %s\n", g10_errstr(rc
) );
1020 item
= rec
->r
.htbl
.item
[msb
% ITEMS_PER_HTBL_RECORD
];
1022 return -1; /* not found */
1024 rc
= tdbio_read_record( item
, rec
, 0 );
1026 log_error( "hashtable read failed: %s\n", g10_errstr(rc
) );
1029 if( rec
->rectype
== RECTYPE_HTBL
) {
1032 if( level
>= keylen
) {
1033 log_error("hashtable has invalid indirections\n");
1034 return G10ERR_TRUSTDB
;
1038 else if( rec
->rectype
== RECTYPE_HLST
) {
1042 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1043 if( rec
->r
.hlst
.rnum
[i
] ) {
1046 rc
= tdbio_read_record( rec
->r
.hlst
.rnum
[i
], &tmp
, 0 );
1048 log_error( "lookup_hashtable: read item failed: %s\n",
1052 if( (*cmpfnc
)( cmpdata
, &tmp
) ) {
1058 if( rec
->r
.hlst
.next
) {
1059 rc
= tdbio_read_record( rec
->r
.hlst
.next
, rec
, RECTYPE_HLST
);
1061 log_error( "lookup_hashtable: read hlst failed: %s\n",
1067 return -1; /* not found */
1072 if( (*cmpfnc
)( cmpdata
, rec
) )
1073 return 0; /* really found */
1075 return -1; /* no: not found */
1080 * Update the trust hashtbl or create the table if it does not exist
1083 update_trusthashtbl( TRUSTREC
*tr
)
1085 return upd_hashtable( get_trusthashrec(),
1086 tr
->r
.trust
.fingerprint
, 20, tr
->recnum
);
1092 tdbio_dump_record( TRUSTREC
*rec
, FILE *fp
)
1095 ulong rnum
= rec
->recnum
;
1097 fprintf(fp
, "rec %5lu, ", rnum
);
1099 switch( rec
->rectype
) {
1100 case 0: fprintf(fp
, "blank\n");
1102 case RECTYPE_VER
: fprintf(fp
,
1103 "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d nc=%lu (%s)\n",
1104 rec
->r
.ver
.trusthashtbl
,
1105 rec
->r
.ver
.firstfree
,
1106 rec
->r
.ver
.marginals
,
1107 rec
->r
.ver
.completes
,
1108 rec
->r
.ver
.cert_depth
,
1109 rec
->r
.ver
.trust_model
,
1110 rec
->r
.ver
.nextcheck
,
1111 strtimestamp(rec
->r
.ver
.nextcheck
)
1114 case RECTYPE_FREE
: fprintf(fp
, "free, next=%lu\n", rec
->r
.free
.next
);
1117 fprintf(fp
, "htbl,");
1118 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ )
1119 fprintf(fp
, " %lu", rec
->r
.htbl
.item
[i
] );
1123 fprintf(fp
, "hlst, next=%lu,", rec
->r
.hlst
.next
);
1124 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ )
1125 fprintf(fp
, " %lu", rec
->r
.hlst
.rnum
[i
] );
1129 fprintf(fp
, "trust ");
1130 for(i
=0; i
< 20; i
++ )
1131 fprintf(fp
, "%02X", rec
->r
.trust
.fingerprint
[i
] );
1132 fprintf (fp
, ", ot=%d, d=%d, vl=%lu\n", rec
->r
.trust
.ownertrust
,
1133 rec
->r
.trust
.depth
, rec
->r
.trust
.validlist
);
1136 fprintf(fp
, "valid ");
1137 for(i
=0; i
< 20; i
++ )
1138 fprintf(fp
, "%02X", rec
->r
.valid
.namehash
[i
] );
1139 fprintf (fp
, ", v=%d, next=%lu\n", rec
->r
.valid
.validity
,
1143 fprintf(fp
, "unknown type %d\n", rec
->rectype
);
1149 * read the record with number recnum
1150 * returns: -1 on error, 0 on success
1153 tdbio_read_record( ulong recnum
, TRUSTREC
*rec
, int expected
)
1155 byte readbuf
[TRUST_RECORD_LEN
];
1156 const byte
*buf
, *p
;
1157 gpg_error_t err
= 0;
1162 buf
= get_record_from_cache( recnum
);
1164 if( lseek( db_fd
, recnum
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
1165 err
= gpg_error_from_syserror ();
1166 log_error(_("trustdb: lseek failed: %s\n"), strerror(errno
) );
1169 n
= read( db_fd
, readbuf
, TRUST_RECORD_LEN
);
1171 return -1; /* eof */
1173 else if( n
!= TRUST_RECORD_LEN
) {
1174 err
= gpg_error_from_syserror ();
1175 log_error(_("trustdb: read failed (n=%d): %s\n"), n
,
1181 rec
->recnum
= recnum
;
1184 rec
->rectype
= *p
++;
1185 if( expected
&& rec
->rectype
!= expected
) {
1186 log_error("%lu: read expected rec type %d, got %d\n",
1187 recnum
, expected
, rec
->rectype
);
1188 return gpg_error (GPG_ERR_TRUSTDB
);
1190 p
++; /* skip reserved byte */
1191 switch( rec
->rectype
) {
1192 case 0: /* unused (free) record */
1194 case RECTYPE_VER
: /* version record */
1195 if( memcmp(buf
+1, "gpg", 3 ) ) {
1196 log_error( _("%s: not a trustdb file\n"), db_name
);
1197 err
= gpg_error (GPG_ERR_TRUSTDB
);
1199 p
+= 2; /* skip "gpg" */
1200 rec
->r
.ver
.version
= *p
++;
1201 rec
->r
.ver
.marginals
= *p
++;
1202 rec
->r
.ver
.completes
= *p
++;
1203 rec
->r
.ver
.cert_depth
= *p
++;
1204 rec
->r
.ver
.trust_model
= *p
++;
1206 rec
->r
.ver
.created
= buftoulong(p
); p
+= 4;
1207 rec
->r
.ver
.nextcheck
= buftoulong(p
); p
+= 4;
1210 rec
->r
.ver
.firstfree
=buftoulong(p
); p
+= 4;
1212 rec
->r
.ver
.trusthashtbl
=buftoulong(p
); p
+= 4;
1214 log_error( _("%s: version record with recnum %lu\n"), db_name
,
1216 err
= gpg_error (GPG_ERR_TRUSTDB
);
1218 else if( rec
->r
.ver
.version
!= 3 ) {
1219 log_error( _("%s: invalid file version %d\n"), db_name
,
1220 rec
->r
.ver
.version
);
1221 err
= gpg_error (GPG_ERR_TRUSTDB
);
1225 rec
->r
.free
.next
= buftoulong(p
); p
+= 4;
1228 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ ) {
1229 rec
->r
.htbl
.item
[i
] = buftoulong(p
); p
+= 4;
1233 rec
->r
.hlst
.next
= buftoulong(p
); p
+= 4;
1234 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1235 rec
->r
.hlst
.rnum
[i
] = buftoulong(p
); p
+= 4;
1239 memcpy( rec
->r
.trust
.fingerprint
, p
, 20); p
+=20;
1240 rec
->r
.trust
.ownertrust
= *p
++;
1241 rec
->r
.trust
.depth
= *p
++;
1242 rec
->r
.trust
.min_ownertrust
= *p
++;
1244 rec
->r
.trust
.validlist
= buftoulong(p
); p
+= 4;
1247 memcpy( rec
->r
.valid
.namehash
, p
, 20); p
+=20;
1248 rec
->r
.valid
.validity
= *p
++;
1249 rec
->r
.valid
.next
= buftoulong(p
); p
+= 4;
1250 rec
->r
.valid
.full_count
= *p
++;
1251 rec
->r
.valid
.marginal_count
= *p
++;
1254 log_error( "%s: invalid record type %d at recnum %lu\n",
1255 db_name
, rec
->rectype
, (ulong
)recnum
);
1256 err
= gpg_error (GPG_ERR_TRUSTDB
);
1264 * Write the record at RECNUM
1267 tdbio_write_record( TRUSTREC
*rec
)
1269 byte buf
[TRUST_RECORD_LEN
], *p
;
1272 ulong recnum
= rec
->recnum
;
1277 memset(buf
, 0, TRUST_RECORD_LEN
);
1279 *p
++ = rec
->rectype
; p
++;
1280 switch( rec
->rectype
) {
1281 case 0: /* unused record */
1283 case RECTYPE_VER
: /* version record */
1286 memcpy(p
-1, "gpg", 3 ); p
+= 2;
1287 *p
++ = rec
->r
.ver
.version
;
1288 *p
++ = rec
->r
.ver
.marginals
;
1289 *p
++ = rec
->r
.ver
.completes
;
1290 *p
++ = rec
->r
.ver
.cert_depth
;
1291 *p
++ = rec
->r
.ver
.trust_model
;
1293 ulongtobuf(p
, rec
->r
.ver
.created
); p
+= 4;
1294 ulongtobuf(p
, rec
->r
.ver
.nextcheck
); p
+= 4;
1297 ulongtobuf(p
, rec
->r
.ver
.firstfree
); p
+= 4;
1299 ulongtobuf(p
, rec
->r
.ver
.trusthashtbl
); p
+= 4;
1303 ulongtobuf(p
, rec
->r
.free
.next
); p
+= 4;
1308 for(i
=0; i
< ITEMS_PER_HTBL_RECORD
; i
++ ) {
1309 ulongtobuf( p
, rec
->r
.htbl
.item
[i
]); p
+= 4;
1314 ulongtobuf( p
, rec
->r
.hlst
.next
); p
+= 4;
1315 for(i
=0; i
< ITEMS_PER_HLST_RECORD
; i
++ ) {
1316 ulongtobuf( p
, rec
->r
.hlst
.rnum
[i
]); p
+= 4;
1321 memcpy( p
, rec
->r
.trust
.fingerprint
, 20); p
+= 20;
1322 *p
++ = rec
->r
.trust
.ownertrust
;
1323 *p
++ = rec
->r
.trust
.depth
;
1324 *p
++ = rec
->r
.trust
.min_ownertrust
;
1326 ulongtobuf( p
, rec
->r
.trust
.validlist
); p
+= 4;
1330 memcpy( p
, rec
->r
.valid
.namehash
, 20); p
+= 20;
1331 *p
++ = rec
->r
.valid
.validity
;
1332 ulongtobuf( p
, rec
->r
.valid
.next
); p
+= 4;
1333 *p
++ = rec
->r
.valid
.full_count
;
1334 *p
++ = rec
->r
.valid
.marginal_count
;
1341 rc
= put_record_into_cache( recnum
, buf
);
1344 else if( rec
->rectype
== RECTYPE_TRUST
)
1345 rc
= update_trusthashtbl( rec
);
1351 tdbio_delete_record( ulong recnum
)
1356 /* Must read the record fist, so we can drop it from the hash tables */
1357 rc
= tdbio_read_record( recnum
, &rec
, 0 );
1360 else if( rec
.rectype
== RECTYPE_TRUST
) {
1361 rc
= drop_from_hashtable( get_trusthashrec(),
1362 rec
.r
.trust
.fingerprint
, 20, rec
.recnum
);
1368 /* now we can chnage it to a free record */
1369 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
1371 log_fatal( _("%s: error reading version record: %s\n"),
1372 db_name
, g10_errstr(rc
) );
1374 rec
.recnum
= recnum
;
1375 rec
.rectype
= RECTYPE_FREE
;
1376 rec
.r
.free
.next
= vr
.r
.ver
.firstfree
;
1377 vr
.r
.ver
.firstfree
= recnum
;
1378 rc
= tdbio_write_record( &rec
);
1380 rc
= tdbio_write_record( &vr
);
1385 * create a new record and return its record number
1395 /* look for unused records */
1396 rc
= tdbio_read_record( 0, &vr
, RECTYPE_VER
);
1398 log_fatal( _("%s: error reading version record: %s\n"),
1399 db_name
, g10_errstr(rc
) );
1400 if( vr
.r
.ver
.firstfree
) {
1401 recnum
= vr
.r
.ver
.firstfree
;
1402 rc
= tdbio_read_record( recnum
, &rec
, RECTYPE_FREE
);
1404 log_error( _("%s: error reading free record: %s\n"),
1405 db_name
, g10_errstr(rc
) );
1408 /* update dir record */
1409 vr
.r
.ver
.firstfree
= rec
.r
.free
.next
;
1410 rc
= tdbio_write_record( &vr
);
1412 log_error( _("%s: error writing dir record: %s\n"),
1413 db_name
, g10_errstr(rc
) );
1416 /*zero out the new record */
1417 memset( &rec
, 0, sizeof rec
);
1418 rec
.rectype
= 0; /* unused record */
1419 rec
.recnum
= recnum
;
1420 rc
= tdbio_write_record( &rec
);
1422 log_fatal(_("%s: failed to zero a record: %s\n"),
1423 db_name
, g10_errstr(rc
));
1425 else { /* not found, append a new record */
1426 offset
= lseek( db_fd
, 0, SEEK_END
);
1428 log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno
) );
1429 recnum
= offset
/ TRUST_RECORD_LEN
;
1430 assert(recnum
); /* this is will never be the first record */
1431 /* we must write a record, so that the next call to this function
1432 * returns another recnum */
1433 memset( &rec
, 0, sizeof rec
);
1434 rec
.rectype
= 0; /* unused record */
1435 rec
.recnum
= recnum
;
1437 if( lseek( db_fd
, recnum
* TRUST_RECORD_LEN
, SEEK_SET
) == -1 ) {
1438 rc
= gpg_error_from_syserror ();
1439 log_error(_("trustdb rec %lu: lseek failed: %s\n"),
1440 recnum
, strerror(errno
) );
1443 int n
= write( db_fd
, &rec
, TRUST_RECORD_LEN
);
1444 if( n
!= TRUST_RECORD_LEN
) {
1445 rc
= gpg_error_from_syserror ();
1446 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
1447 recnum
, n
, strerror(errno
) );
1452 log_fatal(_("%s: failed to append a record: %s\n"),
1453 db_name
, g10_errstr(rc
));
1461 cmp_trec_fpr ( void *fpr
, const TRUSTREC
*rec
)
1463 return rec
->rectype
== RECTYPE_TRUST
1464 && !memcmp( rec
->r
.trust
.fingerprint
, fpr
, 20);
1469 tdbio_search_trust_byfpr( const byte
*fingerprint
, TRUSTREC
*rec
)
1473 /* locate the trust record using the hash table */
1474 rc
= lookup_hashtable( get_trusthashrec(), fingerprint
, 20,
1475 cmp_trec_fpr
, (void*)fingerprint
, rec
);
1480 tdbio_search_trust_bypk (PKT_public_key
*pk
, TRUSTREC
*rec
)
1482 byte fingerprint
[MAX_FINGERPRINT_LEN
];
1485 fingerprint_from_pk( pk
, fingerprint
, &fingerlen
);
1486 for (; fingerlen
< 20; fingerlen
++ )
1487 fingerprint
[fingerlen
] = 0;
1488 return tdbio_search_trust_byfpr (fingerprint
, rec
);
1497 "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") );