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