* gpg.texi (GPG Configuration Options): Make http_proxy option
[gnupg.git] / g10 / tdbio.c
blobc6fe995dfabf0e5299ec6e08501c930709bd26ff
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,
19 * USA.
22 #include <config.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <assert.h>
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fcntl.h>
31 #include <unistd.h>
33 #include "gpg.h"
34 #include "errors.h"
35 #include "iobuf.h"
36 #include "util.h"
37 #include "options.h"
38 #include "main.h"
39 #include "i18n.h"
40 #include "trustdb.h"
41 #include "tdbio.h"
43 #if defined(HAVE_DOSISH_SYSTEM)
44 #define ftruncate chsize
45 #endif
47 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
48 #define MY_O_BINARY O_BINARY
49 #else
50 #define MY_O_BINARY 0
51 #endif
54 /****************
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 {
61 CACHE_CTRL next;
62 struct {
63 unsigned used:1;
64 unsigned dirty:1;
65 } flags;
66 ulong recno;
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 {
78 int pubkey_algo;
79 const char *fpr;
80 int fprlen;
83 /* a type used to pass infomation to cmp_[s]dir */
84 struct cmp_xdir_struct {
85 int pubkey_algo;
86 u32 keyid[2];
90 static char *db_name;
91 static DOTLOCK lockhandle;
92 static int is_locked;
93 static int db_fd = -1;
94 static int in_transaction;
96 static void open_db(void);
100 /*************************************
101 ************* record cache **********
102 *************************************/
104 /****************
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.
109 static const char *
110 get_record_from_cache( ulong recno )
112 CACHE_CTRL r;
114 for( r = cache_list; r; r = r->next ) {
115 if( r->flags.used && r->recno == recno )
116 return r->data;
118 return NULL;
122 static int
123 write_cache_item( CACHE_CTRL r )
125 gpg_error_t err;
126 int n;
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) );
132 return err;
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) );
139 return err;
141 r->flags.dirty = 0;
142 return 0;
145 /****************
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;
153 int dirty_count = 0;
154 int clean_count = 0;
156 /* see whether we already cached this one */
157 for( unused = NULL, r = cache_list; r; r = r->next ) {
158 if( !r->flags.used ) {
159 if( !unused )
160 unused = r;
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 ) ) {
166 r->flags.dirty = 1;
167 cache_is_dirty = 1;
170 memcpy( r->data, data, TRUST_RECORD_LEN );
171 return 0;
173 if( r->flags.used ) {
174 if( r->flags.dirty )
175 dirty_count++;
176 else
177 clean_count++;
180 /* not in the cache: add a new entry */
181 if( unused ) { /* reuse this entry */
182 r = unused;
183 r->flags.used = 1;
184 r->recno = recno;
185 memcpy( r->data, data, TRUST_RECORD_LEN );
186 r->flags.dirty = 1;
187 cache_is_dirty = 1;
188 cache_entries++;
189 return 0;
191 /* see whether we reached the limit */
192 if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */
193 r = xmalloc( sizeof *r );
194 r->flags.used = 1;
195 r->recno = recno;
196 memcpy( r->data, data, TRUST_RECORD_LEN );
197 r->flags.dirty = 1;
198 r->next = cache_list;
199 cache_list = r;
200 cache_is_dirty = 1;
201 cache_entries++;
202 return 0;
204 /* cache is full: discard some clean entries */
205 if( clean_count ) {
206 int n = clean_count / 3; /* discard a third of the clean entries */
207 if( !n )
208 n = 1;
209 for( unused = NULL, r = cache_list; r; r = r->next ) {
210 if( r->flags.used && !r->flags.dirty ) {
211 if( !unused )
212 unused = r;
213 r->flags.used = 0;
214 cache_entries--;
215 if( !--n )
216 break;
219 assert( unused );
220 r = unused;
221 r->flags.used = 1;
222 r->recno = recno;
223 memcpy( r->data, data, TRUST_RECORD_LEN );
224 r->flags.dirty = 1;
225 cache_is_dirty = 1;
226 cache_entries++;
227 return 0;
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 );
237 r->flags.used = 1;
238 r->recno = recno;
239 memcpy( r->data, data, TRUST_RECORD_LEN );
240 r->flags.dirty = 1;
241 r->next = cache_list;
242 cache_list = r;
243 cache_is_dirty = 1;
244 cache_entries++;
245 return 0;
247 log_info(_("trustdb transaction too large\n"));
248 return G10ERR_RESOURCE_LIMIT;
250 if( dirty_count ) {
251 int n = dirty_count / 5; /* discard some dirty entries */
252 if( !n )
253 n = 1;
254 if( !is_locked ) {
255 if( make_dotlock( lockhandle, -1 ) )
256 log_fatal("can't acquire lock - giving up\n");
257 else
258 is_locked = 1;
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 );
263 if( rc )
264 return rc;
265 if( !unused )
266 unused = r;
267 r->flags.used = 0;
268 cache_entries--;
269 if( !--n )
270 break;
273 if( !opt.lock_once ) {
274 if( !release_dotlock( lockhandle ) )
275 is_locked = 0;
277 assert( unused );
278 r = unused;
279 r->flags.used = 1;
280 r->recno = recno;
281 memcpy( r->data, data, TRUST_RECORD_LEN );
282 r->flags.dirty = 1;
283 cache_is_dirty = 1;
284 cache_entries++;
285 return 0;
287 BUG();
292 tdbio_is_dirty()
294 return cache_is_dirty;
298 /****************
299 * Flush the cache. This cannot be used while in a transaction.
302 tdbio_sync()
304 CACHE_CTRL r;
305 int did_lock = 0;
307 if( db_fd == -1 )
308 open_db();
309 if( in_transaction )
310 log_bug("tdbio: syncing while in transaction\n");
312 if( !cache_is_dirty )
313 return 0;
315 if( !is_locked ) {
316 if( make_dotlock( lockhandle, -1 ) )
317 log_fatal("can't acquire lock - giving up\n");
318 else
319 is_locked = 1;
320 did_lock = 1;
322 for( r = cache_list; r; r = r->next ) {
323 if( r->flags.used && r->flags.dirty ) {
324 int rc = write_cache_item( r );
325 if( rc )
326 return rc;
329 cache_is_dirty = 0;
330 if( did_lock && !opt.lock_once ) {
331 if( !release_dotlock( lockhandle ) )
332 is_locked = 0;
335 return 0;
338 #if 0
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. */
342 /****************
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()
351 int rc;
353 if( in_transaction )
354 log_bug("tdbio: nested transactions\n");
355 /* flush everything out */
356 rc = tdbio_sync();
357 if( rc )
358 return rc;
359 in_transaction = 1;
360 return 0;
364 tdbio_end_transaction()
366 int rc;
368 if( !in_transaction )
369 log_bug("tdbio: no active transaction\n");
370 if( !is_locked ) {
371 if( make_dotlock( lockhandle, -1 ) )
372 log_fatal("can't acquire lock - giving up\n");
373 else
374 is_locked = 1;
376 block_all_signals();
377 in_transaction = 0;
378 rc = tdbio_sync();
379 unblock_all_signals();
380 if( !opt.lock_once ) {
381 if( !release_dotlock( lockhandle ) )
382 is_locked = 0;
384 return rc;
388 tdbio_cancel_transaction()
390 CACHE_CTRL r;
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 ) {
400 r->flags.used = 0;
401 cache_entries--;
404 cache_is_dirty = 0;
407 in_transaction = 0;
408 return 0;
410 #endif
413 /********************************************************
414 **************** cached I/O functions ******************
415 ********************************************************/
417 static void
418 cleanup(void)
420 if( is_locked ) {
421 if( !release_dotlock(lockhandle) )
422 is_locked = 0;
426 /* Caller must sync */
428 tdbio_update_version_record (void)
430 TRUSTREC rec;
431 int rc;
433 memset( &rec, 0, sizeof rec );
435 rc=tdbio_read_record( 0, &rec, RECTYPE_VER);
436 if(rc==0)
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);
446 return rc;
449 static int
450 create_version_record (void)
452 TRUSTREC rec;
453 int rc;
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;
463 else
464 rec.r.ver.trust_model = TM_PGP;
465 rec.rectype = RECTYPE_VER;
466 rec.recnum = 0;
467 rc = tdbio_write_record( &rec );
468 if( !rc )
469 tdbio_sync();
470 return rc;
476 tdbio_set_dbname( const char *new_dbname, int create )
478 char *fname;
479 static int initialized = 0;
481 if( !initialized ) {
482 atexit( cleanup );
483 initialized = 1;
486 if(new_dbname==NULL)
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);
492 else
493 fname = make_filename (opt.homedir, new_dbname, NULL);
495 else
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) );
501 xfree(fname);
502 return G10ERR_TRUSTDB;
504 if( create ) {
505 FILE *fp;
506 TRUSTREC rec;
507 int rc;
508 char *p = strrchr( fname, DIRSEP_C );
509 mode_t oldmask;
511 assert(p);
512 *p = 0;
513 if( access( fname, F_OK ) ) {
514 try_make_homedir( fname );
515 log_fatal( _("%s: directory does not exist!\n"), fname );
517 *p = DIRSEP_C;
519 xfree(db_name);
520 db_name = fname;
521 #ifdef __riscos__
522 if( !lockhandle )
523 lockhandle = create_dotlock( db_name );
524 if( !lockhandle )
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__ */
529 oldmask=umask(077);
530 if (is_secured_filename (fname)) {
531 fp = NULL;
532 errno = EPERM;
534 else
535 fp =fopen( fname, "wb" );
536 umask(oldmask);
537 if( !fp )
538 log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) );
539 fclose(fp);
540 db_fd = open( db_name, O_RDWR | MY_O_BINARY );
541 if( db_fd == -1 )
542 log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
544 #ifndef __riscos__
545 if( !lockhandle )
546 lockhandle = create_dotlock( db_name );
547 if( !lockhandle )
548 log_fatal( _("can't create lock for `%s'\n"), db_name );
549 #endif /* !__riscos__ */
551 rc = create_version_record ();
552 if( rc )
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 );
559 if( !opt.quiet )
560 log_info(_("%s: trustdb created\n"), db_name);
562 return 0;
565 xfree(db_name);
566 db_name = fname;
567 return 0;
571 const char *
572 tdbio_get_dbname()
574 return db_name;
579 static void
580 open_db()
582 TRUSTREC rec;
584 assert( db_fd == -1 );
586 if (!lockhandle )
587 lockhandle = create_dotlock( db_name );
588 if (!lockhandle )
589 log_fatal( _("can't create lock for `%s'\n"), db_name );
590 #ifdef __riscos__
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
596 #ifdef EROFS
597 || errno == EROFS)
598 #endif
600 db_fd = open (db_name, O_RDONLY | MY_O_BINARY );
601 if (db_fd != -1)
602 log_info (_("NOTE: trustdb not writable\n"));
604 if ( db_fd == -1 )
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 );
614 /****************
615 * Make a hashtable: type 0 = trust hash
617 static void
618 create_hashtable( TRUSTREC *vr, int type )
620 TRUSTREC rec;
621 off_t offset;
622 ulong recnum;
623 int i, n, rc;
625 offset = lseek( db_fd, 0, SEEK_END );
626 if( offset == -1 )
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 */
631 if( !type )
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;
639 rec.recnum = recnum;
640 rc = tdbio_write_record( &rec );
641 if( rc )
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 );
647 if( !rc )
648 rc = tdbio_sync();
649 if( rc )
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;
660 if( yes_no == -1 )
662 TRUSTREC vr;
663 int rc;
665 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
666 if( rc )
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;
676 return yes_no;
679 byte
680 tdbio_read_model(void)
682 TRUSTREC vr;
683 int rc;
685 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
686 if( rc )
687 log_fatal( _("%s: error reading version record: %s\n"),
688 db_name, g10_errstr(rc) );
689 return vr.r.ver.trust_model;
692 /****************
693 * Return the nextstamp value.
695 ulong
696 tdbio_read_nextcheck ()
698 TRUSTREC vr;
699 int rc;
701 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
702 if( rc )
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)
712 TRUSTREC vr;
713 int rc;
715 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
716 if( rc )
717 log_fatal( _("%s: error reading version record: %s\n"),
718 db_name, g10_errstr(rc) );
720 if (vr.r.ver.nextcheck == stamp)
721 return 0;
723 vr.r.ver.nextcheck = stamp;
724 rc = tdbio_write_record( &vr );
725 if( rc )
726 log_fatal( _("%s: error writing version record: %s\n"),
727 db_name, g10_errstr(rc) );
728 return 1;
733 /****************
734 * Return the record number of the trusthash tbl or create a new one.
736 static ulong
737 get_trusthashrec(void)
739 static ulong trusthashtbl; /* record number of the trust hashtable */
741 if( !trusthashtbl ) {
742 TRUSTREC vr;
743 int rc;
745 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
746 if( rc )
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;
754 return trusthashtbl;
759 /****************
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.
764 static int
765 upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
767 TRUSTREC lastrec, rec;
768 ulong hashrec, item;
769 int msb;
770 int level=0;
771 int rc, i;
773 hashrec = table;
774 next_level:
775 msb = key[level];
776 hashrec += msb / ITEMS_PER_HTBL_RECORD;
777 rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
778 if( rc ) {
779 log_error("upd_hashtable: read failed: %s\n", g10_errstr(rc) );
780 return 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 );
787 if( rc ) {
788 log_error("upd_hashtable: write htbl failed: %s\n",
789 g10_errstr(rc) );
790 return rc;
793 else if( item != newrecnum ) { /* must do an update */
794 lastrec = rec;
795 rc = tdbio_read_record( item, &rec, 0 );
796 if( rc ) {
797 log_error( "upd_hashtable: read item failed: %s\n",
798 g10_errstr(rc) );
799 return rc;
802 if( rec.rectype == RECTYPE_HTBL ) {
803 hashrec = item;
804 level++;
805 if( level >= keylen ) {
806 log_error( "hashtable has invalid indirections.\n");
807 return G10ERR_TRUSTDB;
809 goto next_level;
811 else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
812 /* see whether the key is already in this list */
813 for(;;) {
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,
821 &rec, RECTYPE_HLST);
822 if( rc ) {
823 log_error( "upd_hashtable: read hlst failed: %s\n",
824 g10_errstr(rc) );
825 return rc;
828 else
829 break; /* not there */
831 /* find the next free entry and put it in */
832 for(;;) {
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 );
837 if( rc )
838 log_error( "upd_hashtable: write hlst failed: %s\n",
839 g10_errstr(rc) );
840 return rc; /* done */
843 if( rec.r.hlst.next ) {
844 rc = tdbio_read_record( rec.r.hlst.next,
845 &rec, RECTYPE_HLST );
846 if( rc ) {
847 log_error( "upd_hashtable: read hlst failed: %s\n",
848 g10_errstr(rc) );
849 return rc;
852 else { /* add a new list record */
853 rec.r.hlst.next = item = tdbio_new_recnum();
854 rc = tdbio_write_record( &rec );
855 if( rc ) {
856 log_error( "upd_hashtable: write hlst failed: %s\n",
857 g10_errstr(rc) );
858 return rc;
860 memset( &rec, 0, sizeof rec );
861 rec.rectype = RECTYPE_HLST;
862 rec.recnum = item;
863 rec.r.hlst.rnum[0] = newrecnum;
864 rc = tdbio_write_record( &rec );
865 if( rc )
866 log_error( "upd_hashtable: write ext hlst failed: %s\n",
867 g10_errstr(rc) );
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 ) {
874 return 0;
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 );
883 if( rc ) {
884 log_error( "upd_hashtable: write new hlst failed: %s\n",
885 g10_errstr(rc) );
886 return rc;
888 /* update the hashtable record */
889 lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
890 rc = tdbio_write_record( &lastrec );
891 if( rc )
892 log_error( "upd_hashtable: update htbl failed: %s\n",
893 g10_errstr(rc) );
894 return rc; /* ready */
896 else {
897 log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
898 table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
899 list_trustdb(NULL);
900 return G10ERR_TRUSTDB;
904 return 0;
908 /****************
909 * Drop an entry from a hashtable
910 * table gives the start of the table, key and keylen is the key,
912 static int
913 drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
915 TRUSTREC rec;
916 ulong hashrec, item;
917 int msb;
918 int level=0;
919 int rc, i;
921 hashrec = table;
922 next_level:
923 msb = key[level];
924 hashrec += msb / ITEMS_PER_HTBL_RECORD;
925 rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
926 if( rc ) {
927 log_error("drop_from_hashtable: read failed: %s\n",
928 g10_errstr(rc) );
929 return rc;
932 item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
933 if( !item ) /* not found - forget about it */
934 return 0;
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 );
939 if( rc )
940 log_error("drop_from_hashtable: write htbl failed: %s\n",
941 g10_errstr(rc) );
942 return rc;
945 rc = tdbio_read_record( item, &rec, 0 );
946 if( rc ) {
947 log_error( "drop_from_hashtable: read item failed: %s\n",
948 g10_errstr(rc) );
949 return rc;
952 if( rec.rectype == RECTYPE_HTBL ) {
953 hashrec = item;
954 level++;
955 if( level >= keylen ) {
956 log_error( "hashtable has invalid indirections.\n");
957 return G10ERR_TRUSTDB;
959 goto next_level;
962 if( rec.rectype == RECTYPE_HLST ) {
963 for(;;) {
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 );
968 if( rc )
969 log_error("drop_from_hashtable: write htbl failed: %s\n",
970 g10_errstr(rc) );
971 return rc;
974 if( rec.r.hlst.next ) {
975 rc = tdbio_read_record( rec.r.hlst.next,
976 &rec, RECTYPE_HLST);
977 if( rc ) {
978 log_error( "drop_from_hashtable: read hlst failed: %s\n",
979 g10_errstr(rc) );
980 return rc;
983 else
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;
995 /****************
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
1000 static int
1001 lookup_hashtable( ulong table, const byte *key, size_t keylen,
1002 int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata,
1003 TRUSTREC *rec )
1005 int rc;
1006 ulong hashrec, item;
1007 int msb;
1008 int level=0;
1010 hashrec = table;
1011 next_level:
1012 msb = key[level];
1013 hashrec += msb / ITEMS_PER_HTBL_RECORD;
1014 rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
1015 if( rc ) {
1016 log_error("lookup_hashtable failed: %s\n", g10_errstr(rc) );
1017 return rc;
1020 item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
1021 if( !item )
1022 return -1; /* not found */
1024 rc = tdbio_read_record( item, rec, 0 );
1025 if( rc ) {
1026 log_error( "hashtable read failed: %s\n", g10_errstr(rc) );
1027 return rc;
1029 if( rec->rectype == RECTYPE_HTBL ) {
1030 hashrec = item;
1031 level++;
1032 if( level >= keylen ) {
1033 log_error("hashtable has invalid indirections\n");
1034 return G10ERR_TRUSTDB;
1036 goto next_level;
1038 else if( rec->rectype == RECTYPE_HLST ) {
1039 for(;;) {
1040 int i;
1042 for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
1043 if( rec->r.hlst.rnum[i] ) {
1044 TRUSTREC tmp;
1046 rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
1047 if( rc ) {
1048 log_error( "lookup_hashtable: read item failed: %s\n",
1049 g10_errstr(rc) );
1050 return rc;
1052 if( (*cmpfnc)( cmpdata, &tmp ) ) {
1053 *rec = tmp;
1054 return 0;
1058 if( rec->r.hlst.next ) {
1059 rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
1060 if( rc ) {
1061 log_error( "lookup_hashtable: read hlst failed: %s\n",
1062 g10_errstr(rc) );
1063 return rc;
1066 else
1067 return -1; /* not found */
1072 if( (*cmpfnc)( cmpdata, rec ) )
1073 return 0; /* really found */
1075 return -1; /* no: not found */
1079 /****************
1080 * Update the trust hashtbl or create the table if it does not exist
1082 static int
1083 update_trusthashtbl( TRUSTREC *tr )
1085 return upd_hashtable( get_trusthashrec(),
1086 tr->r.trust.fingerprint, 20, tr->recnum );
1091 void
1092 tdbio_dump_record( TRUSTREC *rec, FILE *fp )
1094 int i;
1095 ulong rnum = rec->recnum;
1097 fprintf(fp, "rec %5lu, ", rnum );
1099 switch( rec->rectype ) {
1100 case 0: fprintf(fp, "blank\n");
1101 break;
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)
1113 break;
1114 case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
1115 break;
1116 case RECTYPE_HTBL:
1117 fprintf(fp, "htbl,");
1118 for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
1119 fprintf(fp, " %lu", rec->r.htbl.item[i] );
1120 putc('\n', fp);
1121 break;
1122 case RECTYPE_HLST:
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] );
1126 putc('\n', fp);
1127 break;
1128 case RECTYPE_TRUST:
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);
1134 break;
1135 case RECTYPE_VALID:
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,
1140 rec->r.valid.next);
1141 break;
1142 default:
1143 fprintf(fp, "unknown type %d\n", rec->rectype );
1144 break;
1148 /****************
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;
1158 int n, i;
1160 if( db_fd == -1 )
1161 open_db();
1162 buf = get_record_from_cache( recnum );
1163 if( !buf ) {
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) );
1167 return err;
1169 n = read( db_fd, readbuf, TRUST_RECORD_LEN);
1170 if( !n ) {
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,
1176 strerror(errno) );
1177 return err;
1179 buf = readbuf;
1181 rec->recnum = recnum;
1182 rec->dirty = 0;
1183 p = buf;
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 */
1193 break;
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++;
1205 p += 3;
1206 rec->r.ver.created = buftoulong(p); p += 4;
1207 rec->r.ver.nextcheck = buftoulong(p); p += 4;
1208 p += 4;
1209 p += 4;
1210 rec->r.ver.firstfree =buftoulong(p); p += 4;
1211 p += 4;
1212 rec->r.ver.trusthashtbl =buftoulong(p); p += 4;
1213 if( recnum ) {
1214 log_error( _("%s: version record with recnum %lu\n"), db_name,
1215 (ulong)recnum );
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);
1223 break;
1224 case RECTYPE_FREE:
1225 rec->r.free.next = buftoulong(p); p += 4;
1226 break;
1227 case RECTYPE_HTBL:
1228 for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
1229 rec->r.htbl.item[i] = buftoulong(p); p += 4;
1231 break;
1232 case RECTYPE_HLST:
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;
1237 break;
1238 case RECTYPE_TRUST:
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++;
1243 p++;
1244 rec->r.trust.validlist = buftoulong(p); p += 4;
1245 break;
1246 case RECTYPE_VALID:
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++;
1252 break;
1253 default:
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);
1257 break;
1260 return err;
1263 /****************
1264 * Write the record at RECNUM
1267 tdbio_write_record( TRUSTREC *rec )
1269 byte buf[TRUST_RECORD_LEN], *p;
1270 int rc = 0;
1271 int i;
1272 ulong recnum = rec->recnum;
1274 if( db_fd == -1 )
1275 open_db();
1277 memset(buf, 0, TRUST_RECORD_LEN);
1278 p = buf;
1279 *p++ = rec->rectype; p++;
1280 switch( rec->rectype ) {
1281 case 0: /* unused record */
1282 break;
1283 case RECTYPE_VER: /* version record */
1284 if( recnum )
1285 BUG();
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;
1292 p += 3;
1293 ulongtobuf(p, rec->r.ver.created); p += 4;
1294 ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
1295 p += 4;
1296 p += 4;
1297 ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
1298 p += 4;
1299 ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
1300 break;
1302 case RECTYPE_FREE:
1303 ulongtobuf(p, rec->r.free.next); p += 4;
1304 break;
1307 case RECTYPE_HTBL:
1308 for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
1309 ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
1311 break;
1313 case RECTYPE_HLST:
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;
1318 break;
1320 case RECTYPE_TRUST:
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;
1325 p++;
1326 ulongtobuf( p, rec->r.trust.validlist); p += 4;
1327 break;
1329 case RECTYPE_VALID:
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;
1335 break;
1337 default:
1338 BUG();
1341 rc = put_record_into_cache( recnum, buf );
1342 if( rc )
1344 else if( rec->rectype == RECTYPE_TRUST )
1345 rc = update_trusthashtbl( rec );
1347 return rc;
1351 tdbio_delete_record( ulong recnum )
1353 TRUSTREC vr, rec;
1354 int rc;
1356 /* Must read the record fist, so we can drop it from the hash tables */
1357 rc = tdbio_read_record( recnum, &rec, 0 );
1358 if( rc )
1360 else if( rec.rectype == RECTYPE_TRUST ) {
1361 rc = drop_from_hashtable( get_trusthashrec(),
1362 rec.r.trust.fingerprint, 20, rec.recnum );
1365 if( rc )
1366 return rc;
1368 /* now we can chnage it to a free record */
1369 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
1370 if( rc )
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 );
1379 if( !rc )
1380 rc = tdbio_write_record( &vr );
1381 return rc;
1384 /****************
1385 * create a new record and return its record number
1387 ulong
1388 tdbio_new_recnum()
1390 off_t offset;
1391 ulong recnum;
1392 TRUSTREC vr, rec;
1393 int rc;
1395 /* look for unused records */
1396 rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
1397 if( rc )
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 );
1403 if( rc ) {
1404 log_error( _("%s: error reading free record: %s\n"),
1405 db_name, g10_errstr(rc) );
1406 return rc;
1408 /* update dir record */
1409 vr.r.ver.firstfree = rec.r.free.next;
1410 rc = tdbio_write_record( &vr );
1411 if( rc ) {
1412 log_error( _("%s: error writing dir record: %s\n"),
1413 db_name, g10_errstr(rc) );
1414 return 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 );
1421 if( rc )
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 );
1427 if( offset == -1 )
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;
1436 rc = 0;
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) );
1442 else {
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) );
1451 if( rc )
1452 log_fatal(_("%s: failed to append a record: %s\n"),
1453 db_name, g10_errstr(rc));
1455 return recnum ;
1460 static int
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 )
1471 int rc;
1473 /* locate the trust record using the hash table */
1474 rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20,
1475 cmp_trec_fpr, (void*)fingerprint, rec );
1476 return rc;
1480 tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
1482 byte fingerprint[MAX_FINGERPRINT_LEN];
1483 size_t fingerlen;
1485 fingerprint_from_pk( pk, fingerprint, &fingerlen );
1486 for (; fingerlen < 20; fingerlen++ )
1487 fingerprint[fingerlen] = 0;
1488 return tdbio_search_trust_byfpr (fingerprint, rec);
1493 void
1494 tdbio_invalid(void)
1496 log_error(_(
1497 "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") );
1498 g10_exit(2);