use of EXTSEP_S
[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     check_permissions(fname,0,0);
451
452     if( access( fname, R_OK ) ) {
453         if( errno != ENOENT ) {
454             log_error( _("%s: can't access: %s\n"), fname, strerror(errno) );
455             m_free(fname);
456             return G10ERR_TRUSTDB;
457         }
458         if( create ) {
459             FILE *fp;
460             TRUSTREC rec;
461             int rc;
462             char *p = strrchr( fname, DIRSEP_C );
463
464             assert(p);
465             *p = 0;
466             if( access( fname, F_OK ) ) {
467                 try_make_homedir( fname );
468                 log_fatal( _("%s: directory does not exist!\n"), fname );
469             }
470             *p = DIRSEP_C;
471
472             m_free(db_name);
473             db_name = fname;
474 #ifdef __riscos__
475             if( !lockhandle )
476                 lockhandle = create_dotlock( db_name );
477             if( !lockhandle )
478                 log_fatal( _("%s: can't create lock\n"), db_name );
479             if( make_dotlock( lockhandle, -1 ) )
480                 log_fatal( _("%s: can't make lock\n"), db_name );
481 #endif /* __riscos__ */
482             fp =fopen( fname, "wb" );
483             if( !fp )
484                 log_fatal( _("%s: can't create: %s\n"), fname, strerror(errno) );
485             fclose(fp);
486           #ifdef HAVE_DOSISH_SYSTEM
487             db_fd = open( db_name, O_RDWR | O_BINARY );
488           #else
489             db_fd = open( db_name, O_RDWR );
490           #endif
491             if( db_fd == -1 )
492                 log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
493
494 #ifndef __riscos__
495             if( !lockhandle )
496                 lockhandle = create_dotlock( db_name );
497             if( !lockhandle )
498                 log_fatal( _("%s: can't create lock\n"), db_name );
499 #endif /* !__riscos__ */
500
501             rc = create_version_record ();
502             if( rc )
503                 log_fatal( _("%s: failed to create version record: %s"),
504                                                    fname, g10_errstr(rc));
505             /* and read again to check that we are okay */
506             if( tdbio_read_record( 0, &rec, RECTYPE_VER ) )
507                 log_fatal( _("%s: invalid trustdb created\n"), db_name );
508
509             if( !opt.quiet )
510                 log_info(_("%s: trustdb created\n"), db_name);
511
512             return 0;
513         }
514     }
515     m_free(db_name);
516     db_name = fname;
517     return 0;
518 }
519
520
521 const char *
522 tdbio_get_dbname()
523 {
524     return db_name;
525 }
526
527
528
529 static void
530 open_db()
531 {
532   byte buf[10];
533   int n;
534   TRUSTREC rec;
535
536   assert( db_fd == -1 );
537
538   if (!lockhandle )
539     lockhandle = create_dotlock( db_name );
540   if (!lockhandle )
541     log_fatal( _("%s: can't create lock\n"), db_name );
542 #ifdef __riscos__
543   if (make_dotlock( lockhandle, -1 ) )
544     log_fatal( _("%s: can't make lock\n"), db_name );
545 #endif /* __riscos__ */
546 #ifdef HAVE_DOSISH_SYSTEM
547   db_fd = open (db_name, O_RDWR | O_BINARY );
548 #else
549   db_fd = open (db_name, O_RDWR );
550 #endif
551   if ( db_fd == -1 )
552     log_fatal( _("%s: can't open: %s\n"), db_name, strerror(errno) );
553
554   /* check whether we need to do a version migration */
555   do
556     n = read (db_fd, buf, 5);
557   while (n==-1 && errno == EINTR);
558   if (n == 5 && !memcmp (buf, "\x01gpg\x02", 5))
559     {
560       migrate_from_v2 ();
561     }
562   
563   /* read the version record */
564   if (tdbio_read_record (0, &rec, RECTYPE_VER ) )
565     log_fatal( _("%s: invalid trustdb\n"), db_name );
566 }
567
568
569 /****************
570  * Make a hashtable: type 0 = trust hash
571  */
572 static void
573 create_hashtable( TRUSTREC *vr, int type )
574 {
575     TRUSTREC rec;
576     off_t offset;
577     ulong recnum;
578     int i, n, rc;
579
580     offset = lseek( db_fd, 0, SEEK_END );
581     if( offset == -1 )
582         log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
583     recnum = offset / TRUST_RECORD_LEN;
584     assert(recnum); /* this is will never be the first record */
585
586     if( !type )
587         vr->r.ver.trusthashtbl = recnum;
588
589     /* Now write the records */
590     n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
591     for(i=0; i < n; i++, recnum++ ) {
592          memset( &rec, 0, sizeof rec );
593          rec.rectype = RECTYPE_HTBL;
594          rec.recnum = recnum;
595          rc = tdbio_write_record( &rec );
596          if( rc )
597              log_fatal( _("%s: failed to create hashtable: %s\n"),
598                                         db_name, g10_errstr(rc));
599     }
600     /* update the version record */
601     rc = tdbio_write_record( vr );
602     if( !rc )
603         rc = tdbio_sync();
604     if( rc )
605         log_fatal( _("%s: error updating version record: %s\n"),
606                                                   db_name, g10_errstr(rc));
607 }
608
609
610 int
611 tdbio_db_matches_options()
612 {
613     static int yes_no = -1;
614
615     if( yes_no == -1 ) {
616         TRUSTREC vr;
617         int rc;
618
619         rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
620         if( rc )
621             log_fatal( _("%s: error reading version record: %s\n"),
622                                                     db_name, g10_errstr(rc) );
623
624         if( !vr.r.ver.marginals && !vr.r.ver.completes
625                                 && !vr.r.ver.cert_depth )
626         {   /* special hack for trustdbs created by old versions of GnuPG */
627             vr.r.ver.marginals =  opt.marginals_needed;
628             vr.r.ver.completes =  opt.completes_needed;
629             vr.r.ver.cert_depth = opt.max_cert_depth;
630             rc = tdbio_write_record( &vr );
631             if( !rc && !in_transaction )
632                 rc = tdbio_sync();
633             if( rc )
634                 log_error( _("%s: error writing version record: %s\n"),
635                                                 db_name, g10_errstr(rc) );
636         }
637
638         yes_no = vr.r.ver.marginals == opt.marginals_needed
639                  && vr.r.ver.completes == opt.completes_needed
640                  && vr.r.ver.cert_depth == opt.max_cert_depth;
641     }
642     return yes_no;
643 }
644
645
646 /****************
647  * Return the nextstamp value.
648  */
649 ulong
650 tdbio_read_nextcheck ()
651 {
652     TRUSTREC vr;
653     int rc;
654
655     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
656     if( rc )
657         log_fatal( _("%s: error reading version record: %s\n"),
658                                                     db_name, g10_errstr(rc) );
659     return vr.r.ver.nextcheck;
660 }
661
662 /* Return true when the stamp was actually changed. */
663 int
664 tdbio_write_nextcheck (ulong stamp)
665 {
666     TRUSTREC vr;
667     int rc;
668
669     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
670     if( rc )
671         log_fatal( _("%s: error reading version record: %s\n"),
672                                        db_name, g10_errstr(rc) );
673
674     if (vr.r.ver.nextcheck == stamp)
675       return 0;
676
677     vr.r.ver.nextcheck = stamp;
678     rc = tdbio_write_record( &vr );
679     if( rc )
680         log_fatal( _("%s: error writing version record: %s\n"),
681                                        db_name, g10_errstr(rc) );
682     return 1;
683 }
684
685
686
687 /****************
688  * Return the record number of the trusthash tbl or create a new one.
689  */
690 static ulong
691 get_trusthashrec(void)
692 {
693     static ulong trusthashtbl; /* record number of the trust hashtable */
694
695     if( !trusthashtbl ) {
696         TRUSTREC vr;
697         int rc;
698
699         rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
700         if( rc )
701             log_fatal( _("%s: error reading version record: %s\n"),
702                                             db_name, g10_errstr(rc) );
703         if( !vr.r.ver.trusthashtbl )
704             create_hashtable( &vr, 0 );
705
706         trusthashtbl = vr.r.ver.trusthashtbl;
707     }
708     return trusthashtbl;
709 }
710
711
712
713 /****************
714  * Update a hashtable.
715  * table gives the start of the table, key and keylen is the key,
716  * newrecnum is the record number to insert.
717  */
718 static int
719 upd_hashtable( ulong table, byte *key, int keylen, ulong newrecnum )
720 {
721     TRUSTREC lastrec, rec;
722     ulong hashrec, item;
723     int msb;
724     int level=0;
725     int rc, i;
726
727     hashrec = table;
728   next_level:
729     msb = key[level];
730     hashrec += msb / ITEMS_PER_HTBL_RECORD;
731     rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
732     if( rc ) {
733         log_error( db_name, "upd_hashtable: read failed: %s\n",
734                                                         g10_errstr(rc) );
735         return rc;
736     }
737
738     item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
739     if( !item ) { /* insert a new item into the hash table */
740         rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
741         rc = tdbio_write_record( &rec );
742         if( rc ) {
743             log_error( db_name, "upd_hashtable: write htbl failed: %s\n",
744                                                             g10_errstr(rc) );
745             return rc;
746         }
747     }
748     else if( item != newrecnum ) {  /* must do an update */
749         lastrec = rec;
750         rc = tdbio_read_record( item, &rec, 0 );
751         if( rc ) {
752             log_error( "upd_hashtable: read item failed: %s\n",
753                                                             g10_errstr(rc) );
754             return rc;
755         }
756
757         if( rec.rectype == RECTYPE_HTBL ) {
758             hashrec = item;
759             level++;
760             if( level >= keylen ) {
761                 log_error( "hashtable has invalid indirections.\n");
762                 return G10ERR_TRUSTDB;
763             }
764             goto next_level;
765         }
766         else if( rec.rectype == RECTYPE_HLST ) { /* extend list */
767             /* see whether the key is already in this list */
768             for(;;) {
769                 for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
770                     if( rec.r.hlst.rnum[i] == newrecnum ) {
771                         return 0; /* okay, already in the list */
772                     }
773                 }
774                 if( rec.r.hlst.next ) {
775                     rc = tdbio_read_record( rec.r.hlst.next,
776                                                        &rec, RECTYPE_HLST);
777                     if( rc ) {
778                         log_error( "upd_hashtable: read hlst failed: %s\n",
779                                                              g10_errstr(rc) );
780                         return rc;
781                     }
782                 }
783                 else
784                     break; /* not there */
785             }
786             /* find the next free entry and put it in */
787             for(;;) {
788                 for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
789                     if( !rec.r.hlst.rnum[i] ) {
790                         rec.r.hlst.rnum[i] = newrecnum;
791                         rc = tdbio_write_record( &rec );
792                         if( rc )
793                             log_error( "upd_hashtable: write hlst failed: %s\n",
794                                                               g10_errstr(rc) );
795                         return rc; /* done */
796                     }
797                 }
798                 if( rec.r.hlst.next ) {
799                     rc = tdbio_read_record( rec.r.hlst.next,
800                                                       &rec, RECTYPE_HLST );
801                     if( rc ) {
802                         log_error( "upd_hashtable: read hlst failed: %s\n",
803                                                              g10_errstr(rc) );
804                         return rc;
805                     }
806                 }
807                 else { /* add a new list record */
808                     rec.r.hlst.next = item = tdbio_new_recnum();
809                     rc = tdbio_write_record( &rec );
810                     if( rc ) {
811                         log_error( "upd_hashtable: write hlst failed: %s\n",
812                                                           g10_errstr(rc) );
813                         return rc;
814                     }
815                     memset( &rec, 0, sizeof rec );
816                     rec.rectype = RECTYPE_HLST;
817                     rec.recnum = item;
818                     rec.r.hlst.rnum[0] = newrecnum;
819                     rc = tdbio_write_record( &rec );
820                     if( rc )
821                         log_error( "upd_hashtable: write ext hlst failed: %s\n",
822                                                           g10_errstr(rc) );
823                     return rc; /* done */
824                 }
825             } /* end loop over hlst slots */
826         }
827         else if( rec.rectype == RECTYPE_TRUST ) { /* insert a list record */
828             if( rec.recnum == newrecnum ) {
829                 return 0;
830             }
831             item = rec.recnum; /* save number of key record */
832             memset( &rec, 0, sizeof rec );
833             rec.rectype = RECTYPE_HLST;
834             rec.recnum = tdbio_new_recnum();
835             rec.r.hlst.rnum[0] = item;       /* old keyrecord */
836             rec.r.hlst.rnum[1] = newrecnum; /* and new one */
837             rc = tdbio_write_record( &rec );
838             if( rc ) {
839                 log_error( "upd_hashtable: write new hlst failed: %s\n",
840                                                   g10_errstr(rc) );
841                 return rc;
842             }
843             /* update the hashtable record */
844             lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
845             rc = tdbio_write_record( &lastrec );
846             if( rc )
847                 log_error( "upd_hashtable: update htbl failed: %s\n",
848                                                              g10_errstr(rc) );
849             return rc; /* ready */
850         }
851         else {
852             log_error( "hashtbl %lu: %lu/%d points to an invalid record %lu\n",
853                        table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
854             list_trustdb(NULL);
855             return G10ERR_TRUSTDB;
856         }
857     }
858
859     return 0;
860 }
861
862
863 /****************
864  * Drop an entry from a hashtable
865  * table gives the start of the table, key and keylen is the key,
866  */
867 static int
868 drop_from_hashtable( ulong table, byte *key, int keylen, ulong recnum )
869 {
870     TRUSTREC rec;
871     ulong hashrec, item;
872     int msb;
873     int level=0;
874     int rc, i;
875
876     hashrec = table;
877   next_level:
878     msb = key[level];
879     hashrec += msb / ITEMS_PER_HTBL_RECORD;
880     rc = tdbio_read_record( hashrec, &rec, RECTYPE_HTBL );
881     if( rc ) {
882         log_error( db_name, "drop_from_hashtable: read failed: %s\n",
883                                                         g10_errstr(rc) );
884         return rc;
885     }
886
887     item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
888     if( !item )  /* not found - forget about it  */
889         return 0;
890
891     if( item == recnum ) {  /* tables points direct to the record */
892         rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0;
893         rc = tdbio_write_record( &rec );
894         if( rc )
895             log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n",
896                                                             g10_errstr(rc) );
897         return rc;
898     }
899
900     rc = tdbio_read_record( item, &rec, 0 );
901     if( rc ) {
902         log_error( "drop_from_hashtable: read item failed: %s\n",
903                                                         g10_errstr(rc) );
904         return rc;
905     }
906
907     if( rec.rectype == RECTYPE_HTBL ) {
908         hashrec = item;
909         level++;
910         if( level >= keylen ) {
911             log_error( "hashtable has invalid indirections.\n");
912             return G10ERR_TRUSTDB;
913         }
914         goto next_level;
915     }
916
917     if( rec.rectype == RECTYPE_HLST ) {
918         for(;;) {
919             for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
920                 if( rec.r.hlst.rnum[i] == recnum ) {
921                     rec.r.hlst.rnum[i] = 0; /* drop */
922                     rc = tdbio_write_record( &rec );
923                     if( rc )
924                         log_error( db_name, "drop_from_hashtable: write htbl failed: %s\n",
925                                                                         g10_errstr(rc) );
926                     return rc;
927                 }
928             }
929             if( rec.r.hlst.next ) {
930                 rc = tdbio_read_record( rec.r.hlst.next,
931                                                    &rec, RECTYPE_HLST);
932                 if( rc ) {
933                     log_error( "drop_from_hashtable: read hlst failed: %s\n",
934                                                          g10_errstr(rc) );
935                     return rc;
936                 }
937             }
938             else
939                 return 0; /* key not in table */
940         }
941     }
942
943     log_error( "hashtbl %lu: %lu/%d points to wrong record %lu\n",
944                     table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
945     return G10ERR_TRUSTDB;
946 }
947
948
949
950 /****************
951  * Lookup a record via the hashtable tablewith key/keylen and return the
952  * result in rec.  cmp() should return if the record is the desired one.
953  * Returns -1 if not found, 0 if found or another errocode
954  */
955 static int
956 lookup_hashtable( ulong table, const byte *key, size_t keylen,
957                   int (*cmpfnc)(void*, const TRUSTREC *), void *cmpdata,
958                                                 TRUSTREC *rec )
959 {
960     int rc;
961     ulong hashrec, item;
962     int msb;
963     int level=0;
964
965     hashrec = table;
966   next_level:
967     msb = key[level];
968     hashrec += msb / ITEMS_PER_HTBL_RECORD;
969     rc = tdbio_read_record( hashrec, rec, RECTYPE_HTBL );
970     if( rc ) {
971         log_error( db_name, "lookup_hashtable failed: %s\n", g10_errstr(rc) );
972         return rc;
973     }
974
975     item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
976     if( !item )
977         return -1; /* not found */
978
979     rc = tdbio_read_record( item, rec, 0 );
980     if( rc ) {
981         log_error( db_name, "hashtable read failed: %s\n", g10_errstr(rc) );
982         return rc;
983     }
984     if( rec->rectype == RECTYPE_HTBL ) {
985         hashrec = item;
986         level++;
987         if( level >= keylen ) {
988             log_error( db_name, "hashtable has invalid indirections\n");
989             return G10ERR_TRUSTDB;
990         }
991         goto next_level;
992     }
993     else if( rec->rectype == RECTYPE_HLST ) {
994         for(;;) {
995             int i;
996
997             for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
998                 if( rec->r.hlst.rnum[i] ) {
999                     TRUSTREC tmp;
1000
1001                     rc = tdbio_read_record( rec->r.hlst.rnum[i], &tmp, 0 );
1002                     if( rc ) {
1003                         log_error( "lookup_hashtable: read item failed: %s\n",
1004                                                               g10_errstr(rc) );
1005                         return rc;
1006                     }
1007                     if( (*cmpfnc)( cmpdata, &tmp ) ) {
1008                         *rec = tmp;
1009                         return 0;
1010                     }
1011                 }
1012             }
1013             if( rec->r.hlst.next ) {
1014                 rc = tdbio_read_record( rec->r.hlst.next, rec, RECTYPE_HLST );
1015                 if( rc ) {
1016                     log_error( "lookup_hashtable: read hlst failed: %s\n",
1017                                                          g10_errstr(rc) );
1018                     return rc;
1019                 }
1020             }
1021             else
1022                 return -1; /* not found */
1023         }
1024     }
1025
1026
1027     if( (*cmpfnc)( cmpdata, rec ) )
1028         return 0; /* really found */
1029
1030     return -1; /* no: not found */
1031 }
1032
1033
1034 /****************
1035  * Update the trust hashtbl or create the table if it does not exist
1036  */
1037 static int
1038 update_trusthashtbl( TRUSTREC *tr )
1039 {
1040     return upd_hashtable( get_trusthashrec(),
1041                           tr->r.trust.fingerprint, 20, tr->recnum );
1042 }
1043
1044
1045
1046 void
1047 tdbio_dump_record( TRUSTREC *rec, FILE *fp  )
1048 {
1049     int i;
1050     ulong rnum = rec->recnum;
1051
1052     fprintf(fp, "rec %5lu, ", rnum );
1053
1054     switch( rec->rectype ) {
1055       case 0: fprintf(fp, "blank\n");
1056         break;
1057       case RECTYPE_VER: fprintf(fp,
1058             "version, td=%lu, f=%lu, m/c/d=%d/%d/%d nc=%lu (%s)\n",
1059                                    rec->r.ver.trusthashtbl,
1060                                    rec->r.ver.firstfree,
1061                                    rec->r.ver.marginals,
1062                                    rec->r.ver.completes,
1063                                    rec->r.ver.cert_depth,
1064                                    rec->r.ver.nextcheck,
1065                                    strtimestamp(rec->r.ver.nextcheck)
1066                                  );
1067         break;
1068       case RECTYPE_FREE: fprintf(fp, "free, next=%lu\n", rec->r.free.next );
1069         break;
1070       case RECTYPE_HTBL:
1071         fprintf(fp, "htbl,");
1072         for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ )
1073             fprintf(fp, " %lu", rec->r.htbl.item[i] );
1074         putc('\n', fp);
1075         break;
1076       case RECTYPE_HLST:
1077         fprintf(fp, "hlst, next=%lu,", rec->r.hlst.next );
1078         for(i=0; i < ITEMS_PER_HLST_RECORD; i++ )
1079             fprintf(fp, " %lu", rec->r.hlst.rnum[i] );
1080         putc('\n', fp);
1081         break;
1082       case RECTYPE_TRUST:
1083         fprintf(fp, "trust ");
1084         for(i=0; i < 20; i++ )
1085             fprintf(fp, "%02X", rec->r.trust.fingerprint[i] );
1086         fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust,
1087                  rec->r.trust.depth, rec->r.trust.validlist);
1088         break;
1089       case RECTYPE_VALID:
1090         fprintf(fp, "valid ");
1091         for(i=0; i < 20; i++ )
1092             fprintf(fp, "%02X", rec->r.valid.namehash[i] );
1093         fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity,
1094                  rec->r.valid.next);
1095         break;
1096       default:
1097         fprintf(fp, "unknown type %d\n", rec->rectype );
1098         break;
1099     }
1100 }
1101
1102 /****************
1103  * read the record with number recnum
1104  * returns: -1 on error, 0 on success
1105  */
1106 int
1107 tdbio_read_record( ulong recnum, TRUSTREC *rec, int expected )
1108 {
1109     byte readbuf[TRUST_RECORD_LEN];
1110     const byte *buf, *p;
1111     int rc = 0;
1112     int n, i;
1113
1114     if( db_fd == -1 )
1115         open_db();
1116     buf = get_record_from_cache( recnum );
1117     if( !buf ) {
1118         if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
1119             log_error(_("trustdb: lseek failed: %s\n"), strerror(errno) );
1120             return G10ERR_READ_FILE;
1121         }
1122         n = read( db_fd, readbuf, TRUST_RECORD_LEN);
1123         if( !n ) {
1124             return -1; /* eof */
1125         }
1126         else if( n != TRUST_RECORD_LEN ) {
1127             log_error(_("trustdb: read failed (n=%d): %s\n"), n,
1128                                                         strerror(errno) );
1129             return G10ERR_READ_FILE;
1130         }
1131         buf = readbuf;
1132     }
1133     rec->recnum = recnum;
1134     rec->dirty = 0;
1135     p = buf;
1136     rec->rectype = *p++;
1137     if( expected && rec->rectype != expected ) {
1138         log_error("%lu: read expected rec type %d, got %d\n",
1139                     recnum, expected, rec->rectype );
1140         return G10ERR_TRUSTDB;
1141     }
1142     p++;    /* skip reserved byte */
1143     switch( rec->rectype ) {
1144       case 0:  /* unused (free) record */
1145         break;
1146       case RECTYPE_VER: /* version record */
1147         if( memcmp(buf+1, "gpg", 3 ) ) {
1148             log_error( _("%s: not a trustdb file\n"), db_name );
1149             rc = G10ERR_TRUSTDB;
1150         }
1151         p += 2; /* skip "gpg" */
1152         rec->r.ver.version  = *p++;
1153         rec->r.ver.marginals = *p++;
1154         rec->r.ver.completes = *p++;
1155         rec->r.ver.cert_depth = *p++;
1156         p += 4; /* lock flags */
1157         rec->r.ver.created  = buftoulong(p); p += 4;
1158         rec->r.ver.nextcheck = buftoulong(p); p += 4;
1159         p += 4;
1160         p += 4;
1161         rec->r.ver.firstfree =buftoulong(p); p += 4;
1162         p += 4;
1163         rec->r.ver.trusthashtbl =buftoulong(p); p += 4;
1164         if( recnum ) {
1165             log_error( _("%s: version record with recnum %lu\n"), db_name,
1166                                                              (ulong)recnum );
1167             rc = G10ERR_TRUSTDB;
1168         }
1169         else if( rec->r.ver.version != 3 ) {
1170             log_error( _("%s: invalid file version %d\n"), db_name,
1171                                                         rec->r.ver.version );
1172             rc = G10ERR_TRUSTDB;
1173         }
1174         break;
1175       case RECTYPE_FREE:
1176         rec->r.free.next  = buftoulong(p); p += 4;
1177         break;
1178       case RECTYPE_HTBL:
1179         for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
1180             rec->r.htbl.item[i] = buftoulong(p); p += 4;
1181         }
1182         break;
1183       case RECTYPE_HLST:
1184         rec->r.hlst.next = buftoulong(p); p += 4;
1185         for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
1186             rec->r.hlst.rnum[i] = buftoulong(p); p += 4;
1187         }
1188         break;
1189       case RECTYPE_TRUST:
1190         memcpy( rec->r.trust.fingerprint, p, 20); p+=20;
1191         rec->r.trust.ownertrust = *p++;
1192         rec->r.trust.depth = *p++;
1193         p += 2;
1194         rec->r.trust.validlist  = buftoulong(p); p += 4;
1195         break;
1196       case RECTYPE_VALID:
1197         memcpy( rec->r.valid.namehash, p, 20); p+=20;
1198         rec->r.valid.validity = *p++;
1199         rec->r.valid.next = buftoulong(p); p += 4;
1200         break;
1201       default:
1202         log_error( "%s: invalid record type %d at recnum %lu\n",
1203                                    db_name, rec->rectype, (ulong)recnum );
1204         rc = G10ERR_TRUSTDB;
1205         break;
1206     }
1207
1208     return rc;
1209 }
1210
1211 /****************
1212  * Write the record at RECNUM
1213  */
1214 int
1215 tdbio_write_record( TRUSTREC *rec )
1216 {
1217     byte buf[TRUST_RECORD_LEN], *p;
1218     int rc = 0;
1219     int i;
1220     ulong recnum = rec->recnum;
1221
1222     if( db_fd == -1 )
1223         open_db();
1224
1225     memset(buf, 0, TRUST_RECORD_LEN);
1226     p = buf;
1227     *p++ = rec->rectype; p++;
1228     switch( rec->rectype ) {
1229       case 0:  /* unused record */
1230         break;
1231       case RECTYPE_VER: /* version record */
1232         if( recnum )
1233             BUG();
1234         memcpy(p-1, "gpg", 3 ); p += 2;
1235         *p++ = rec->r.ver.version;
1236         *p++ = rec->r.ver.marginals;
1237         *p++ = rec->r.ver.completes;
1238         *p++ = rec->r.ver.cert_depth;
1239         p += 4; /* skip lock flags */
1240         ulongtobuf(p, rec->r.ver.created); p += 4;
1241         ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
1242         p += 4;
1243         p += 4;
1244         ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
1245         p += 4;
1246         ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
1247         break;
1248
1249       case RECTYPE_FREE:
1250         ulongtobuf(p, rec->r.free.next); p += 4;
1251         break;
1252
1253
1254       case RECTYPE_HTBL:
1255         for(i=0; i < ITEMS_PER_HTBL_RECORD; i++ ) {
1256             ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
1257         }
1258         break;
1259
1260       case RECTYPE_HLST:
1261         ulongtobuf( p, rec->r.hlst.next); p += 4;
1262         for(i=0; i < ITEMS_PER_HLST_RECORD; i++ ) {
1263             ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
1264         }
1265         break;
1266
1267       case RECTYPE_TRUST:
1268         memcpy( p, rec->r.trust.fingerprint, 20); p += 20;
1269         *p++ = rec->r.trust.ownertrust;
1270         *p++ = rec->r.trust.depth;
1271         p += 2;
1272         ulongtobuf( p, rec->r.trust.validlist); p += 4;
1273         break;
1274
1275       case RECTYPE_VALID:
1276         memcpy( p, rec->r.valid.namehash, 20); p += 20;
1277         *p++ = rec->r.valid.validity;
1278         ulongtobuf( p, rec->r.valid.next); p += 4;
1279         break;
1280
1281       default:
1282         BUG();
1283     }
1284
1285     rc = put_record_into_cache( recnum, buf );
1286     if( rc )
1287         ;
1288     else if( rec->rectype == RECTYPE_TRUST )
1289         rc = update_trusthashtbl( rec );
1290
1291     return rc;
1292 }
1293
1294 int
1295 tdbio_delete_record( ulong recnum )
1296 {
1297     TRUSTREC vr, rec;
1298     int rc;
1299
1300     /* Must read the record fist, so we can drop it from the hash tables */
1301     rc = tdbio_read_record( recnum, &rec, 0 );
1302     if( rc )
1303         ;
1304     else if( rec.rectype == RECTYPE_TRUST ) {
1305          rc = drop_from_hashtable( get_trusthashrec(),
1306                                    rec.r.trust.fingerprint, 20, rec.recnum );
1307     }
1308
1309     if( rc )
1310         return rc;
1311
1312     /* now we can chnage it to a free record */
1313     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
1314     if( rc )
1315         log_fatal( _("%s: error reading version record: %s\n"),
1316                                        db_name, g10_errstr(rc) );
1317
1318     rec.recnum = recnum;
1319     rec.rectype = RECTYPE_FREE;
1320     rec.r.free.next = vr.r.ver.firstfree;
1321     vr.r.ver.firstfree = recnum;
1322     rc = tdbio_write_record( &rec );
1323     if( !rc )
1324         rc = tdbio_write_record( &vr );
1325     return rc;
1326 }
1327
1328 /****************
1329  * create a new record and return its record number
1330  */
1331 ulong
1332 tdbio_new_recnum()
1333 {
1334     off_t offset;
1335     ulong recnum;
1336     TRUSTREC vr, rec;
1337     int rc;
1338
1339     /* look for unused records */
1340     rc = tdbio_read_record( 0, &vr, RECTYPE_VER );
1341     if( rc )
1342         log_fatal( _("%s: error reading version record: %s\n"),
1343                                              db_name, g10_errstr(rc) );
1344     if( vr.r.ver.firstfree ) {
1345         recnum = vr.r.ver.firstfree;
1346         rc = tdbio_read_record( recnum, &rec, RECTYPE_FREE );
1347         if( rc ) {
1348             log_error( _("%s: error reading free record: %s\n"),
1349                                                   db_name,  g10_errstr(rc) );
1350             return rc;
1351         }
1352         /* update dir record */
1353         vr.r.ver.firstfree = rec.r.free.next;
1354         rc = tdbio_write_record( &vr );
1355         if( rc ) {
1356             log_error( _("%s: error writing dir record: %s\n"),
1357                                                      db_name, g10_errstr(rc) );
1358             return rc;
1359         }
1360         /*zero out the new record */
1361         memset( &rec, 0, sizeof rec );
1362         rec.rectype = 0; /* unused record */
1363         rec.recnum = recnum;
1364         rc = tdbio_write_record( &rec );
1365         if( rc )
1366             log_fatal(_("%s: failed to zero a record: %s\n"),
1367                                        db_name, g10_errstr(rc));
1368     }
1369     else { /* not found, append a new record */
1370         offset = lseek( db_fd, 0, SEEK_END );
1371         if( offset == -1 )
1372             log_fatal("trustdb: lseek to end failed: %s\n", strerror(errno) );
1373         recnum = offset / TRUST_RECORD_LEN;
1374         assert(recnum); /* this is will never be the first record */
1375         /* we must write a record, so that the next call to this function
1376          * returns another recnum */
1377         memset( &rec, 0, sizeof rec );
1378         rec.rectype = 0; /* unused record */
1379         rec.recnum = recnum;
1380         rc = 0;
1381         if( lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET ) == -1 ) {
1382             log_error(_("trustdb rec %lu: lseek failed: %s\n"),
1383                                                 recnum, strerror(errno) );
1384             rc = G10ERR_WRITE_FILE;
1385         }
1386         else {
1387             int n = write( db_fd, &rec, TRUST_RECORD_LEN);
1388             if( n != TRUST_RECORD_LEN ) {
1389                 log_error(_("trustdb rec %lu: write failed (n=%d): %s\n"),
1390                                                  recnum, n, strerror(errno) );
1391                 rc = G10ERR_WRITE_FILE;
1392             }
1393         }
1394
1395         if( rc )
1396             log_fatal(_("%s: failed to append a record: %s\n"),
1397                                     db_name,    g10_errstr(rc));
1398     }
1399     return recnum ;
1400 }
1401
1402
1403
1404 static int
1405 cmp_trec_fpr ( void *fpr, const TRUSTREC *rec )
1406 {
1407     return rec->rectype == RECTYPE_TRUST
1408            && !memcmp( rec->r.trust.fingerprint, fpr, 20);
1409 }
1410
1411
1412 int
1413 tdbio_search_trust_byfpr( const byte *fingerprint, TRUSTREC *rec )
1414 {
1415     int rc;
1416
1417     /* locate the trust record using the hash table */
1418     rc = lookup_hashtable( get_trusthashrec(), fingerprint, 20,
1419                            cmp_trec_fpr, (void*)fingerprint, rec );
1420     return rc;
1421 }
1422
1423 int
1424 tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
1425 {
1426     byte fingerprint[MAX_FINGERPRINT_LEN];
1427     size_t fingerlen;
1428
1429     fingerprint_from_pk( pk, fingerprint, &fingerlen );
1430     for (; fingerlen < 20; fingerlen++ )
1431       fingerprint[fingerlen] = 0;
1432     return tdbio_search_trust_byfpr (fingerprint, rec);
1433 }
1434
1435
1436
1437 void
1438 tdbio_invalid(void)
1439 {
1440     log_error(_(
1441         "the trustdb is corrupted; please run \"gpg --fix-trustdb\".\n") );
1442     g10_exit(2);
1443 }
1444
1445 /*
1446  * Migrate the trustdb as just up to gpg 1.0.6 (trustdb version 2)
1447  * to the 2.1 version as used with 1.0.6b - This is pretty trivial as needs
1448  * only to scan the tdb and insert new the new trust records.  The old ones are
1449  * obsolte from now on
1450  */
1451 static void
1452 migrate_from_v2 ()
1453 {
1454   TRUSTREC rec;
1455   int i, n;
1456   struct {
1457     ulong keyrecno;
1458     byte  ot;
1459     byte okay;
1460     byte  fpr[20];
1461   } *ottable;
1462   int ottable_size, ottable_used;
1463   byte oldbuf[40];
1464   ulong recno;
1465   int rc, count;
1466
1467   ottable_size = 5;
1468   ottable = m_alloc (ottable_size * sizeof *ottable);
1469   ottable_used = 0;
1470
1471   /* We have some restrictions here.  We can't use the version record
1472    * and we can't use any of the old hashtables because we dropped the
1473    * code.  So we first collect all ownertrusts and then use a second
1474    * pass fo find the associated keys.  We have to do this all without using 
1475    * the regular record read functions.
1476    */
1477
1478   /* get all the ownertrusts */
1479   if (lseek (db_fd, 0, SEEK_SET ) == -1 ) 
1480       log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
1481   for (recno=0;;recno++)
1482     {
1483       do
1484         n = read (db_fd, oldbuf, 40);
1485       while (n==-1 && errno == EINTR);
1486       if (!n)
1487         break; /* eof */
1488       if (n != 40)
1489         log_fatal ("migrate_vfrom_v2: read error or short read\n");
1490
1491       if (*oldbuf != 2)
1492         continue;
1493       
1494       /* v2 dir record */
1495       if (ottable_used == ottable_size)
1496         {
1497           ottable_size += 1000;
1498           ottable = m_realloc (ottable, ottable_size * sizeof *ottable);
1499         }
1500       ottable[ottable_used].keyrecno = buftoulong (oldbuf+6);
1501       ottable[ottable_used].ot = oldbuf[18];
1502       ottable[ottable_used].okay = 0;
1503       memset (ottable[ottable_used].fpr,0, 20);
1504       if (ottable[ottable_used].keyrecno && ottable[ottable_used].ot)
1505         ottable_used++;
1506     }
1507   log_info ("found %d ownertrust records\n", ottable_used);
1508
1509   /* Read again and find the fingerprints */
1510   if (lseek (db_fd, 0, SEEK_SET ) == -1 ) 
1511       log_fatal ("migrate_from_v2: lseek failed: %s\n", strerror (errno));
1512   for (recno=0;;recno++)
1513     {
1514       do
1515         n = read (db_fd, oldbuf, 40);
1516       while (n==-1 && errno == EINTR);
1517       if (!n)
1518         break; /* eof */
1519       if (n != 40)
1520         log_fatal ("migrate_from_v2: read error or short read\n");
1521
1522       if (*oldbuf != 3) 
1523         continue;
1524
1525       /* v2 key record */
1526       for (i=0; i < ottable_used; i++)
1527         {
1528           if (ottable[i].keyrecno == recno)
1529             {
1530               memcpy (ottable[i].fpr, oldbuf+20, 20);
1531               ottable[i].okay = 1;
1532               break;
1533             }
1534         }
1535     }
1536
1537   /* got everything - create the v3 trustdb */
1538   if (ftruncate (db_fd, 0))
1539     log_fatal ("can't truncate `%s': %s\n", db_name, strerror (errno) );
1540   if (create_version_record ())
1541     log_fatal ("failed to recreate version record of `%s'\n", db_name);
1542
1543   /* access the hash table, so it is store just after the version record, 
1544    * this is not needed put a dump is more pretty */
1545   get_trusthashrec ();
1546
1547   /* And insert the old ownertrust values */
1548   count = 0;
1549   for (i=0; i < ottable_used; i++)
1550     {
1551       if (!ottable[i].okay)
1552         continue;
1553       
1554       memset (&rec, 0, sizeof rec);
1555       rec.recnum = tdbio_new_recnum ();
1556       rec.rectype = RECTYPE_TRUST;
1557       memcpy(rec.r.trust.fingerprint, ottable[i].fpr, 20);
1558       rec.r.trust.ownertrust = ottable[i].ot;
1559       if (tdbio_write_record (&rec))
1560         log_fatal ("failed to write trust record of `%s'\n", db_name);
1561       count++;
1562     }
1563
1564   revalidation_mark ();
1565   rc = tdbio_sync ();
1566   if (rc)
1567     log_fatal ("failed to sync `%s'\n", db_name);
1568   log_info ("migrated %d version 2 ownertrusts\n", count);
1569   m_free (ottable);
1570 }
1571
1572
1573