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