f109dde02280a411ee26faac74947d06b515c678
[gnupg.git] / g10 / tdbio.c
1 /* tdbio.c
2  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2012 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <assert.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30
31 #include "errors.h"
32 #include "iobuf.h"
33 #include "memory.h"
34 #include "util.h"
35 #include "options.h"
36 #include "main.h"
37 #include "i18n.h"
38 #include "trustdb.h"
39 #include "tdbio.h"
40
41 #if defined(HAVE_DOSISH_SYSTEM)
42 #define ftruncate chsize
43 #endif
44
45 #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
46 #define MY_O_BINARY  O_BINARY
47 #else
48 #define MY_O_BINARY  0
49 #endif
50
51
52 /****************
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.
56  */
57 typedef struct cache_ctrl_struct *CACHE_CTRL;
58 struct cache_ctrl_struct {
59     CACHE_CTRL next;
60     struct {
61         unsigned used:1;
62         unsigned dirty:1;
63     } flags;
64     ulong recno;
65     char data[TRUST_RECORD_LEN];
66 };
67
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;
73
74 /* a type used to pass infomation to cmp_krec_fpr */
75 struct cmp_krec_fpr_struct {
76     int pubkey_algo;
77     const char *fpr;
78     int fprlen;
79 };
80
81 /* a type used to pass infomation to cmp_[s]dir */
82 struct cmp_xdir_struct {
83     int pubkey_algo;
84     u32 keyid[2];
85 };
86
87
88 static char *db_name;
89 static dotlock_t lockhandle;
90 static int is_locked;
91 static int  db_fd = -1;
92 static int in_transaction;
93
94 static void open_db(void);
95 static void migrate_from_v2 (void);
96
97
98 \f
99 /*************************************
100  ************* record cache **********
101  *************************************/
102
103 /****************
104  * Get the data from therecord cache and return a
105  * pointer into that cache.  Caller should copy
106  * the return data.  NULL is returned on a cache miss.
107  */
108 static const char *
109 get_record_from_cache( ulong recno )
110 {
111     CACHE_CTRL r;
112
113     for( r = cache_list; r; r = r->next ) {
114         if( r->flags.used && r->recno == recno )
115             return r->data;
116     }
117     return NULL;
118 }
119
120
121 static int
122 write_cache_item( CACHE_CTRL r )
123 {
124     int n;
125
126     if( lseek( db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
127         log_error(_("trustdb rec %lu: lseek failed: %s\n"),
128                                             r->recno, strerror(errno) );
129         return G10ERR_WRITE_FILE;
130     }
131     n = write( db_fd, r->data, TRUST_RECORD_LEN);
132     if( n != TRUST_RECORD_LEN ) {
133         log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
134                                             r->recno, n, strerror(errno) );
135         return G10ERR_WRITE_FILE;
136     }
137     r->flags.dirty = 0;
138     return 0;
139 }
140
141 /****************
142  * Put data into the cache.  This function may flush the
143  * some cache entries if there is not enough space available.
144  */
145 int
146 put_record_into_cache( ulong recno, const char *data )
147 {
148     CACHE_CTRL r, unused;
149     int dirty_count = 0;
150     int clean_count = 0;
151
152     /* see whether we already cached this one */
153     for( unused = NULL, r = cache_list; r; r = r->next ) {
154         if( !r->flags.used ) {
155             if( !unused )
156                 unused = r;
157         }
158         else if( r->recno == recno ) {
159             if( !r->flags.dirty ) {
160                 /* Hmmm: should we use a a copy and compare? */
161                 if( memcmp(r->data, data, TRUST_RECORD_LEN ) ) {
162                     r->flags.dirty = 1;
163                     cache_is_dirty = 1;
164                 }
165             }
166             memcpy( r->data, data, TRUST_RECORD_LEN );
167             return 0;
168         }
169         if( r->flags.used ) {
170             if( r->flags.dirty )
171                 dirty_count++;
172             else
173                 clean_count++;
174         }
175     }
176     /* not in the cache: add a new entry */
177     if( unused ) { /* reuse this entry */
178         r = unused;
179         r->flags.used = 1;
180         r->recno = recno;
181         memcpy( r->data, data, TRUST_RECORD_LEN );
182         r->flags.dirty = 1;
183         cache_is_dirty = 1;
184         cache_entries++;
185         return 0;
186     }
187     /* see whether we reached the limit */
188     if( cache_entries < MAX_CACHE_ENTRIES_SOFT ) { /* no */
189         r = xmalloc( sizeof *r );
190         r->flags.used = 1;
191         r->recno = recno;
192         memcpy( r->data, data, TRUST_RECORD_LEN );
193         r->flags.dirty = 1;
194         r->next = cache_list;
195         cache_list = r;
196         cache_is_dirty = 1;
197         cache_entries++;
198         return 0;
199     }
200     /* cache is full: discard some clean entries */
201     if( clean_count ) {
202         int n = clean_count / 3; /* discard a third of the clean entries */
203         if( !n )
204             n = 1;
205         for( unused = NULL, r = cache_list; r; r = r->next ) {
206             if( r->flags.used && !r->flags.dirty ) {
207                 if( !unused )
208                     unused = r;
209                 r->flags.used = 0;
210                 cache_entries--;
211                 if( !--n )
212                     break;
213             }
214         }
215         assert( unused );
216         r = unused;
217         r->flags.used = 1;
218         r->recno = recno;
219         memcpy( r->data, data, TRUST_RECORD_LEN );
220         r->flags.dirty = 1;
221         cache_is_dirty = 1;
222         cache_entries++;
223         return 0;
224     }
225     /* no clean entries: have to flush some dirty entries */
226     if( in_transaction ) {
227         /* but we can't do this while in a transaction
228          * we increase the cache size instead */
229         if( cache_entries < MAX_CACHE_ENTRIES_HARD ) { /* no */
230             if( opt.debug && !(cache_entries % 100) )
231                 log_debug("increasing tdbio cache size\n");
232             r = xmalloc( sizeof *r );
233             r->flags.used = 1;
234             r->recno = recno;
235             memcpy( r->data, data, TRUST_RECORD_LEN );
236             r->flags.dirty = 1;
237             r->next = cache_list;
238             cache_list = r;
239             cache_is_dirty = 1;
240             cache_entries++;
241             return 0;
242         }
243         log_info(_("trustdb transaction too large\n"));
244         return G10ERR_RESOURCE_LIMIT;
245     }
246     if( dirty_count ) {
247         int n = dirty_count / 5; /* discard some dirty entries */
248         if( !n )
249             n = 1;
250         if( !is_locked ) {
251             if (dotlock_take (lockhandle, -1))
252                 log_fatal("can't acquire lock - giving up\n");
253             else
254                 is_locked = 1;
255         }
256         for( unused = NULL, r = cache_list; r; r = r->next ) {
257             if( r->flags.used && r->flags.dirty ) {
258                 int rc = write_cache_item( r );
259                 if( rc )
260                     return rc;
261                 if( !unused )
262                     unused = r;
263                 r->flags.used = 0;
264                 cache_entries--;
265                 if( !--n )
266                     break;
267             }
268         }
269         if( !opt.lock_once ) {
270             if (!dotlock_release (lockhandle))
271                 is_locked = 0;
272         }
273         assert( unused );
274         r = unused;
275         r->flags.used = 1;
276         r->recno = recno;
277         memcpy( r->data, data, TRUST_RECORD_LEN );
278         r->flags.dirty = 1;
279         cache_is_dirty = 1;
280         cache_entries++;
281         return 0;
282     }
283     BUG();
284 }
285
286
287 int
288 tdbio_is_dirty()
289 {
290     return cache_is_dirty;
291 }
292
293
294 /****************
295  * Flush the cache.  This cannot be used while in a transaction.
296  */
297 int
298 tdbio_sync()
299 {
300     CACHE_CTRL r;
301     int did_lock = 0;
302
303     if( db_fd == -1 )
304         open_db();
305     if( in_transaction )
306         log_bug("tdbio: syncing while in transaction\n");
307
308     if( !cache_is_dirty )
309         return 0;
310
311     if( !is_locked ) {
312         if (dotlock_take (lockhandle, -1))
313             log_fatal("can't acquire lock - giving up\n");
314         else
315             is_locked = 1;
316         did_lock = 1;
317     }
318     for( r = cache_list; r; r = r->next ) {
319         if( r->flags.used && r->flags.dirty ) {
320             int rc = write_cache_item( r );
321             if( rc )
322                 return rc;
323         }
324     }
325     cache_is_dirty = 0;
326     if( did_lock && !opt.lock_once ) {
327         if (!dotlock_release (lockhandle))
328             is_locked = 0;
329     }
330
331     return 0;
332 }
333
334 #if 0
335 /* The transaction code is disabled in the 1.2.x branch, as it is not
336    yet used.  It will be enabled in 1.3.x. */
337
338 /****************
339  * Simple transactions system:
340  * Everything between begin_transaction and end/cancel_transaction
341  * is not immediatly written but at the time of end_transaction.
342  *
343  */
344 int
345 tdbio_begin_transaction()
346 {
347     int rc;
348
349     if( in_transaction )
350         log_bug("tdbio: nested transactions\n");
351     /* flush everything out */
352     rc = tdbio_sync();
353     if( rc )
354         return rc;
355     in_transaction = 1;
356     return 0;
357 }
358
359 int
360 tdbio_end_transaction()
361 {
362     int rc;
363
364     if( !in_transaction )
365         log_bug("tdbio: no active transaction\n");
366     if( !is_locked ) {
367         if (dotlock_take (lockhandle, -1))
368             log_fatal("can't acquire lock - giving up\n");
369         else
370             is_locked = 1;
371     }
372     block_all_signals();
373     in_transaction = 0;
374     rc = tdbio_sync();
375     unblock_all_signals();
376     if( !opt.lock_once ) {
377         if (!dotlock_release (lockhandle))
378             is_locked = 0;
379     }
380     return rc;
381 }
382
383 int
384 tdbio_cancel_transaction()
385 {
386     CACHE_CTRL r;
387
388     if( !in_transaction )
389         log_bug("tdbio: no active transaction\n");
390
391     /* remove all dirty marked entries, so that the original ones
392      * are read back the next time */
393     if( cache_is_dirty ) {
394         for( r = cache_list; r; r = r->next ) {
395             if( r->flags.used && r->flags.dirty ) {
396                 r->flags.used = 0;
397                 cache_entries--;
398             }
399         }
400         cache_is_dirty = 0;
401     }
402
403     in_transaction = 0;
404     return 0;
405 }
406 #endif
407
408 \f
409 /********************************************************
410  **************** cached I/O functions ******************
411  ********************************************************/
412
413 static void
414 cleanup(void)
415 {
416     if( is_locked ) {
417         if (!dotlock_release (lockhandle))
418             is_locked = 0;
419     }
420 }
421
422 /* Caller must sync */
423 int
424 tdbio_update_version_record (void)
425 {
426   TRUSTREC rec;
427   int rc;
428
429   memset( &rec, 0, sizeof rec );
430
431   rc=tdbio_read_record( 0, &rec, RECTYPE_VER);
432   if(rc==0)
433     {
434       rec.r.ver.created     = make_timestamp();
435       rec.r.ver.marginals   = opt.marginals_needed;
436       rec.r.ver.completes   = opt.completes_needed;
437       rec.r.ver.cert_depth  = opt.max_cert_depth;
438       rec.r.ver.trust_model = opt.trust_model;
439       rec.r.ver.min_cert_level = opt.min_cert_level;
440       rc=tdbio_write_record(&rec);
441     }
442
443   return rc;
444 }
445
446 static int
447 create_version_record (void)
448 {
449   TRUSTREC rec;
450   int rc;
451
452   memset( &rec, 0, sizeof rec );
453   rec.r.ver.version     = 3;
454   rec.r.ver.created     = make_timestamp();
455   rec.r.ver.marginals   = opt.marginals_needed;
456   rec.r.ver.completes   = opt.completes_needed;
457   rec.r.ver.cert_depth  = opt.max_cert_depth;
458   if(opt.trust_model==TM_PGP || opt.trust_model==TM_CLASSIC)
459     rec.r.ver.trust_model = opt.trust_model;
460   else
461     rec.r.ver.trust_model = TM_PGP;
462   rec.r.ver.min_cert_level = opt.min_cert_level;
463   rec.rectype = RECTYPE_VER;
464   rec.recnum = 0;
465   rc = tdbio_write_record( &rec );
466   if( !rc )
467     tdbio_sync();
468   return rc;
469 }
470
471
472
473 int
474 tdbio_set_dbname( const char *new_dbname, int create, int *r_nofile)
475 {
476     char *fname;
477     static int initialized = 0;
478
479     if( !initialized ) {
480         atexit( cleanup );
481         initialized = 1;
482     }
483
484     *r_nofile = 0;
485
486     if(new_dbname==NULL)
487       fname=make_filename(opt.homedir,"trustdb" EXTSEP_S "gpg", NULL);
488     else if (*new_dbname != DIRSEP_C )
489       {
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);
494       }
495     else
496       fname = xstrdup (new_dbname);
497
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;
503         }
504         if (!create)
505           *r_nofile = 1;
506         else {
507             FILE *fp;
508             TRUSTREC rec;
509             int rc;
510             char *p = strrchr( fname, DIRSEP_C );
511             mode_t oldmask;
512
513             assert(p);
514             *p = 0;
515             if( access( fname, F_OK ) ) {
516                 try_make_homedir( fname );
517                 if (access (fname, F_OK ))
518                   log_fatal (_("%s: directory does not exist!\n"), fname);
519             }
520             *p = DIRSEP_C;
521
522             xfree(db_name);
523             db_name = fname;
524 #ifdef __riscos__
525             if( !lockhandle )
526                 lockhandle = dotlock_create (db_name, 0);
527             if( !lockhandle )
528                 log_fatal( _("can't create lock for `%s'\n"), db_name );
529             if (dotlock_take (lockhandle, -1))
530                 log_fatal( _("can't lock `%s'\n"), db_name );
531 #endif /* __riscos__ */
532             oldmask=umask(077);
533             if (is_secured_filename (fname)) {
534                 fp = NULL;
535                 errno = EPERM;
536             }
537             else
538                 fp =fopen( fname, "wb" );
539             umask(oldmask);
540             if( !fp )
541                 log_fatal( _("can't create `%s': %s\n"), fname, strerror(errno) );
542             fclose(fp);
543             db_fd = open( db_name, O_RDWR | MY_O_BINARY );
544             if( db_fd == -1 )
545                 log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
546
547 #ifndef __riscos__
548             if( !lockhandle )
549                 lockhandle = dotlock_create (db_name, 0);
550             if( !lockhandle )
551                 log_fatal( _("can't create lock for `%s'\n"), db_name );
552 #endif /* !__riscos__ */
553
554             rc = create_version_record ();
555             if( rc )
556                 log_fatal( _("%s: failed to create version record: %s"),
557                                                    fname, g10_errstr(rc));
558             /* and read again to check that we are okay */
559             if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
560                 log_fatal( _("%s: invalid trustdb created\n"), db_name );
561
562             if( !opt.quiet )
563                 log_info(_("%s: trustdb created\n"), db_name);
564
565             return 0;
566         }
567     }
568     xfree(db_name);
569     db_name = fname;
570     return 0;
571 }
572
573
574 const char *
575 tdbio_get_dbname()
576 {
577     return db_name;
578 }
579
580
581
582 static void
583 open_db()
584 {
585   byte buf[10];
586   int n;
587   TRUSTREC rec;
588
589   assert( db_fd == -1 );
590
591   if (!lockhandle )
592     lockhandle = dotlock_create (db_name, 0);
593   if (!lockhandle )
594     log_fatal( _("can't create lock for `%s'\n"), db_name );
595 #ifdef __riscos__
596   if (dotlock_take (lockhandle, -1))
597     log_fatal( _("can't lock `%s'\n"), db_name );
598 #endif /* __riscos__ */
599   db_fd = open (db_name, O_RDWR | MY_O_BINARY );
600   if (db_fd == -1 && (errno == EACCES
601 #ifdef EROFS
602                       || errno == EROFS
603 #endif
604                       )
605       ) {
606       db_fd = open (db_name, O_RDONLY | MY_O_BINARY );
607       if (db_fd != -1)
608           log_info (_("NOTE: trustdb not writable\n"));
609   }
610   if ( db_fd == -1 )
611     log_fatal( _("can't open `%s': %s\n"), db_name, strerror(errno) );
612   register_secured_file (db_name);
613
614   /* check whether we need to do a version migration */
615   do
616     n = read (db_fd, buf, 5);
617   while (n==-1 && errno == EINTR);
618   if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5))
619     {
620       migrate_from_v2 ();
621     }
622
623   /* read the version record */
624   if (tdbio_read_record (0, &rec, RECTYPE_VER ) )
625     log_fatal( _("%s: invalid trustdb\n"), db_name );
626 }
627
628
629 /****************
630  * Make a hashtable: type 0 = trust hash
631  */
632 static void
633 create_hashtable( TRUSTREC *vr, int type )
634 {
635     TRUSTREC rec;
636     off_t offset;
637     ulong recnum;
638     int i, n, rc;
639
640     offset = lseek( db_fd, 0, SEEK_END );
641     if( offset == -1 )
642         log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
643     recnum = offset / TRUST_RECORD_LEN;
644     assert(recnum); /* this is will never be the first record */
645
646     if( !type )
647         vr->r.ver.trusthashtbl = recnum;
648
649     /* Now write the records */
650     n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
651     for(i=0; i < n; i++, recnum++ ) {
652          memset( &rec, 0, sizeof rec );
653          rec.rectype = RECTYPE_HTBL;
654          rec.recnum = recnum;
655          rc = tdbio_write_record( &rec );
656          if( rc )
657              log_fatal( _("%s: failed to create hashtable: %s\n"),
658                                         db_name, g10_errstr(rc));
659     }
660     /* update the version record */
661     rc = tdbio_write_record( vr );
662     if( !rc )
663         rc = tdbio_sync();
664     if( rc )
665         log_fatal( _("%s: error updating version record: %s\n"),
666                                                   db_name, g10_errstr(rc));
667 }
668
669
670 int
671 tdbio_db_matches_options()
672 {
673   static int yes_no = -1;
674
675   if( yes_no == -1 )
676     {
677       TRUSTREC vr;
678       int rc;
679
680       rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
681       if( rc )
682         log_fatal( _("%s: error reading version record: %s\n"),
683                    db_name, g10_errstr(rc) );
684
685       yes_no = vr.r.ver.marginals == opt.marginals_needed
686         && vr.r.ver.completes == opt.completes_needed
687         && vr.r.ver.cert_depth == opt.max_cert_depth
688         && vr.r.ver.trust_model == opt.trust_model
689         && vr.r.ver.min_cert_level == opt.min_cert_level;
690     }
691
692   return yes_no;
693 }
694
695 byte
696 tdbio_read_model(void)
697 {
698   TRUSTREC vr;
699   int rc;
700
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.trust_model;
706 }
707
708 /****************
709  * Return the nextstamp value.
710  */
711 ulong
712 tdbio_read_nextcheck ()
713 {
714     TRUSTREC vr;
715     int rc;
716
717     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
718     if( rc )
719         log_fatal( _("%s: error reading version record: %s\n"),
720                                                     db_name, g10_errstr(rc) );
721     return vr.r.ver.nextcheck;
722 }
723
724 /* Return true when the stamp was actually changed. */
725 int
726 tdbio_write_nextcheck (ulong stamp)
727 {
728     TRUSTREC vr;
729     int rc;
730
731     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
732     if( rc )
733         log_fatal( _("%s: error reading version record: %s\n"),
734                                        db_name, g10_errstr(rc) );
735
736     if (vr.r.ver.nextcheck == stamp)
737       return 0;
738
739     vr.r.ver.nextcheck = stamp;
740     rc = tdbio_write_record( &vr );
741     if( rc )
742         log_fatal( _("%s: error writing version record: %s\n"),
743                                        db_name, g10_errstr(rc) );
744     return 1;
745 }
746
747
748
749 /****************
750  * Return the record number of the trusthash tbl or create a new one.
751  */
752 static ulong
753 get_trusthashrec(void)
754 {
755     static ulong trusthashtbl; /* record number of the trust hashtable */
756
757     if( !trusthashtbl ) {
758         TRUSTREC vr;
759         int rc;
760
761         rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
762         if( rc )
763             log_fatal( _("%s: error reading version record: %s\n"),
764                                             db_name, g10_errstr(rc) );
765         if( !vr.r.ver.trusthashtbl )
766             create_hashtable( &vr, 0 );
767
768         trusthashtbl = vr.r.ver.trusthashtbl;
769     }
770     return trusthashtbl;
771 }
772
773
774
775 /****************
776  * Update a hashtable.
777  * table gives the start of the table, key and keylen is the key,
778  * newrecnum is the record number to insert.
779  */
780 static int
781 upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
782 {
783     TRUSTREC lastrec, rec;
784     ulong hashrec, item;
785     int msb;
786     int level=0;
787     int rc, i;
788
789     hashrec = table;
790   next_level:
791     msb = key[level];
792     hashrec += msb / ITEMS_PER_HTBL_RECORD;
793     rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
794     if( rc ) {
795         log_error("upd_hashtable: read failed: %s\n",   g10_errstr(rc) );
796         return rc;
797     }
798
799     item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
800     if( !item ) { /* insert a new item into the hash table */
801         rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
802         rc = tdbio_write_record( &rec );
803         if( rc ) {
804             log_error("upd_hashtable: write htbl failed: %s\n",
805                                                             g10_errstr(rc) );
806             return rc;
807         }
808     }
809     else if( item != newrecnum ) {  /* must do an update */
810         lastrec = rec;
811         rc = tdbio_read_record( item, &rec, 0 );
812         if( rc ) {
813             log_error( "upd_hashtable: read item failed: %s\n",
814                                                             g10_errstr(rc) );
815             return rc;
816         }
817
818         if( rec.rectype == RECTYPE_HTBL ) {
819             hashrec = item;
820             level++;
821             if( level >= keylen ) {
822                 log_error( "hashtable has invalid indirections.\n");
823                 return G10ERR_TRUSTDB;
824             }
825             goto next_level;
826         }
827         else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
828             /* see whether the key is already in this list */
829             for(;;) {
830                 for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
831                     if( rec.r.hlst.rnum[i] == newrecnum ) {
832                         return 0; /* okay, already in the list */
833                     }
834                 }
835                 if( rec.r.hlst.next ) {
836                     rc = tdbio_read_record( rec.r.hlst.next,
837                                                        &rec, RECTYPE_HLST);
838                     if( rc ) {
839                         log_error( "upd_hashtable: read hlst failed: %s\n",
840                                                              g10_errstr(rc) );
841                         return rc;
842                     }
843                 }
844                 else
845                     break; /* not there */
846             }
847             /* find the next free entry and put it in */
848             for(;;) {
849                 for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
850                     if( !rec.r.hlst.rnum[i] ) {
851                         rec.r.hlst.rnum[i] = newrecnum;
852                         rc = tdbio_write_record( &rec );
853                         if( rc )
854                             log_error( "upd_hashtable: write hlst failed: %s\n",
855                                                               g10_errstr(rc) );
856                         return rc; /* done */
857                     }
858                 }
859                 if( rec.r.hlst.next ) {
860                     rc = tdbio_read_record( rec.r.hlst.next,
861                                                       &rec, RECTYPE_HLST );
862                     if( rc ) {
863                         log_error( "upd_hashtable: read hlst failed: %s\n",
864                                                              g10_errstr(rc) );
865                         return rc;
866                     }
867                 }
868                 else { /* add a new list record */
869                     rec.r.hlst.next = item = tdbio_new_recnum();
870                     rc = tdbio_write_record( &rec );
871                     if( rc ) {
872                         log_error( "upd_hashtable: write hlst failed: %s\n",
873                                                           g10_errstr(rc) );
874                         return rc;
875                     }
876                     memset( &rec, 0, sizeof rec );
877                     rec.rectype = RECTYPE_HLST;
878                     rec.recnum = item;
879                     rec.r.hlst.rnum[0] = newrecnum;
880                     rc = tdbio_write_record( &rec );
881                     if( rc )
882                         log_error( "upd_hashtable: write ext hlst failed: %s\n",
883                                                           g10_errstr(rc) );
884                     return rc; /* done */
885                 }
886             } /* end loop over hlst slots */
887         }
888         else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */
889             if( rec.recnum == newrecnum ) {
890                 return 0;
891             }
892             item = rec.recnum; /* save number of key record */
893             memset( &rec, 0, sizeof rec );
894             rec.rectype = RECTYPE_HLST;
895             rec.recnum = tdbio_new_recnum();
896             rec.r.hlst.rnum[0] = item;       /* old keyrecord */
897             rec.r.hlst.rnum[1] = newrecnum; /* and new one */
898             rc = tdbio_write_record( &rec );
899             if( rc ) {
900                 log_error( "upd_hashtable: write new hlst failed: %s\n",
901                                                   g10_errstr(rc) );
902                 return rc;
903             }
904             /* update the hashtable record */
905             lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
906             rc = tdbio_write_record( &lastrec );
907             if( rc )
908                 log_error( "upd_hashtable: update htbl failed: %s\n",
909                                                              g10_errstr(rc) );
910             return rc; /* ready */
911         }
912         else {
913             log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
914                        table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
915             list_trustdb(NULL);
916             return G10ERR_TRUSTDB;
917         }
918     }
919
920     return 0;
921 }
922
923
924 /****************
925  * Drop an entry from a hashtable
926  * table gives the start of the table, key and keylen is the key,
927  */
928 static int
929 drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
930 {
931     TRUSTREC rec;
932     ulong hashrec, item;
933     int msb;
934     int level=0;
935     int rc, i;
936
937     hashrec = table;
938   next_level:
939     msb = key[level];
940     hashrec += msb / ITEMS_PER_HTBL_RECORD;
941     rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
942     if( rc ) {
943         log_error("drop_from_hashtable: read failed: %s\n",
944                                                         g10_errstr(rc) );
945         return rc;
946     }
947
948     item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
949     if( !item )  /* not found - forget about it  */
950         return 0;
951
952     if( item == recnum ) {  /* tables points direct to the record */
953         rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0;
954         rc = tdbio_write_record( &rec );
955         if( rc )
956             log_error("drop_from_hashtable: write htbl failed: %s\n",
957                                                             g10_errstr(rc) );
958         return rc;
959     }
960
961     rc = tdbio_read_record( item, &rec, 0 );
962     if( rc ) {
963         log_error( "drop_from_hashtable: read item failed: %s\n",
964                                                         g10_errstr(rc) );
965         return rc;
966     }
967
968     if( rec.rectype == RECTYPE_HTBL ) {
969         hashrec = item;
970         level++;
971         if( level >= keylen ) {
972             log_error( "hashtable has invalid indirections.\n");
973             return G10ERR_TRUSTDB;
974         }
975         goto next_level;
976     }
977
978     if( rec.rectype == RECTYPE_HLST ) {
979         for(;;) {
980             for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
981                 if( rec.r.hlst.rnum[i] == recnum ) {
982                     rec.r.hlst.rnum[i] = 0; /* drop */
983                     rc = tdbio_write_record( &rec );
984                     if( rc )
985                         log_error("drop_from_hashtable: write htbl failed: %s\n",
986                                                                         g10_errstr(rc) );
987                     return rc;
988                 }
989             }
990             if( rec.r.hlst.next ) {
991                 rc = tdbio_read_record( rec.r.hlst.next,
992                                                    &rec, RECTYPE_HLST);
993                 if( rc ) {
994                     log_error( "drop_from_hashtable: read hlst failed: %s\n",
995                                                          g10_errstr(rc) );
996                     return rc;
997                 }
998             }
999             else
1000                 return 0; /* key not in table */
1001         }
1002     }
1003
1004     log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n",
1005                     table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
1006     return G10ERR_TRUSTDB;
1007 }
1008
1009
1010
1011 /****************
1012  * Lookup a record via the hashtable tablewith key/keylen and return the
1013  * result in rec.  cmp() should return if the record is the desired one.
1014  * Returns -1 if not found, 0 if found or another errocode
1015  */
1016 static int
1017 lookup_hashtable( ulong table, const byte *key, size_t keylen,
1018                   int (*cmpfnc)(const void*, const TRUSTREC *),
1019                   const void *cmpdata, TRUSTREC *rec )
1020 {
1021     int rc;
1022     ulong hashrec, item;
1023     int msb;
1024     int level=0;
1025
1026     hashrec = table;
1027   next_level:
1028     msb = key[level];
1029     hashrec += msb / ITEMS_PER_HTBL_RECORD;
1030     rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
1031     if( rc ) {
1032         log_error("lookup_hashtable failed: %s\n", g10_errstr(rc) );
1033         return rc;
1034     }
1035
1036     item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
1037     if( !item )
1038         return -1; /* not found */
1039
1040     rc = tdbio_read_record( item, rec, 0 );
1041     if( rc ) {
1042         log_error( "hashtable read failed: %s\n", g10_errstr(rc) );
1043         return rc;
1044     }
1045     if( rec->rectype == RECTYPE_HTBL ) {
1046         hashrec = item;
1047         level++;
1048         if( level >= keylen ) {
1049             log_error("hashtable has invalid indirections\n");
1050             return G10ERR_TRUSTDB;
1051         }
1052         goto next_level;
1053     }
1054     else if( rec->rectype == RECTYPE_HLST ) {
1055         for(;;) {
1056             int i;
1057
1058             for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
1059                 if( rec->r.hlst.rnum[i] ) {
1060                     TRUSTREC tmp;
1061
1062                     rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
1063                     if( rc ) {
1064                         log_error( "lookup_hashtable: read item failed: %s\n",
1065                                                               g10_errstr(rc) );
1066                         return rc;
1067                     }
1068                     if( (*cmpfnc)( cmpdata, &tmp ) ) {
1069                         *rec = tmp;
1070                         return 0;
1071                     }
1072                 }
1073             }
1074             if( rec->r.hlst.next ) {
1075                 rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
1076                 if( rc ) {
1077                     log_error( "lookup_hashtable: read hlst failed: %s\n",
1078                                                          g10_errstr(rc) );
1079                     return rc;
1080                 }
1081             }
1082             else
1083                 return -1; /* not found */
1084         }
1085     }
1086
1087
1088     if( (*cmpfnc)( cmpdata, rec ) )
1089         return 0; /* really found */
1090
1091     return -1; /* no: not found */
1092 }
1093
1094
1095 /****************
1096  * Update the trust hashtbl or create the table if it does not exist
1097  */
1098 static int
1099 update_trusthashtbl( TRUSTREC *tr )
1100 {
1101     return upd_hashtable( get_trusthashrec(),
1102                           tr->r.trust.fingerprint, 20, tr->recnum );
1103 }
1104
1105
1106
1107 void
1108 tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
1109 {
1110     int i;
1111     ulong rnum = rec->recnum;
1112
1113     fprintf(fp, "rec %5lu, ", rnum );
1114
1115     switch( rec->rectype ) {
1116       case 0: fprintf(fp, "blank\n");
1117         break;
1118       case RECTYPE_VER: fprintf(fp,
1119             "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d mcl=%d nc=%lu (%s)\n",
1120                                    rec->r.ver.trusthashtbl,
1121                                    rec->r.ver.firstfree,
1122                                    rec->r.ver.marginals,
1123                                    rec->r.ver.completes,
1124                                    rec->r.ver.cert_depth,
1125                                    rec->r.ver.trust_model,
1126                                    rec->r.ver.min_cert_level,
1127                                    rec->r.ver.nextcheck,
1128                                    strtimestamp(rec->r.ver.nextcheck)
1129                                  );
1130         break;
1131       case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
1132         break;
1133       case RECTYPE_HTBL:
1134         fprintf(fp, "htbl,");
1135         for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
1136             fprintf(fp, " %lu", rec->r.htbl.item[i] );
1137         putc('\n', fp);
1138         break;
1139       case RECTYPE_HLST:
1140         fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next );
1141         for(i=0; i < ITEMS_PER_HLST_RECORD; i++ )
1142             fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
1143         putc('\n', fp);
1144         break;
1145       case RECTYPE_TRUST:
1146         fprintf(fp, "trust ");
1147         for(i=0; i < 20; i++ )
1148             fprintf(fp, "%02X", rec->r.trust.fingerprint[i] );
1149         fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust,
1150                  rec->r.trust.depth, rec->r.trust.validlist);
1151         break;
1152       case RECTYPE_VALID:
1153         fprintf(fp, "valid ");
1154         for(i=0; i < 20; i++ )
1155             fprintf(fp, "%02X", rec->r.valid.namehash[i] );
1156         fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity,
1157                  rec->r.valid.next);
1158         break;
1159       default:
1160         fprintf(fp, "unknown type %d\n", rec->rectype );
1161         break;
1162     }
1163 }
1164
1165 /****************
1166  * read the record with number recnum
1167  * returns: -1 on error, 0 on success
1168  */
1169 int
1170 tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
1171 {
1172     byte readbuf[TRUST_RECORD_LEN];
1173     const byte *buf, *p;
1174     int rc = 0;
1175     int n, i;
1176
1177     if( db_fd == -1 )
1178         open_db();
1179     buf = get_record_from_cache( recnum );
1180     if( !buf ) {
1181         if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
1182             log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
1183             return G10ERR_READ_FILE;
1184         }
1185         n = read( db_fd, readbuf, TRUST_RECORD_LEN);
1186         if( !n ) {
1187             return -1; /* eof */
1188         }
1189         else if( n != TRUST_RECORD_LEN ) {
1190             log_error(_("trustdb: read failed (n=%d): %s\n"), n,
1191                                                         strerror(errno) );
1192             return G10ERR_READ_FILE;
1193         }
1194         buf = readbuf;
1195     }
1196     rec->recnum = recnum;
1197     rec->dirty = 0;
1198     p = buf;
1199     rec->rectype = *p++;
1200     if( expected && rec->rectype != expected ) {
1201         log_error("%lu: read expected rec type %d, got %d\n",
1202                     recnum, expected, rec->rectype );
1203         return G10ERR_TRUSTDB;
1204     }
1205     p++;    /* skip reserved byte */
1206     switch( rec->rectype ) {
1207       case 0:  /* unused (free) record */
1208         break;
1209       case RECTYPE_VER: /* version record */
1210         if( memcmp(buf+1, "gpg", 3 ) ) {
1211             log_error( _("%s: not a trustdb file\n"), db_name );
1212             rc = G10ERR_TRUSTDB;
1213         }
1214         p += 2; /* skip "gpg" */
1215         rec->r.ver.version  = *p++;
1216         rec->r.ver.marginals = *p++;
1217         rec->r.ver.completes = *p++;
1218         rec->r.ver.cert_depth = *p++;
1219         rec->r.ver.trust_model = *p++;
1220         rec->r.ver.min_cert_level = *p++;
1221         p += 2;
1222         rec->r.ver.created  = buftoulong(p); p += 4;
1223         rec->r.ver.nextcheck = buftoulong(p); p += 4;
1224         p += 4;
1225         p += 4;
1226         rec->r.ver.firstfree =buftoulong(p); p += 4;
1227         p += 4;
1228         rec->r.ver.trusthashtbl =buftoulong(p); p += 4;
1229         if( recnum ) {
1230             log_error( _("%s: version record with recnum %lu\n"), db_name,
1231                                                              (ulong)recnum );
1232             rc = G10ERR_TRUSTDB;
1233         }
1234         else if( rec->r.ver.version != 3 ) {
1235             log_error( _("%s: invalid file version %d\n"), db_name,
1236                                                         rec->r.ver.version );
1237             rc = G10ERR_TRUSTDB;
1238         }
1239         break;
1240       case RECTYPE_FREE:
1241         rec->r.free.next  = buftoulong(p); p += 4;
1242         break;
1243       case RECTYPE_HTBL:
1244         for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
1245             rec->r.htbl.item[i] = buftoulong(p); p += 4;
1246         }
1247         break;
1248       case RECTYPE_HLST:
1249         rec->r.hlst.next = buftoulong(p); p += 4;
1250         for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
1251             rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
1252         }
1253         break;
1254       case RECTYPE_TRUST:
1255         memcpy( rec->r.trust.fingerprint, p, 20); p+=20;
1256         rec->r.trust.ownertrust = *p++;
1257         rec->r.trust.depth = *p++;
1258         rec->r.trust.min_ownertrust = *p++;
1259         p++;
1260         rec->r.trust.validlist = buftoulong(p); p += 4;
1261         break;
1262       case RECTYPE_VALID:
1263         memcpy( rec->r.valid.namehash, p, 20); p+=20;
1264         rec->r.valid.validity = *p++;
1265         rec->r.valid.next = buftoulong(p); p += 4;
1266         rec->r.valid.full_count = *p++;
1267         rec->r.valid.marginal_count = *p++;
1268         break;
1269       default:
1270         log_error( "%s: invalid record type %d at recnum %lu\n",
1271                                    db_name, rec->rectype, (ulong)recnum );
1272         rc = G10ERR_TRUSTDB;
1273         break;
1274     }
1275
1276     return rc;
1277 }
1278
1279 /****************
1280  * Write the record at RECNUM
1281  */
1282 int
1283 tdbio_write_record( TRUSTREC *rec )
1284 {
1285     byte buf[TRUST_RECORD_LEN], *p;
1286     int rc = 0;
1287     int i;
1288     ulong recnum = rec->recnum;
1289
1290     if( db_fd == -1 )
1291         open_db();
1292
1293     memset(buf, 0, TRUST_RECORD_LEN);
1294     p = buf;
1295     *p++ = rec->rectype; p++;
1296     switch( rec->rectype ) {
1297       case 0:  /* unused record */
1298         break;
1299       case RECTYPE_VER: /* version record */
1300         if( recnum )
1301             BUG();
1302         memcpy(p-1, "gpg", 3 ); p += 2;
1303         *p++ = rec->r.ver.version;
1304         *p++ = rec->r.ver.marginals;
1305         *p++ = rec->r.ver.completes;
1306         *p++ = rec->r.ver.cert_depth;
1307         *p++ = rec->r.ver.trust_model;
1308         *p++ = rec->r.ver.min_cert_level;
1309         p += 2;
1310         ulongtobuf(p, rec->r.ver.created); p += 4;
1311         ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
1312         p += 4;
1313         p += 4;
1314         ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
1315         p += 4;
1316         ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
1317         break;
1318
1319       case RECTYPE_FREE:
1320         ulongtobuf(p, rec->r.free.next); p += 4;
1321         break;
1322
1323
1324       case RECTYPE_HTBL:
1325         for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
1326             ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
1327         }
1328         break;
1329
1330       case RECTYPE_HLST:
1331         ulongtobuf( p, rec->r.hlst.next); p += 4;
1332         for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
1333             ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
1334         }
1335         break;
1336
1337       case RECTYPE_TRUST:
1338         memcpy( p, rec->r.trust.fingerprint, 20); p += 20;
1339         *p++ = rec->r.trust.ownertrust;
1340         *p++ = rec->r.trust.depth;
1341         *p++ = rec->r.trust.min_ownertrust;
1342         p++;
1343         ulongtobuf( p, rec->r.trust.validlist); p += 4;
1344         break;
1345
1346       case RECTYPE_VALID:
1347         memcpy( p, rec->r.valid.namehash, 20); p += 20;
1348         *p++ = rec->r.valid.validity;
1349         ulongtobuf( p, rec->r.valid.next); p += 4;
1350         *p++ = rec->r.valid.full_count;
1351         *p++ = rec->r.valid.marginal_count;
1352         break;
1353
1354       default:
1355         BUG();
1356     }
1357
1358     rc = put_record_into_cache( recnum, buf );
1359     if( rc )
1360         ;
1361     else if( rec->rectype == RECTYPE_TRUST )
1362         rc = update_trusthashtbl( rec );
1363
1364     return rc;
1365 }
1366
1367 int
1368 tdbio_delete_record( ulong recnum )
1369 {
1370     TRUSTREC vr, rec;
1371     int rc;
1372
1373     /* Must read the record fist, so we can drop it from the hash tables */
1374     rc = tdbio_read_record( recnum, &rec, 0 );
1375     if( rc )
1376         ;
1377     else if( rec.rectype == RECTYPE_TRUST ) {
1378          rc = drop_from_hashtable( get_trusthashrec(),
1379                                    rec.r.trust.fingerprint, 20, rec.recnum );
1380     }
1381
1382     if( rc )
1383         return rc;
1384
1385     /* now we can chnage it to a free record */
1386     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
1387     if( rc )
1388         log_fatal( _("%s: error reading version record: %s\n"),
1389                                        db_name, g10_errstr(rc) );
1390
1391     rec.recnum = recnum;
1392     rec.rectype = RECTYPE_FREE;
1393     rec.r.free.next = vr.r.ver.firstfree;
1394     vr.r.ver.firstfree = recnum;
1395     rc = tdbio_write_record( &rec );
1396     if( !rc )
1397         rc = tdbio_write_record( &vr );
1398     return rc;
1399 }
1400
1401 /****************
1402  * create a new record and return its record number
1403  */
1404 ulong
1405 tdbio_new_recnum()
1406 {
1407     off_t offset;
1408     ulong recnum;
1409     TRUSTREC vr, rec;
1410     int rc;
1411
1412     /* look for unused records */
1413     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
1414     if( rc )
1415         log_fatal( _("%s: error reading version record: %s\n"),
1416                                              db_name, g10_errstr(rc) );
1417     if( vr.r.ver.firstfree ) {
1418         recnum = vr.r.ver.firstfree;
1419         rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE );
1420         if( rc ) {
1421             log_error( _("%s: error reading free record: %s\n"),
1422                                                   db_name,  g10_errstr(rc) );
1423             return rc;
1424         }
1425         /* update dir record */
1426         vr.r.ver.firstfree = rec.r.free.next;
1427         rc = tdbio_write_record( &vr );
1428         if( rc ) {
1429             log_error( _("%s: error writing dir record: %s\n"),
1430                                                      db_name, g10_errstr(rc) );
1431             return rc;
1432         }
1433         /*zero out the new record */
1434         memset( &rec, 0, sizeof rec );
1435         rec.rectype = 0; /* unused record */
1436         rec.recnum = recnum;
1437         rc = tdbio_write_record( &rec );
1438         if( rc )
1439             log_fatal(_("%s: failed to zero a record: %s\n"),
1440                                        db_name, g10_errstr(rc));
1441     }
1442     else { /* not found, append a new record */
1443         offset = lseek( db_fd, 0, SEEK_END );
1444         if( offset == -1 )
1445             log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
1446         recnum = offset / TRUST_RECORD_LEN;
1447         assert(recnum); /* this is will never be the first record */
1448         /* we must write a record, so that the next call to this function
1449          * returns another recnum */
1450         memset( &rec, 0, sizeof rec );
1451         rec.rectype = 0; /* unused record */
1452         rec.recnum = recnum;
1453         rc = 0;
1454         if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
1455             log_error(_("trustdb rec %lu: lseek failed: %s\n"),
1456                                                 recnum, strerror(errno) );
1457             rc = G10ERR_WRITE_FILE;
1458         }
1459         else {
1460             int n = write( db_fd, &rec, TRUST_RECORD_LEN);
1461             if( n != TRUST_RECORD_LEN ) {
1462                 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
1463                                                  recnum, n, strerror(errno) );
1464                 rc = G10ERR_WRITE_FILE;
1465             }
1466         }
1467
1468         if( rc )
1469             log_fatal(_("%s: failed to append a record: %s\n"),
1470                                     db_name,    g10_errstr(rc));
1471     }
1472     return recnum ;
1473 }
1474
1475
1476
1477 static int
1478 cmp_trec_fpr (const void *fpr, const TRUSTREC *rec )
1479 {
1480     return (rec->rectype == RECTYPE_TRUST
1481             && !memcmp( rec->r.trust.fingerprint, fpr, 20));
1482 }
1483
1484
1485 int
1486 tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec )
1487 {
1488     int rc;
1489
1490     /* Locate the trust record using the hash table.  */
1491     rc = lookup_hashtable (get_trusthashrec(), fingerprint, 20,
1492                            cmp_trec_fpr, fingerprint, rec);
1493     return rc;
1494 }
1495
1496 int
1497 tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
1498 {
1499     byte fingerprint[MAX_FINGERPRINT_LEN];
1500     size_t fingerlen;
1501
1502     fingerprint_from_pk( pk, fingerprint, &fingerlen );
1503     for (; fingerlen < 20; fingerlen++ )
1504       fingerprint[fingerlen] = 0;
1505     return tdbio_search_trust_byfpr (fingerprint, rec);
1506 }
1507
1508
1509
1510 void
1511 tdbio_invalid(void)
1512 {
1513   log_error (_("Error: The trustdb is corrupted.\n"));
1514   how_to_fix_the_trustdb ();
1515   g10_exit (2);
1516 }
1517
1518 /*
1519  * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2)
1520  * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs
1521  * only to scan the tdb and insert new the new trust records.  The old ones are
1522  * obsolte from now on
1523  */
1524 static void
1525 migrate_from_v2 ()
1526 {
1527   TRUSTREC rec;
1528   int i, n;
1529   struct {
1530     ulong keyrecno;
1531     byte  ot;
1532     byte okay;
1533     byte  fpr[20];
1534   } *ottable;
1535   int ottable_size, ottable_used;
1536   byte oldbuf[40];
1537   ulong recno;
1538   int rc, count;
1539
1540   ottable_size = 5;
1541   ottable = xmalloc (ottable_size * sizeof *ottable);
1542   ottable_used = 0;
1543
1544   /* We have some restrictions here.  We can't use the version record
1545    * and we can't use any of the old hashtables because we dropped the
1546    * code.  So we first collect all ownertrusts and then use a second
1547    * pass fo find the associated keys.  We have to do this all without using
1548    * the regular record read functions.
1549    */
1550
1551   /* get all the ownertrusts */
1552   if (lseek (db_fd, 0, SEEK_SET ) == -1 )
1553       log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
1554   for (recno=0;;recno++)
1555     {
1556       do
1557         n = read (db_fd, oldbuf, 40);
1558       while (n==-1 && errno == EINTR);
1559       if (!n)
1560         break; /* eof */
1561       if (n != 40)
1562         log_fatal ("migrate_vfrom_v2: read error or short read\n");
1563
1564       if (*oldbuf != 2)
1565         continue;
1566
1567       /* v2 dir record */
1568       if (ottable_used == ottable_size)
1569         {
1570           ottable_size += 1000;
1571           ottable = xrealloc (ottable, ottable_size * sizeof *ottable);
1572         }
1573       ottable[ottable_used].keyrecno = buftoulong (oldbuf+6);
1574       ottable[ottable_used].ot = oldbuf[18];
1575       ottable[ottable_used].okay = 0;
1576       memset (ottable[ottable_used].fpr,0, 20);
1577       if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot)
1578         ottable_used++;
1579     }
1580   log_info ("found %d ownertrust records\n", ottable_used);
1581
1582   /* Read again and find the fingerprints */
1583   if (lseek (db_fd, 0, SEEK_SET ) == -1 )
1584       log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
1585   for (recno=0;;recno++)
1586     {
1587       do
1588         n = read (db_fd, oldbuf, 40);
1589       while (n==-1 && errno == EINTR);
1590       if (!n)
1591         break; /* eof */
1592       if (n != 40)
1593         log_fatal ("migrate_from_v2: read error or short read\n");
1594
1595       if (*oldbuf != 3)
1596         continue;
1597
1598       /* v2 key record */
1599       for (i=0; i < ottable_used; i++)
1600         {
1601           if (ottable[i].keyrecno == recno)
1602             {
1603               memcpy (ottable[i].fpr, oldbuf+20, 20);
1604               ottable[i].okay = 1;
1605               break;
1606             }
1607         }
1608     }
1609
1610   /* got everything - create the v3 trustdb */
1611   if (ftruncate (db_fd, 0))
1612     log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) );
1613   if (create_version_record ())
1614     log_fatal ("failed to recreate version record of `%s'\n", db_name);
1615
1616   /* access the hash table, so it is store just after the version record,
1617    * this is not needed put a dump is more pretty */
1618   get_trusthashrec ();
1619
1620   /* And insert the old ownertrust values */
1621   count = 0;
1622   for (i=0; i < ottable_used; i++)
1623     {
1624       if (!ottable[i].okay)
1625         continue;
1626
1627       memset (&rec, 0, sizeof rec);
1628       rec.recnum = tdbio_new_recnum ();
1629       rec.rectype = RECTYPE_TRUST;
1630       memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20);
1631       rec.r.trust.ownertrust = ottable[i].ot;
1632       if (tdbio_write_record (&rec))
1633         log_fatal ("failed to write trust record of `%s'\n", db_name);
1634       count++;
1635     }
1636
1637   revalidation_mark ();
1638   rc = tdbio_sync ();
1639   if (rc)
1640     log_fatal ("failed to sync `%s'\n", db_name);
1641   log_info ("migrated %d version 2 ownertrusts\n", count);
1642   xfree (ottable);
1643 }