LCOV - code coverage report
Current view: top level - g10 - tdbio.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 353 766 46.1 %
Date: 2016-09-12 12:29:17 Functions: 26 32 81.2 %

          Line data    Source code
       1             : /* tdbio.c - trust database I/O operations
       2             :  * Copyright (C) 1998-2002, 2012 Free Software Foundation, Inc.
       3             :  * Copyright (C) 1998-2015 Werner Koch
       4             :  *
       5             :  * This file is part of GnuPG.
       6             :  *
       7             :  * GnuPG is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 3 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * GnuPG is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : #include <sys/types.h>
      27             : #include <sys/stat.h>
      28             : #include <fcntl.h>
      29             : #include <unistd.h>
      30             : 
      31             : #include "gpg.h"
      32             : #include "status.h"
      33             : #include "iobuf.h"
      34             : #include "util.h"
      35             : #include "options.h"
      36             : #include "main.h"
      37             : #include "i18n.h"
      38             : #include "trustdb.h"
      39             : #include "tdbio.h"
      40             : 
      41             : #if defined(HAVE_DOSISH_SYSTEM) && !defined(ftruncate)
      42             : #define ftruncate chsize
      43             : #endif
      44             : 
      45             : #if defined(HAVE_DOSISH_SYSTEM) || defined(__CYGWIN__)
      46             : #define MY_O_BINARY  O_BINARY
      47             : #else
      48             : #define MY_O_BINARY  0
      49             : #endif
      50             : 
      51             : /* We use ERRNO despite that the cegcc provided open/read/write
      52             :    functions don't set ERRNO - at least show that ERRNO does not make
      53             :    sense.  */
      54             : #ifdef HAVE_W32CE_SYSTEM
      55             : #undef strerror
      56             : #define strerror(a) ("[errno not available]")
      57             : #endif
      58             : 
      59             : /*
      60             :  * Yes, this is a very simple implementation. We should really
      61             :  * use a page aligned buffer and read complete pages.
      62             :  * To implement a simple trannsaction system, this is sufficient.
      63             :  */
      64             : typedef struct cache_ctrl_struct *CACHE_CTRL;
      65             : struct cache_ctrl_struct
      66             : {
      67             :   CACHE_CTRL next;
      68             :   struct {
      69             :     unsigned used:1;
      70             :     unsigned dirty:1;
      71             :   } flags;
      72             :   ulong recno;
      73             :   char data[TRUST_RECORD_LEN];
      74             : };
      75             : 
      76             : /* Size of the cache.  The SOFT value is the general one.  While in a
      77             :    transaction this may not be sufficient and thus we may increase it
      78             :    then up to the HARD limit.  */
      79             : #define MAX_CACHE_ENTRIES_SOFT  200
      80             : #define MAX_CACHE_ENTRIES_HARD  10000
      81             : 
      82             : 
      83             : /* The cache is controlled by these variables.  */
      84             : static CACHE_CTRL cache_list;
      85             : static int cache_entries;
      86             : static int cache_is_dirty;
      87             : 
      88             : 
      89             : /* An object to pass information to cmp_krec_fpr. */
      90             : struct cmp_krec_fpr_struct
      91             : {
      92             :   int pubkey_algo;
      93             :   const char *fpr;
      94             :   int fprlen;
      95             : };
      96             : 
      97             : /* An object used to pass information to cmp_[s]dir. */
      98             : struct cmp_xdir_struct
      99             : {
     100             :   int pubkey_algo;
     101             :   u32 keyid[2];
     102             : };
     103             : 
     104             : 
     105             : /* The name of the trustdb file.  */
     106             : static char *db_name;
     107             : 
     108             : /* The handle for locking the trustdb file and a flag to record
     109             :    whether a lock has been taken.  */
     110             : static dotlock_t lockhandle;
     111             : static int is_locked;
     112             : 
     113             : /* The file descriptor of the trustdb.  */
     114             : static int  db_fd = -1;
     115             : 
     116             : /* A flag indicating that a transaction is active.  */
     117             : static int in_transaction;
     118             : 
     119             : 
     120             : 
     121             : static void open_db (void);
     122             : static void create_hashtable (TRUSTREC *vr, int type);
     123             : 
     124             : 
     125             : 
     126             : /*
     127             :  * Take a lock on the trustdb file name.  I a lock file can't be
     128             :  * created the function terminates the process.  Excvept for a
     129             :  * different return code the function does nothing if the lock has
     130             :  * already been taken.
     131             :  *
     132             :  * Returns: True if lock already exists, False if the lock has
     133             :  *          actually been taken.
     134             :  */
     135             : static int
     136          25 : take_write_lock (void)
     137             : {
     138          25 :   if (!lockhandle)
     139           9 :     lockhandle = dotlock_create (db_name, 0);
     140          25 :   if (!lockhandle)
     141           0 :     log_fatal ( _("can't create lock for '%s'\n"), db_name );
     142             : 
     143          25 :   if (!is_locked)
     144             :     {
     145          11 :       if (dotlock_take (lockhandle, -1) )
     146           0 :         log_fatal ( _("can't lock '%s'\n"), db_name );
     147             :       else
     148          11 :         is_locked = 1;
     149          11 :       return 0;
     150             :     }
     151             :   else
     152          14 :     return 1;
     153             : }
     154             : 
     155             : 
     156             : /*
     157             :  * Release a lock from the trustdb file unless the global option
     158             :  * --lock-once has been used.
     159             :  */
     160             : static void
     161          11 : release_write_lock (void)
     162             : {
     163          11 :   if (!opt.lock_once)
     164          11 :     if (!dotlock_release (lockhandle))
     165          11 :       is_locked = 0;
     166          11 : }
     167             : 
     168             : /*************************************
     169             :  ************* record cache **********
     170             :  *************************************/
     171             : 
     172             : /*
     173             :  * Get the data from the record cache and return a pointer into that
     174             :  * cache.  Caller should copy the returned data.  NULL is returned on
     175             :  * a cache miss.
     176             :  */
     177             : static const char *
     178        3332 : get_record_from_cache (ulong recno)
     179             : {
     180             :   CACHE_CTRL r;
     181             : 
     182        7559 :   for (r = cache_list; r; r = r->next)
     183             :     {
     184        4482 :       if (r->flags.used && r->recno == recno)
     185         255 :         return r->data;
     186             :     }
     187        3077 :   return NULL;
     188             : }
     189             : 
     190             : 
     191             : /*
     192             :  * Write a cached item back to the trustdb file.
     193             :  *
     194             :  * Returns: 0 on success or an error code.
     195             :  */
     196             : static int
     197         224 : write_cache_item (CACHE_CTRL r)
     198             : {
     199             :   gpg_error_t err;
     200             :   int n;
     201             : 
     202         224 :   if (lseek (db_fd, r->recno * TRUST_RECORD_LEN, SEEK_SET) == -1)
     203             :     {
     204           0 :       err = gpg_error_from_syserror ();
     205           0 :       log_error (_("trustdb rec %lu: lseek failed: %s\n"),
     206           0 :                  r->recno, strerror (errno));
     207           0 :       return err;
     208             :     }
     209         224 :   n = write (db_fd, r->data, TRUST_RECORD_LEN);
     210         224 :   if (n != TRUST_RECORD_LEN)
     211             :     {
     212           0 :       err = gpg_error_from_syserror ();
     213           0 :       log_error (_("trustdb rec %lu: write failed (n=%d): %s\n"),
     214           0 :                  r->recno, n, strerror (errno) );
     215           0 :       return err;
     216             :     }
     217         224 :   r->flags.dirty = 0;
     218         224 :   return 0;
     219             : }
     220             : 
     221             : 
     222             : /*
     223             :  * Put data into the cache.  This function may flush
     224             :  * some cache entries if the cache is filled up.
     225             :  *
     226             :  * Returns: 0 on success or an error code.
     227             :  */
     228             : static int
     229         224 : put_record_into_cache (ulong recno, const char *data)
     230             : {
     231             :   CACHE_CTRL r, unused;
     232         224 :   int dirty_count = 0;
     233         224 :   int clean_count = 0;
     234             : 
     235             :   /* See whether we already cached this one.  */
     236        3585 :   for (unused = NULL, r = cache_list; r; r = r->next)
     237             :     {
     238        3371 :       if (!r->flags.used)
     239             :         {
     240           0 :           if (!unused)
     241           0 :             unused = r;
     242             :         }
     243        3371 :       else if (r->recno == recno)
     244             :         {
     245          10 :           if (!r->flags.dirty)
     246             :             {
     247             :               /* Hmmm: should we use a copy and compare? */
     248          10 :               if (memcmp (r->data, data, TRUST_RECORD_LEN))
     249             :                 {
     250          10 :                   r->flags.dirty = 1;
     251          10 :                   cache_is_dirty = 1;
     252             :                 }
     253             :             }
     254          10 :           memcpy (r->data, data, TRUST_RECORD_LEN);
     255          10 :           return 0;
     256             :         }
     257        3361 :       if (r->flags.used)
     258             :         {
     259        3361 :           if (r->flags.dirty)
     260        3049 :             dirty_count++;
     261             :           else
     262         312 :             clean_count++;
     263             :         }
     264             :     }
     265             : 
     266             :   /* Not in the cache: add a new entry. */
     267         214 :   if (unused)
     268             :     {
     269             :       /* Reuse this entry. */
     270           0 :       r = unused;
     271           0 :       r->flags.used = 1;
     272           0 :       r->recno = recno;
     273           0 :       memcpy (r->data, data, TRUST_RECORD_LEN);
     274           0 :       r->flags.dirty = 1;
     275           0 :       cache_is_dirty = 1;
     276           0 :       cache_entries++;
     277           0 :       return 0;
     278             :     }
     279             : 
     280             :   /* See whether we reached the limit. */
     281         214 :   if (cache_entries < MAX_CACHE_ENTRIES_SOFT)
     282             :     {
     283             :       /* No: Put into cache.  */
     284         214 :       r = xmalloc (sizeof *r);
     285         214 :       r->flags.used = 1;
     286         214 :       r->recno = recno;
     287         214 :       memcpy (r->data, data, TRUST_RECORD_LEN);
     288         214 :       r->flags.dirty = 1;
     289         214 :       r->next = cache_list;
     290         214 :       cache_list = r;
     291         214 :       cache_is_dirty = 1;
     292         214 :       cache_entries++;
     293         214 :       return 0;
     294             :     }
     295             : 
     296             :   /* Cache is full: discard some clean entries.  */
     297           0 :   if (clean_count)
     298             :     {
     299             :       int n;
     300             : 
     301             :       /* We discard a third of the clean entries.  */
     302           0 :       n = clean_count / 3;
     303           0 :       if (!n)
     304           0 :         n = 1;
     305             : 
     306           0 :       for (unused = NULL, r = cache_list; r; r = r->next)
     307             :         {
     308           0 :           if (r->flags.used && !r->flags.dirty)
     309             :             {
     310           0 :               if (!unused)
     311           0 :                 unused = r;
     312           0 :               r->flags.used = 0;
     313           0 :               cache_entries--;
     314           0 :               if (!--n)
     315           0 :                 break;
     316             :             }
     317             :         }
     318             : 
     319             :       /* Now put into the cache.  */
     320           0 :       log_assert (unused);
     321           0 :       r = unused;
     322           0 :       r->flags.used = 1;
     323           0 :       r->recno = recno;
     324           0 :       memcpy (r->data, data, TRUST_RECORD_LEN);
     325           0 :       r->flags.dirty = 1;
     326           0 :       cache_is_dirty = 1;
     327           0 :       cache_entries++;
     328           0 :       return 0;
     329             :     }
     330             : 
     331             :   /* No clean entries: We have to flush some dirty entries.  */
     332           0 :   if (in_transaction)
     333             :     {
     334             :       /* But we can't do this while in a transaction.  Thus we
     335             :        * increase the cache size instead.  */
     336           0 :       if (cache_entries < MAX_CACHE_ENTRIES_HARD)
     337             :         {
     338           0 :           if (opt.debug && !(cache_entries % 100))
     339           0 :             log_debug ("increasing tdbio cache size\n");
     340           0 :           r = xmalloc (sizeof *r);
     341           0 :           r->flags.used = 1;
     342           0 :           r->recno = recno;
     343           0 :           memcpy (r->data, data, TRUST_RECORD_LEN);
     344           0 :           r->flags.dirty = 1;
     345           0 :           r->next = cache_list;
     346           0 :           cache_list = r;
     347           0 :           cache_is_dirty = 1;
     348           0 :           cache_entries++;
     349           0 :           return 0;
     350             :         }
     351             :       /* Hard limit for the cache size reached.  */
     352           0 :       log_info (_("trustdb transaction too large\n"));
     353           0 :       return GPG_ERR_RESOURCE_LIMIT;
     354             :     }
     355             : 
     356           0 :   if (dirty_count)
     357             :     {
     358             :       int n;
     359             : 
     360             :       /* Discard some dirty entries. */
     361           0 :       n = dirty_count / 5;
     362           0 :       if (!n)
     363           0 :         n = 1;
     364             : 
     365           0 :       take_write_lock ();
     366           0 :       for (unused = NULL, r = cache_list; r; r = r->next)
     367             :         {
     368           0 :           if (r->flags.used && r->flags.dirty)
     369             :             {
     370             :               int rc;
     371             : 
     372           0 :               rc = write_cache_item (r);
     373           0 :               if (rc)
     374           0 :                 return rc;
     375           0 :               if (!unused)
     376           0 :                 unused = r;
     377           0 :               r->flags.used = 0;
     378           0 :               cache_entries--;
     379           0 :               if (!--n)
     380           0 :                 break;
     381             :             }
     382             :         }
     383           0 :       release_write_lock ();
     384             : 
     385             :       /* Now put into the cache.  */
     386           0 :       log_assert (unused);
     387           0 :       r = unused;
     388           0 :       r->flags.used = 1;
     389           0 :       r->recno = recno;
     390           0 :       memcpy (r->data, data, TRUST_RECORD_LEN);
     391           0 :       r->flags.dirty = 1;
     392           0 :       cache_is_dirty = 1;
     393           0 :       cache_entries++;
     394           0 :       return 0;
     395             :     }
     396             : 
     397             :   /* We should never reach this.  */
     398           0 :   BUG();
     399             : }
     400             : 
     401             : 
     402             : /* Return true if the cache is dirty.  */
     403             : int
     404           0 : tdbio_is_dirty()
     405             : {
     406           0 :   return cache_is_dirty;
     407             : }
     408             : 
     409             : 
     410             : /*
     411             :  * Flush the cache.  This cannot be used while in a transaction.
     412             :  */
     413             : int
     414          19 : tdbio_sync()
     415             : {
     416             :     CACHE_CTRL r;
     417          19 :     int did_lock = 0;
     418             : 
     419          19 :     if( db_fd == -1 )
     420           0 :         open_db();
     421          19 :     if( in_transaction )
     422           0 :         log_bug("tdbio: syncing while in transaction\n");
     423             : 
     424          19 :     if( !cache_is_dirty )
     425           1 :         return 0;
     426             : 
     427          18 :     if (!take_write_lock ())
     428           4 :         did_lock = 1;
     429             : 
     430         299 :     for( r = cache_list; r; r = r->next ) {
     431         281 :         if( r->flags.used && r->flags.dirty ) {
     432         224 :             int rc = write_cache_item( r );
     433         224 :             if( rc )
     434           0 :                 return rc;
     435             :         }
     436             :     }
     437          18 :     cache_is_dirty = 0;
     438          18 :     if (did_lock)
     439           4 :         release_write_lock ();
     440             : 
     441          18 :     return 0;
     442             : }
     443             : 
     444             : 
     445             : #if 0  /* Not yet used.  */
     446             : /*
     447             :  * Simple transactions system:
     448             :  * Everything between begin_transaction and end/cancel_transaction
     449             :  * is not immediately written but at the time of end_transaction.
     450             :  *
     451             :  * NOTE: The transaction code is disabled in the 1.2 branch, as it is
     452             :  * not yet used.
     453             :  */
     454             : int
     455             : tdbio_begin_transaction ()  /* Not yet used.  */
     456             : {
     457             :   int rc;
     458             : 
     459             :   if (in_transaction)
     460             :     log_bug ("tdbio: nested transactions\n");
     461             :   /* Flush everything out. */
     462             :   rc = tdbio_sync();
     463             :   if (rc)
     464             :     return rc;
     465             :   in_transaction = 1;
     466             :   return 0;
     467             : }
     468             : 
     469             : int
     470             : tdbio_end_transaction ()  /* Not yet used.  */
     471             : {
     472             :   int rc;
     473             : 
     474             :   if (!in_transaction)
     475             :     log_bug ("tdbio: no active transaction\n");
     476             :   take_write_lock ();
     477             :   gnupg_block_all_signals ();
     478             :   in_transaction = 0;
     479             :   rc = tdbio_sync();
     480             :   gnupg_unblock_all_signals();
     481             :   release_write_lock ();
     482             :   return rc;
     483             : }
     484             : 
     485             : int
     486             : tdbio_cancel_transaction () /* Not yet used.  */
     487             : {
     488             :   CACHE_CTRL r;
     489             : 
     490             :   if (!in_transaction)
     491             :     log_bug ("tdbio: no active transaction\n");
     492             : 
     493             :   /* Remove all dirty marked entries, so that the original ones are
     494             :    * read back the next time.  */
     495             :   if (cache_is_dirty)
     496             :     {
     497             :       for (r = cache_list; r; r = r->next)
     498             :         {
     499             :           if (r->flags.used && r->flags.dirty)
     500             :             {
     501             :               r->flags.used = 0;
     502             :               cache_entries--;
     503             :             }
     504             :         }
     505             :       cache_is_dirty = 0;
     506             :     }
     507             : 
     508             :   in_transaction = 0;
     509             :   return 0;
     510             : }
     511             : #endif  /* Not yet used.  */
     512             : 
     513             : 
     514             : 
     515             : /********************************************************
     516             :  **************** cached I/O functions ******************
     517             :  ********************************************************/
     518             : 
     519             : /* The cleanup handler for this module.  */
     520             : static void
     521         561 : cleanup (void)
     522             : {
     523         561 :   if (is_locked)
     524             :     {
     525           0 :       if (!dotlock_release (lockhandle))
     526           0 :         is_locked = 0;
     527             :     }
     528         561 : }
     529             : 
     530             : 
     531             : /*
     532             :  * Update an existing trustdb record.  The caller must call
     533             :  * tdbio_sync.
     534             :  *
     535             :  * Returns: 0 on success or an error code.
     536             :  */
     537             : int
     538           1 : tdbio_update_version_record (void)
     539             : {
     540             :   TRUSTREC rec;
     541             :   int rc;
     542             : 
     543           1 :   memset (&rec, 0, sizeof rec);
     544             : 
     545           1 :   rc = tdbio_read_record (0, &rec, RECTYPE_VER);
     546           1 :   if (!rc)
     547             :     {
     548           1 :       rec.r.ver.created     = make_timestamp();
     549           1 :       rec.r.ver.marginals   = opt.marginals_needed;
     550           1 :       rec.r.ver.completes   = opt.completes_needed;
     551           1 :       rec.r.ver.cert_depth  = opt.max_cert_depth;
     552           1 :       rec.r.ver.trust_model = opt.trust_model;
     553           1 :       rec.r.ver.min_cert_level = opt.min_cert_level;
     554           1 :       rc=tdbio_write_record(&rec);
     555             :     }
     556             : 
     557           1 :   return rc;
     558             : }
     559             : 
     560             : 
     561             : /*
     562             :  * Create and write the trustdb version record.
     563             :  *
     564             :  * Returns: 0 on success or an error code.
     565             :  */
     566             : static int
     567           7 : create_version_record (void)
     568             : {
     569             :   TRUSTREC rec;
     570             :   int rc;
     571             : 
     572           7 :   memset (&rec, 0, sizeof rec);
     573           7 :   rec.r.ver.version     = 3;
     574           7 :   rec.r.ver.created     = make_timestamp ();
     575           7 :   rec.r.ver.marginals   = opt.marginals_needed;
     576           7 :   rec.r.ver.completes   = opt.completes_needed;
     577           7 :   rec.r.ver.cert_depth  = opt.max_cert_depth;
     578           7 :   if (opt.trust_model == TM_PGP || opt.trust_model == TM_CLASSIC)
     579           0 :     rec.r.ver.trust_model = opt.trust_model;
     580             :   else
     581           7 :     rec.r.ver.trust_model = TM_PGP;
     582           7 :   rec.r.ver.min_cert_level = opt.min_cert_level;
     583           7 :   rec.rectype = RECTYPE_VER;
     584           7 :   rec.recnum = 0;
     585           7 :   rc = tdbio_write_record (&rec);
     586             : 
     587           7 :   if (!rc)
     588           7 :     tdbio_sync ();
     589             : 
     590           7 :   if (!rc)
     591           7 :     create_hashtable (&rec, 0);
     592             : 
     593           7 :   return rc;
     594             : }
     595             : 
     596             : 
     597             : /*
     598             :  * Set the file name for the trustdb to NEW_DBNAME and if CREATE is
     599             :  * true create that file.  If NEW_DBNAME is NULL a default name is
     600             :  * used, if the it does not contain a path component separator ('/')
     601             :  * the global GnuPG home directory is used.
     602             :  *
     603             :  * Returns: 0 on success or an error code.
     604             :  *
     605             :  * On the first call this function registers an atexit handler.
     606             :  *
     607             :  */
     608             : int
     609         561 : tdbio_set_dbname (const char *new_dbname, int create, int *r_nofile)
     610             : {
     611             :   char *fname, *p;
     612             :   struct stat statbuf;
     613             :   static int initialized = 0;
     614             :   int save_slash;
     615             : 
     616         561 :   if (!initialized)
     617             :     {
     618         561 :       atexit (cleanup);
     619         561 :       initialized = 1;
     620             :     }
     621             : 
     622         561 :   *r_nofile = 0;
     623             : 
     624         561 :   if (!new_dbname)
     625             :     {
     626         561 :       fname = make_filename (gnupg_homedir (),
     627             :                              "trustdb" EXTSEP_S GPGEXT_GPG, NULL);
     628             :     }
     629           0 :   else if (*new_dbname != DIRSEP_C )
     630             :     {
     631           0 :       if (strchr (new_dbname, DIRSEP_C))
     632           0 :         fname = make_filename (new_dbname, NULL);
     633             :       else
     634           0 :         fname = make_filename (gnupg_homedir (), new_dbname, NULL);
     635             :     }
     636             :   else
     637             :     {
     638           0 :       fname = xstrdup (new_dbname);
     639             :     }
     640             : 
     641         561 :   xfree (db_name);
     642         561 :   db_name = fname;
     643             : 
     644             :   /* Quick check for (likely) case where there already is a
     645             :    * trustdb.gpg.  This check is not required in theory, but it helps
     646             :    * in practice avoiding costly operations of preparing and taking
     647             :    * the lock.  */
     648         561 :   if (!stat (fname, &statbuf) && statbuf.st_size > 0)
     649             :     {
     650             :       /* OK, we have the valid trustdb.gpg already.  */
     651         148 :       return 0;
     652             :     }
     653         413 :   else if (!create)
     654             :     {
     655         406 :       *r_nofile = 1;
     656         406 :       return 0;
     657             :     }
     658             : 
     659             :   /* Here comes: No valid trustdb.gpg AND CREATE==1 */
     660             : 
     661             :   /*
     662             :    * Make sure the directory exists.  This should be done before
     663             :    * acquiring the lock, which assumes the existence of the directory.
     664             :    */
     665           7 :   p = strrchr (fname, DIRSEP_C);
     666             : #if HAVE_W32_SYSTEM
     667             :   {
     668             :     /* Windows may either have a slash or a backslash.  Take
     669             :        care of it.  */
     670             :     char *pp = strrchr (fname, '/');
     671             :     if (!p || pp > p)
     672             :       p = pp;
     673             :   }
     674             : #endif /*HAVE_W32_SYSTEM*/
     675           7 :   log_assert (p);
     676           7 :   save_slash = *p;
     677           7 :   *p = 0;
     678           7 :   if (access (fname, F_OK))
     679             :     {
     680           0 :       try_make_homedir (fname);
     681           0 :       if (access (fname, F_OK))
     682           0 :         log_fatal (_("%s: directory does not exist!\n"), fname);
     683             :     }
     684           7 :   *p = save_slash;
     685             : 
     686           7 :   take_write_lock ();
     687             : 
     688           7 :   if (access (fname, R_OK) || stat (fname, &statbuf) || statbuf.st_size == 0)
     689             :     {
     690             :       FILE *fp;
     691             :       TRUSTREC rec;
     692             :       int rc;
     693             :       mode_t oldmask;
     694             : 
     695             : #ifdef HAVE_W32CE_SYSTEM
     696             :       /* We know how the cegcc implementation of access works ;-). */
     697             :       if (GetLastError () == ERROR_FILE_NOT_FOUND)
     698             :         gpg_err_set_errno (ENOENT);
     699             :       else
     700             :         gpg_err_set_errno (EIO);
     701             : #endif /*HAVE_W32CE_SYSTEM*/
     702           7 :       if (errno && errno != ENOENT)
     703           0 :         log_fatal ( _("can't access '%s': %s\n"), fname, strerror (errno));
     704             : 
     705           7 :       oldmask = umask (077);
     706           7 :       if (is_secured_filename (fname))
     707             :         {
     708           0 :           fp = NULL;
     709           0 :           gpg_err_set_errno (EPERM);
     710             :         }
     711             :       else
     712           7 :         fp = fopen (fname, "wb");
     713           7 :       umask(oldmask);
     714           7 :       if (!fp)
     715           0 :         log_fatal (_("can't create '%s': %s\n"), fname, strerror (errno));
     716           7 :       fclose (fp);
     717             : 
     718           7 :       db_fd = open (db_name, O_RDWR | MY_O_BINARY);
     719           7 :       if (db_fd == -1)
     720           0 :         log_fatal (_("can't open '%s': %s\n"), db_name, strerror (errno));
     721             : 
     722           7 :       rc = create_version_record ();
     723           7 :       if (rc)
     724           0 :         log_fatal (_("%s: failed to create version record: %s"),
     725             :                    fname, gpg_strerror (rc));
     726             : 
     727             :       /* Read again to check that we are okay. */
     728           7 :       if (tdbio_read_record (0, &rec, RECTYPE_VER))
     729           0 :         log_fatal (_("%s: invalid trustdb created\n"), db_name);
     730             : 
     731           7 :       if (!opt.quiet)
     732           6 :         log_info (_("%s: trustdb created\n"), db_name);
     733             :     }
     734             : 
     735           7 :   release_write_lock ();
     736           7 :   return 0;
     737             : }
     738             : 
     739             : 
     740             : /*
     741             :  * Return the full name of the trustdb.
     742             :  */
     743             : const char *
     744           0 : tdbio_get_dbname ()
     745             : {
     746           0 :   return db_name;
     747             : }
     748             : 
     749             : 
     750             : /*
     751             :  * Open the trustdb.  This may only be called if it has not yet been
     752             :  * opened and after a successful call to tdbio_set_dbname.  On return
     753             :  * the trustdb handle (DB_FD) is guaranteed to be open.
     754             :  */
     755             : static void
     756          93 : open_db ()
     757             : {
     758             :   TRUSTREC rec;
     759             : 
     760          93 :   log_assert( db_fd == -1 );
     761             : 
     762             : #ifdef HAVE_W32CE_SYSTEM
     763             :   {
     764             :     DWORD prevrc = 0;
     765             :     wchar_t *wname = utf8_to_wchar (db_name);
     766             :     if (wname)
     767             :       {
     768             :         db_fd = (int)CreateFile (wname, GENERIC_READ|GENERIC_WRITE,
     769             :                                  FILE_SHARE_READ|FILE_SHARE_WRITE, NULL,
     770             :                                  OPEN_EXISTING, 0, NULL);
     771             :         xfree (wname);
     772             :       }
     773             :     if (db_fd == -1)
     774             :       log_fatal ("can't open '%s': %d, %d\n", db_name,
     775             :                  (int)prevrc, (int)GetLastError ());
     776             :   }
     777             : #else /*!HAVE_W32CE_SYSTEM*/
     778          93 :   db_fd = open (db_name, O_RDWR | MY_O_BINARY );
     779          93 :   if (db_fd == -1 && (errno == EACCES
     780             : #ifdef EROFS
     781           0 :                       || errno == EROFS
     782             : #endif
     783             :                       )
     784             :       ) {
     785             :       /* Take care of read-only trustdbs.  */
     786           0 :       db_fd = open (db_name, O_RDONLY | MY_O_BINARY );
     787           0 :       if (db_fd != -1 && !opt.quiet)
     788           0 :           log_info (_("Note: trustdb not writable\n"));
     789             :   }
     790          93 :   if ( db_fd == -1 )
     791           0 :     log_fatal( _("can't open '%s': %s\n"), db_name, strerror(errno) );
     792             : #endif /*!HAVE_W32CE_SYSTEM*/
     793          93 :   register_secured_file (db_name);
     794             : 
     795             :   /* Read the version record. */
     796          93 :   if (tdbio_read_record (0, &rec, RECTYPE_VER ) )
     797           0 :     log_fatal( _("%s: invalid trustdb\n"), db_name );
     798          93 : }
     799             : 
     800             : 
     801             : /*
     802             :  * Append a new empty hashtable to the trustdb.  TYPE gives the type
     803             :  * of the hash table.  The only defined type is 0 for a trust hash.
     804             :  * On return the hashtable has been created, written, the version
     805             :  * record update, and the data flushed to the disk.  On a fatal error
     806             :  * the function terminates the process.
     807             :  */
     808             : static void
     809           7 : create_hashtable( TRUSTREC *vr, int type )
     810             : {
     811             :   TRUSTREC rec;
     812             :   off_t offset;
     813             :   ulong recnum;
     814             :   int i, n, rc;
     815             : 
     816           7 :   offset = lseek (db_fd, 0, SEEK_END);
     817           7 :   if (offset == -1)
     818           0 :     log_fatal ("trustdb: lseek to end failed: %s\n", strerror(errno));
     819           7 :   recnum = offset / TRUST_RECORD_LEN;
     820           7 :   log_assert (recnum); /* This is will never be the first record. */
     821             : 
     822           7 :   if (!type)
     823           7 :     vr->r.ver.trusthashtbl = recnum;
     824             : 
     825             :   /* Now write the records making up the hash table. */
     826           7 :   n = (256+ITEMS_PER_HTBL_RECORD-1) / ITEMS_PER_HTBL_RECORD;
     827         210 :   for (i=0; i < n; i++, recnum++)
     828             :     {
     829         203 :       memset (&rec, 0, sizeof rec);
     830         203 :       rec.rectype = RECTYPE_HTBL;
     831         203 :       rec.recnum = recnum;
     832         203 :       rc = tdbio_write_record (&rec);
     833         203 :       if (rc)
     834           0 :         log_fatal (_("%s: failed to create hashtable: %s\n"),
     835             :                    db_name, gpg_strerror (rc));
     836             :     }
     837             :   /* Update the version record and flush. */
     838           7 :   rc = tdbio_write_record (vr);
     839           7 :   if (!rc)
     840           7 :     rc = tdbio_sync ();
     841           7 :   if (rc)
     842           0 :     log_fatal (_("%s: error updating version record: %s\n"),
     843             :                db_name, gpg_strerror (rc));
     844           7 : }
     845             : 
     846             : 
     847             : /*
     848             :  * Check whether open trustdb matches the global trust options given
     849             :  * for this process.  On a read problem the process is terminated.
     850             :  *
     851             :  * Return: 1 for yes, 0 for no.
     852             :  */
     853             : int
     854          88 : tdbio_db_matches_options()
     855             : {
     856             :   static int yes_no = -1;
     857             : 
     858          88 :   if (yes_no == -1)
     859             :     {
     860             :       TRUSTREC vr;
     861             :       int rc;
     862             : 
     863          88 :       rc = tdbio_read_record (0, &vr, RECTYPE_VER);
     864          88 :       if( rc )
     865           0 :         log_fatal( _("%s: error reading version record: %s\n"),
     866             :                    db_name, gpg_strerror (rc) );
     867             : 
     868         176 :       yes_no = vr.r.ver.marginals == opt.marginals_needed
     869          88 :         && vr.r.ver.completes == opt.completes_needed
     870          88 :         && vr.r.ver.cert_depth == opt.max_cert_depth
     871          88 :         && vr.r.ver.trust_model == opt.trust_model
     872         132 :         && vr.r.ver.min_cert_level == opt.min_cert_level;
     873             :     }
     874             : 
     875          88 :   return yes_no;
     876             : }
     877             : 
     878             : 
     879             : /*
     880             :  * Read and return the trust model identifier from the trustdb.  On a
     881             :  * read problem the process is terminated.
     882             :  */
     883             : byte
     884          44 : tdbio_read_model (void)
     885             : {
     886             :   TRUSTREC vr;
     887             :   int rc;
     888             : 
     889          44 :   rc = tdbio_read_record (0, &vr, RECTYPE_VER );
     890          44 :   if (rc)
     891           0 :     log_fatal (_("%s: error reading version record: %s\n"),
     892             :                db_name, gpg_strerror (rc) );
     893          44 :   return vr.r.ver.trust_model;
     894             : }
     895             : 
     896             : 
     897             : /*
     898             :  * Read and return the nextstamp value from the trustdb.  On a read
     899             :  * problem the process is terminated.
     900             :  */
     901             : ulong
     902          68 : tdbio_read_nextcheck ()
     903             : {
     904             :   TRUSTREC vr;
     905             :   int rc;
     906             : 
     907          68 :   rc = tdbio_read_record (0, &vr, RECTYPE_VER);
     908          68 :   if (rc)
     909           0 :     log_fatal (_("%s: error reading version record: %s\n"),
     910             :                db_name, gpg_strerror (rc));
     911          68 :   return vr.r.ver.nextcheck;
     912             : }
     913             : 
     914             : 
     915             : /*
     916             :  * Write the STAMP nextstamp timestamp to the trustdb.  On a read or
     917             :  * write problem the process is terminated.
     918             :  *
     919             :  * Return: True if the stamp actually changed.
     920             :  */
     921             : int
     922           5 : tdbio_write_nextcheck (ulong stamp)
     923             : {
     924             :   TRUSTREC vr;
     925             :   int rc;
     926             : 
     927           5 :   rc = tdbio_read_record (0, &vr, RECTYPE_VER);
     928           5 :   if (rc)
     929           0 :     log_fatal (_("%s: error reading version record: %s\n"),
     930             :                db_name, gpg_strerror (rc));
     931             : 
     932           5 :   if (vr.r.ver.nextcheck == stamp)
     933           3 :     return 0;
     934             : 
     935           2 :   vr.r.ver.nextcheck = stamp;
     936           2 :   rc = tdbio_write_record( &vr );
     937           2 :   if (rc)
     938           0 :     log_fatal (_("%s: error writing version record: %s\n"),
     939             :                db_name, gpg_strerror (rc));
     940           2 :   return 1;
     941             : }
     942             : 
     943             : 
     944             : 
     945             : /*
     946             :  * Return the record number of the trusthash table or create one if it
     947             :  * does not yet exist.  On a read or write problem the process is
     948             :  * terminated.
     949             :  *
     950             :  * Return: record number
     951             :  */
     952             : static ulong
     953         210 : get_trusthashrec(void)
     954             : {
     955             :   static ulong trusthashtbl; /* Record number of the trust hashtable.  */
     956             : 
     957         210 :   if (!trusthashtbl)
     958             :     {
     959             :       TRUSTREC vr;
     960             :       int rc;
     961             : 
     962          96 :       rc = tdbio_read_record (0, &vr, RECTYPE_VER );
     963          96 :       if (rc)
     964           0 :         log_fatal (_("%s: error reading version record: %s\n"),
     965             :                    db_name, gpg_strerror (rc) );
     966             : 
     967          96 :       trusthashtbl = vr.r.ver.trusthashtbl;
     968             :     }
     969             : 
     970         210 :   return trusthashtbl;
     971             : }
     972             : 
     973             : 
     974             : 
     975             : /*
     976             :  * Update a hashtable in the trustdb.  TABLE gives the start of the
     977             :  * table, KEY and KEYLEN are the key, NEWRECNUM is the record number
     978             :  * to insert into the table.
     979             :  *
     980             :  * Return: 0 on success or an error code.
     981             :  */
     982             : static int
     983           2 : upd_hashtable (ulong table, byte *key, int keylen, ulong newrecnum)
     984             : {
     985             :   TRUSTREC lastrec, rec;
     986             :   ulong hashrec, item;
     987             :   int msb;
     988           2 :   int level = 0;
     989             :   int rc, i;
     990             : 
     991           2 :   hashrec = table;
     992             :  next_level:
     993           2 :   msb = key[level];
     994           2 :   hashrec += msb / ITEMS_PER_HTBL_RECORD;
     995           2 :   rc = tdbio_read_record (hashrec, &rec, RECTYPE_HTBL);
     996           2 :   if (rc)
     997             :     {
     998           0 :       log_error ("upd_hashtable: read failed: %s\n", gpg_strerror (rc));
     999           0 :       return rc;
    1000             :     }
    1001             : 
    1002           2 :   item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
    1003           2 :   if (!item)  /* Insert a new item into the hash table.  */
    1004             :     {
    1005           2 :       rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = newrecnum;
    1006           2 :       rc = tdbio_write_record (&rec);
    1007           2 :       if (rc)
    1008             :         {
    1009           0 :           log_error ("upd_hashtable: write htbl failed: %s\n",
    1010             :                      gpg_strerror (rc));
    1011           0 :           return rc;
    1012             :         }
    1013             :     }
    1014           0 :   else if (item != newrecnum) /* Must do an update.  */
    1015             :     {
    1016           0 :       lastrec = rec;
    1017           0 :       rc = tdbio_read_record (item, &rec, 0);
    1018           0 :       if (rc)
    1019             :         {
    1020           0 :           log_error ("upd_hashtable: read item failed: %s\n",
    1021             :                      gpg_strerror (rc));
    1022           0 :           return rc;
    1023             :         }
    1024             : 
    1025           0 :       if (rec.rectype == RECTYPE_HTBL)
    1026             :         {
    1027           0 :           hashrec = item;
    1028           0 :           level++;
    1029           0 :           if (level >= keylen)
    1030             :             {
    1031           0 :               log_error ("hashtable has invalid indirections.\n");
    1032           0 :               return GPG_ERR_TRUSTDB;
    1033             :             }
    1034           0 :           goto next_level;
    1035             :         }
    1036           0 :       else if (rec.rectype == RECTYPE_HLST) /* Extend the list.  */
    1037             :         {
    1038             :           /* Check whether the key is already in this list. */
    1039             :           for (;;)
    1040             :             {
    1041           0 :               for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
    1042             :                 {
    1043           0 :                   if (rec.r.hlst.rnum[i] == newrecnum)
    1044             :                     {
    1045           0 :                       return 0; /* Okay, already in the list.  */
    1046             :                     }
    1047             :                 }
    1048           0 :               if (rec.r.hlst.next)
    1049             :                 {
    1050           0 :                   rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
    1051           0 :                   if (rc)
    1052             :                     {
    1053           0 :                       log_error ("upd_hashtable: read hlst failed: %s\n",
    1054             :                                  gpg_strerror (rc) );
    1055           0 :                       return rc;
    1056             :                     }
    1057             :                 }
    1058             :               else
    1059           0 :                 break; /* key is not in the list */
    1060           0 :             }
    1061             : 
    1062             :           /* Find the next free entry and put it in.  */
    1063             :           for (;;)
    1064             :             {
    1065           0 :               for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
    1066             :                 {
    1067           0 :                   if (!rec.r.hlst.rnum[i])
    1068             :                     {
    1069             :                       /* Empty slot found.  */
    1070           0 :                       rec.r.hlst.rnum[i] = newrecnum;
    1071           0 :                       rc = tdbio_write_record (&rec);
    1072           0 :                       if (rc)
    1073           0 :                         log_error ("upd_hashtable: write hlst failed: %s\n",
    1074             :                                    gpg_strerror (rc));
    1075           0 :                       return rc; /* Done.  */
    1076             :                     }
    1077             :                 }
    1078             : 
    1079           0 :               if (rec.r.hlst.next)
    1080             :                 {
    1081             :                   /* read the next reord of the list.  */
    1082           0 :                   rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
    1083           0 :                   if (rc)
    1084             :                     {
    1085           0 :                       log_error ("upd_hashtable: read hlst failed: %s\n",
    1086             :                                  gpg_strerror (rc));
    1087           0 :                       return rc;
    1088             :                     }
    1089             :                 }
    1090             :               else
    1091             :                 {
    1092             :                   /* Append a new record to the list.  */
    1093           0 :                   rec.r.hlst.next = item = tdbio_new_recnum ();
    1094           0 :                   rc = tdbio_write_record (&rec);
    1095           0 :                   if (rc)
    1096             :                     {
    1097           0 :                       log_error ("upd_hashtable: write hlst failed: %s\n",
    1098             :                                  gpg_strerror (rc));
    1099           0 :                       return rc;
    1100             :                     }
    1101           0 :                   memset (&rec, 0, sizeof rec);
    1102           0 :                   rec.rectype = RECTYPE_HLST;
    1103           0 :                   rec.recnum = item;
    1104           0 :                   rec.r.hlst.rnum[0] = newrecnum;
    1105           0 :                   rc = tdbio_write_record (&rec);
    1106           0 :                   if (rc)
    1107           0 :                     log_error ("upd_hashtable: write ext hlst failed: %s\n",
    1108             :                                gpg_strerror (rc));
    1109           0 :                   return rc; /* Done.  */
    1110             :                 }
    1111           0 :             } /* end loop over list slots */
    1112             : 
    1113             :         }
    1114           0 :       else if (rec.rectype == RECTYPE_TRUST) /* Insert a list record.  */
    1115             :         {
    1116           0 :           if (rec.recnum == newrecnum)
    1117             :             {
    1118           0 :               return 0;
    1119             :             }
    1120           0 :           item = rec.recnum; /* Save number of key record.  */
    1121           0 :           memset (&rec, 0, sizeof rec);
    1122           0 :           rec.rectype = RECTYPE_HLST;
    1123           0 :           rec.recnum = tdbio_new_recnum ();
    1124           0 :           rec.r.hlst.rnum[0] = item;        /* Old key record */
    1125           0 :           rec.r.hlst.rnum[1] = newrecnum; /* and new key record */
    1126           0 :           rc = tdbio_write_record (&rec);
    1127           0 :           if (rc)
    1128             :             {
    1129           0 :               log_error( "upd_hashtable: write new hlst failed: %s\n",
    1130             :                            gpg_strerror (rc) );
    1131           0 :               return rc;
    1132             :             }
    1133             :           /* Update the hashtable record.  */
    1134           0 :           lastrec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = rec.recnum;
    1135           0 :           rc = tdbio_write_record (&lastrec);
    1136           0 :           if (rc)
    1137           0 :             log_error ("upd_hashtable: update htbl failed: %s\n",
    1138             :                        gpg_strerror (rc));
    1139           0 :           return rc; /* Ready.  */
    1140             :         }
    1141             :       else
    1142             :         {
    1143           0 :           log_error ("hashtbl %lu: %lu/%d points to an invalid record %lu\n",
    1144             :                      table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
    1145           0 :           if (opt.verbose > 1)
    1146           0 :             list_trustdb (es_stderr, NULL);
    1147           0 :           return GPG_ERR_TRUSTDB;
    1148             :         }
    1149             :     }
    1150             : 
    1151           2 :   return 0;
    1152             : }
    1153             : 
    1154             : 
    1155             : /*
    1156             :  * Drop an entry from a hashtable.  TABLE gives the start of the
    1157             :  * table, KEY and KEYLEN are the key.
    1158             :  *
    1159             :  * Return: 0 on success or an error code.
    1160             :  */
    1161             : static int
    1162           0 : drop_from_hashtable (ulong table, byte *key, int keylen, ulong recnum)
    1163             : {
    1164             :   TRUSTREC rec;
    1165             :   ulong hashrec, item;
    1166             :   int msb;
    1167           0 :   int level = 0;
    1168             :   int rc, i;
    1169             : 
    1170           0 :   hashrec = table;
    1171             :  next_level:
    1172           0 :   msb = key[level];
    1173           0 :   hashrec += msb / ITEMS_PER_HTBL_RECORD;
    1174           0 :   rc = tdbio_read_record (hashrec, &rec, RECTYPE_HTBL );
    1175           0 :   if (rc)
    1176             :     {
    1177           0 :       log_error ("drop_from_hashtable: read failed: %s\n", gpg_strerror (rc));
    1178           0 :       return rc;
    1179             :     }
    1180             : 
    1181           0 :   item = rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
    1182           0 :   if (!item)
    1183           0 :     return 0;   /* Not found - forget about it.  */
    1184             : 
    1185           0 :   if (item == recnum) /* Table points direct to the record.  */
    1186             :     {
    1187           0 :       rec.r.htbl.item[msb % ITEMS_PER_HTBL_RECORD] = 0;
    1188           0 :       rc = tdbio_write_record( &rec );
    1189           0 :       if (rc)
    1190           0 :         log_error ("drop_from_hashtable: write htbl failed: %s\n",
    1191             :                    gpg_strerror (rc));
    1192           0 :       return rc;
    1193             :     }
    1194             : 
    1195           0 :   rc = tdbio_read_record (item, &rec, 0);
    1196           0 :   if (rc)
    1197             :     {
    1198           0 :       log_error ("drop_from_hashtable: read item failed: %s\n",
    1199             :                  gpg_strerror (rc));
    1200           0 :       return rc;
    1201             :     }
    1202             : 
    1203           0 :   if (rec.rectype == RECTYPE_HTBL)
    1204             :     {
    1205           0 :       hashrec = item;
    1206           0 :       level++;
    1207           0 :       if (level >= keylen)
    1208             :         {
    1209           0 :           log_error ("hashtable has invalid indirections.\n");
    1210           0 :           return GPG_ERR_TRUSTDB;
    1211             :         }
    1212           0 :       goto next_level;
    1213             :     }
    1214             : 
    1215           0 :   if (rec.rectype == RECTYPE_HLST)
    1216             :     {
    1217             :       for (;;)
    1218             :         {
    1219           0 :           for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
    1220             :             {
    1221           0 :               if (rec.r.hlst.rnum[i] == recnum)
    1222             :                 {
    1223           0 :                   rec.r.hlst.rnum[i] = 0; /* Mark as free.  */
    1224           0 :                   rc = tdbio_write_record (&rec);
    1225           0 :                   if (rc)
    1226           0 :                     log_error("drop_from_hashtable: write htbl failed: %s\n",
    1227             :                               gpg_strerror (rc));
    1228           0 :                   return rc;
    1229             :                 }
    1230             :             }
    1231           0 :           if (rec.r.hlst.next)
    1232             :             {
    1233           0 :               rc = tdbio_read_record (rec.r.hlst.next, &rec, RECTYPE_HLST);
    1234           0 :               if (rc)
    1235             :                 {
    1236           0 :                   log_error ("drop_from_hashtable: read hlst failed: %s\n",
    1237             :                              gpg_strerror (rc));
    1238           0 :                   return rc;
    1239             :                 }
    1240             :             }
    1241             :           else
    1242           0 :             return 0; /* Key not in table.  */
    1243           0 :         }
    1244             :     }
    1245             : 
    1246           0 :   log_error ("hashtbl %lu: %lu/%d points to wrong record %lu\n",
    1247             :              table, hashrec, (msb % ITEMS_PER_HTBL_RECORD), item);
    1248           0 :   return GPG_ERR_TRUSTDB;
    1249             : }
    1250             : 
    1251             : 
    1252             : 
    1253             : /*
    1254             :  * Lookup a record via the hashtable TABLE by (KEY,KEYLEN) and return
    1255             :  * the result in REC.  The return value of CMP() should be True if the
    1256             :  * record is the desired one.
    1257             :  *
    1258             :  * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
    1259             :  */
    1260             : static gpg_error_t
    1261         208 : lookup_hashtable (ulong table, const byte *key, size_t keylen,
    1262             :                   int (*cmpfnc)(const void*, const TRUSTREC *),
    1263             :                   const void *cmpdata, TRUSTREC *rec )
    1264             : {
    1265             :   int rc;
    1266             :   ulong hashrec, item;
    1267             :   int msb;
    1268         208 :   int level = 0;
    1269             : 
    1270         208 :   hashrec = table;
    1271             :  next_level:
    1272         208 :   msb = key[level];
    1273         208 :   hashrec += msb / ITEMS_PER_HTBL_RECORD;
    1274         208 :   rc = tdbio_read_record (hashrec, rec, RECTYPE_HTBL);
    1275         208 :   if (rc)
    1276             :     {
    1277           0 :       log_error("lookup_hashtable failed: %s\n", gpg_strerror (rc) );
    1278           0 :       return rc;
    1279             :     }
    1280             : 
    1281         208 :   item = rec->r.htbl.item[msb % ITEMS_PER_HTBL_RECORD];
    1282         208 :   if (!item)
    1283         204 :     return gpg_error (GPG_ERR_NOT_FOUND);
    1284             : 
    1285           4 :   rc = tdbio_read_record (item, rec, 0);
    1286           4 :   if (rc)
    1287             :     {
    1288           0 :       log_error( "hashtable read failed: %s\n", gpg_strerror (rc) );
    1289           0 :       return rc;
    1290             :     }
    1291           4 :   if (rec->rectype == RECTYPE_HTBL)
    1292             :     {
    1293           0 :       hashrec = item;
    1294           0 :       level++;
    1295           0 :       if (level >= keylen)
    1296             :         {
    1297           0 :           log_error ("hashtable has invalid indirections\n");
    1298           0 :           return GPG_ERR_TRUSTDB;
    1299             :         }
    1300           0 :       goto next_level;
    1301             :     }
    1302           4 :   else if (rec->rectype == RECTYPE_HLST)
    1303             :     {
    1304             :       for (;;)
    1305             :         {
    1306             :           int i;
    1307             : 
    1308           0 :           for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
    1309             :             {
    1310           0 :               if (rec->r.hlst.rnum[i])
    1311             :                 {
    1312             :                   TRUSTREC tmp;
    1313             : 
    1314           0 :                   rc = tdbio_read_record (rec->r.hlst.rnum[i], &tmp, 0);
    1315           0 :                   if (rc)
    1316             :                     {
    1317           0 :                       log_error ("lookup_hashtable: read item failed: %s\n",
    1318             :                                  gpg_strerror (rc));
    1319           0 :                       return rc;
    1320             :                     }
    1321           0 :                   if ((*cmpfnc)(cmpdata, &tmp))
    1322             :                     {
    1323           0 :                       *rec = tmp;
    1324           0 :                       return 0;
    1325             :                     }
    1326             :                 }
    1327             :             }
    1328           0 :           if (rec->r.hlst.next)
    1329             :             {
    1330           0 :               rc = tdbio_read_record (rec->r.hlst.next, rec, RECTYPE_HLST);
    1331           0 :               if (rc)
    1332             :                 {
    1333           0 :                   log_error ("lookup_hashtable: read hlst failed: %s\n",
    1334             :                              gpg_strerror (rc) );
    1335           0 :                   return rc;
    1336             :                 }
    1337             :             }
    1338             :           else
    1339           0 :             return gpg_error (GPG_ERR_NOT_FOUND);
    1340           0 :         }
    1341             :     }
    1342             : 
    1343           4 :   if ((*cmpfnc)(cmpdata, rec))
    1344           4 :     return 0; /* really found */
    1345             : 
    1346           0 :   return gpg_error (GPG_ERR_NOT_FOUND); /* no: not found */
    1347             : }
    1348             : 
    1349             : 
    1350             : /*
    1351             :  * Update the trust hash table TR or create the table if it does not
    1352             :  * exist.
    1353             :  *
    1354             :  * Return: 0 on success or an error code.
    1355             :  */
    1356             : static int
    1357           2 : update_trusthashtbl( TRUSTREC *tr )
    1358             : {
    1359           4 :   return upd_hashtable (get_trusthashrec(),
    1360           2 :                         tr->r.trust.fingerprint, 20, tr->recnum);
    1361             : }
    1362             : 
    1363             : 
    1364             : /*
    1365             :  * Dump the trustdb record REC to stream FP.
    1366             :  */
    1367             : void
    1368           0 : tdbio_dump_record (TRUSTREC *rec, estream_t fp)
    1369             : {
    1370             :   int i;
    1371           0 :   ulong rnum = rec->recnum;
    1372             : 
    1373           0 :   es_fprintf (fp, "rec %5lu, ", rnum);
    1374             : 
    1375           0 :   switch (rec->rectype)
    1376             :     {
    1377             :     case 0:
    1378           0 :       es_fprintf (fp, "blank\n");
    1379           0 :       break;
    1380             : 
    1381             :     case RECTYPE_VER:
    1382           0 :       es_fprintf (fp,
    1383             :          "version, td=%lu, f=%lu, m/c/d=%d/%d/%d tm=%d mcl=%d nc=%lu (%s)\n",
    1384             :                   rec->r.ver.trusthashtbl,
    1385             :                   rec->r.ver.firstfree,
    1386           0 :                   rec->r.ver.marginals,
    1387           0 :                   rec->r.ver.completes,
    1388           0 :                   rec->r.ver.cert_depth,
    1389           0 :                   rec->r.ver.trust_model,
    1390           0 :                   rec->r.ver.min_cert_level,
    1391             :                   rec->r.ver.nextcheck,
    1392           0 :                   strtimestamp(rec->r.ver.nextcheck)
    1393             :                   );
    1394           0 :       break;
    1395             : 
    1396             :     case RECTYPE_FREE:
    1397           0 :       es_fprintf (fp, "free, next=%lu\n", rec->r.free.next);
    1398           0 :       break;
    1399             : 
    1400             :     case RECTYPE_HTBL:
    1401           0 :       es_fprintf (fp, "htbl,");
    1402           0 :       for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
    1403           0 :         es_fprintf (fp, " %lu", rec->r.htbl.item[i]);
    1404           0 :       es_putc ('\n', fp);
    1405           0 :       break;
    1406             : 
    1407             :     case RECTYPE_HLST:
    1408           0 :       es_fprintf (fp, "hlst, next=%lu,", rec->r.hlst.next);
    1409           0 :       for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
    1410           0 :         es_fprintf (fp, " %lu", rec->r.hlst.rnum[i]);
    1411           0 :       es_putc ('\n', fp);
    1412           0 :       break;
    1413             : 
    1414             :     case RECTYPE_TRUST:
    1415           0 :       es_fprintf (fp, "trust ");
    1416           0 :       for (i=0; i < 20; i++)
    1417           0 :         es_fprintf (fp, "%02X", rec->r.trust.fingerprint[i]);
    1418           0 :       es_fprintf (fp, ", ot=%d, d=%d, vl=%lu\n", rec->r.trust.ownertrust,
    1419           0 :                   rec->r.trust.depth, rec->r.trust.validlist);
    1420           0 :       break;
    1421             : 
    1422             :     case RECTYPE_VALID:
    1423           0 :       es_fprintf (fp, "valid ");
    1424           0 :       for (i=0; i < 20; i++)
    1425           0 :         es_fprintf(fp, "%02X", rec->r.valid.namehash[i]);
    1426           0 :       es_fprintf (fp, ", v=%d, next=%lu\n", rec->r.valid.validity,
    1427             :                   rec->r.valid.next);
    1428           0 :       break;
    1429             : 
    1430             :     default:
    1431           0 :       es_fprintf (fp, "unknown type %d\n", rec->rectype );
    1432           0 :       break;
    1433             :     }
    1434           0 : }
    1435             : 
    1436             : 
    1437             : /*
    1438             :  * Read the record with number RECNUM into the structure REC.  If
    1439             :  * EXPECTED is not 0 reading any other record type will return an
    1440             :  * error.
    1441             :  *
    1442             :  * Return: 0 on success, -1 on EOF, or an error code.
    1443             :  */
    1444             : int
    1445        3332 : tdbio_read_record (ulong recnum, TRUSTREC *rec, int expected)
    1446             : {
    1447             :   byte readbuf[TRUST_RECORD_LEN];
    1448             :   const byte *buf, *p;
    1449        3332 :   gpg_error_t err = 0;
    1450             :   int n, i;
    1451             : 
    1452        3332 :   if (db_fd == -1)
    1453          93 :     open_db ();
    1454             : 
    1455        3332 :   buf = get_record_from_cache( recnum );
    1456        3332 :   if (!buf)
    1457             :     {
    1458        3077 :       if (lseek (db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET) == -1)
    1459             :         {
    1460           0 :           err = gpg_error_from_syserror ();
    1461           0 :           log_error (_("trustdb: lseek failed: %s\n"), strerror (errno));
    1462           0 :           return err;
    1463             :         }
    1464        3077 :       n = read (db_fd, readbuf, TRUST_RECORD_LEN);
    1465        3077 :       if (!n)
    1466             :         {
    1467          89 :           return -1; /* eof */
    1468             :         }
    1469        2988 :       else if (n != TRUST_RECORD_LEN)
    1470             :         {
    1471           0 :           err = gpg_error_from_syserror ();
    1472           0 :           log_error (_("trustdb: read failed (n=%d): %s\n"),
    1473           0 :                      n, strerror(errno));
    1474           0 :           return err;
    1475             :         }
    1476        2988 :       buf = readbuf;
    1477             :     }
    1478        3243 :   rec->recnum = recnum;
    1479        3243 :   rec->dirty = 0;
    1480        3243 :   p = buf;
    1481        3243 :   rec->rectype = *p++;
    1482        3243 :   if (expected && rec->rectype != expected)
    1483             :     {
    1484           0 :       log_error ("%lu: read expected rec type %d, got %d\n",
    1485             :                  recnum, expected, rec->rectype);
    1486           0 :       return gpg_error (GPG_ERR_TRUSTDB);
    1487             :     }
    1488        3243 :   p++;    /* Skip reserved byte.  */
    1489        3243 :   switch (rec->rectype)
    1490             :     {
    1491             :     case 0:  /* unused (free) record */
    1492           0 :       break;
    1493             : 
    1494             :     case RECTYPE_VER: /* version record */
    1495         447 :       if (memcmp(buf+1, GPGEXT_GPG, 3))
    1496             :         {
    1497           0 :           log_error (_("%s: not a trustdb file\n"), db_name );
    1498           0 :           err = gpg_error (GPG_ERR_TRUSTDB);
    1499             :         }
    1500             :       else
    1501             :         {
    1502         447 :           p += 2; /* skip "gpg" */
    1503         447 :           rec->r.ver.version  = *p++;
    1504         447 :           rec->r.ver.marginals = *p++;
    1505         447 :           rec->r.ver.completes = *p++;
    1506         447 :           rec->r.ver.cert_depth = *p++;
    1507         447 :           rec->r.ver.trust_model = *p++;
    1508         447 :           rec->r.ver.min_cert_level = *p++;
    1509         447 :           p += 2;
    1510         447 :           rec->r.ver.created  = buf32_to_ulong(p);
    1511         447 :           p += 4;
    1512         447 :           rec->r.ver.nextcheck = buf32_to_ulong(p);
    1513         447 :           p += 4;
    1514         447 :           p += 4;
    1515         447 :           p += 4;
    1516         447 :           rec->r.ver.firstfree = buf32_to_ulong(p);
    1517         447 :           p += 4;
    1518         447 :           p += 4;
    1519         447 :           rec->r.ver.trusthashtbl = buf32_to_ulong(p);
    1520         447 :           if (recnum)
    1521             :             {
    1522           0 :               log_error( _("%s: version record with recnum %lu\n"), db_name,
    1523             :                          (ulong)recnum );
    1524           0 :               err = gpg_error (GPG_ERR_TRUSTDB);
    1525             :             }
    1526         447 :           else if (rec->r.ver.version != 3)
    1527             :             {
    1528           0 :               log_error( _("%s: invalid file version %d\n"), db_name,
    1529           0 :                          rec->r.ver.version );
    1530           0 :               err = gpg_error (GPG_ERR_TRUSTDB);
    1531             :             }
    1532             :         }
    1533         447 :       break;
    1534             : 
    1535             :     case RECTYPE_FREE:
    1536           0 :       rec->r.free.next  = buf32_to_ulong(p);
    1537           0 :       break;
    1538             : 
    1539             :     case RECTYPE_HTBL:
    1540       27910 :       for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
    1541             :         {
    1542       25119 :           rec->r.htbl.item[i] = buf32_to_ulong(p);
    1543       25119 :           p += 4;
    1544             :         }
    1545        2791 :       break;
    1546             : 
    1547             :     case RECTYPE_HLST:
    1548           0 :       rec->r.hlst.next = buf32_to_ulong(p);
    1549           0 :       p += 4;
    1550           0 :       for (i=0; i < ITEMS_PER_HLST_RECORD; i++)
    1551             :         {
    1552           0 :           rec->r.hlst.rnum[i] = buf32_to_ulong(p);
    1553           0 :           p += 4;
    1554             :         }
    1555           0 :       break;
    1556             : 
    1557             :     case RECTYPE_TRUST:
    1558           5 :       memcpy (rec->r.trust.fingerprint, p, 20);
    1559           5 :       p+=20;
    1560           5 :       rec->r.trust.ownertrust = *p++;
    1561           5 :       rec->r.trust.depth = *p++;
    1562           5 :       rec->r.trust.min_ownertrust = *p++;
    1563           5 :       p++;
    1564           5 :       rec->r.trust.validlist = buf32_to_ulong(p);
    1565           5 :       break;
    1566             : 
    1567             :     case RECTYPE_VALID:
    1568           0 :       memcpy (rec->r.valid.namehash, p, 20);
    1569           0 :       p+=20;
    1570           0 :       rec->r.valid.validity = *p++;
    1571           0 :       rec->r.valid.next = buf32_to_ulong(p);
    1572           0 :       p += 4;
    1573           0 :       rec->r.valid.full_count = *p++;
    1574           0 :       rec->r.valid.marginal_count = *p++;
    1575           0 :       break;
    1576             : 
    1577             :     default:
    1578           0 :       log_error ("%s: invalid record type %d at recnum %lu\n",
    1579             :                  db_name, rec->rectype, (ulong)recnum);
    1580           0 :       err = gpg_error (GPG_ERR_TRUSTDB);
    1581           0 :       break;
    1582             :     }
    1583             : 
    1584        3243 :   return err;
    1585             : }
    1586             : 
    1587             : 
    1588             : /*
    1589             :  * Write the record from the struct REC.
    1590             :  *
    1591             :  * Return: 0 on success or an error code.
    1592             :  */
    1593             : int
    1594         224 : tdbio_write_record( TRUSTREC *rec )
    1595             : {
    1596             :   byte buf[TRUST_RECORD_LEN];
    1597             :   byte *p;
    1598         224 :   int rc = 0;
    1599             :   int i;
    1600         224 :   ulong recnum = rec->recnum;
    1601             : 
    1602         224 :   if (db_fd == -1)
    1603           0 :     open_db ();
    1604             : 
    1605         224 :   memset (buf, 0, TRUST_RECORD_LEN);
    1606         224 :   p = buf;
    1607         224 :   *p++ = rec->rectype; p++;
    1608             : 
    1609         224 :   switch (rec->rectype)
    1610             :     {
    1611             :     case 0:  /* unused record */
    1612           0 :       break;
    1613             : 
    1614             :     case RECTYPE_VER: /* version record */
    1615          17 :       if (recnum)
    1616           0 :         BUG ();
    1617          17 :       memcpy(p-1, GPGEXT_GPG, 3 ); p += 2;
    1618          17 :       *p++ = rec->r.ver.version;
    1619          17 :       *p++ = rec->r.ver.marginals;
    1620          17 :       *p++ = rec->r.ver.completes;
    1621          17 :       *p++ = rec->r.ver.cert_depth;
    1622          17 :       *p++ = rec->r.ver.trust_model;
    1623          17 :       *p++ = rec->r.ver.min_cert_level;
    1624          17 :       p += 2;
    1625          17 :       ulongtobuf(p, rec->r.ver.created); p += 4;
    1626          17 :       ulongtobuf(p, rec->r.ver.nextcheck); p += 4;
    1627          17 :       p += 4;
    1628          17 :       p += 4;
    1629          17 :       ulongtobuf(p, rec->r.ver.firstfree ); p += 4;
    1630          17 :       p += 4;
    1631          17 :       ulongtobuf(p, rec->r.ver.trusthashtbl ); p += 4;
    1632          17 :       break;
    1633             : 
    1634             :     case RECTYPE_FREE:
    1635           0 :       ulongtobuf(p, rec->r.free.next); p += 4;
    1636           0 :       break;
    1637             : 
    1638             :     case RECTYPE_HTBL:
    1639        2050 :       for (i=0; i < ITEMS_PER_HTBL_RECORD; i++)
    1640             :         {
    1641        1845 :           ulongtobuf( p, rec->r.htbl.item[i]); p += 4;
    1642             :         }
    1643         205 :       break;
    1644             : 
    1645             :     case RECTYPE_HLST:
    1646           0 :       ulongtobuf( p, rec->r.hlst.next); p += 4;
    1647           0 :       for (i=0; i < ITEMS_PER_HLST_RECORD; i++ )
    1648             :         {
    1649           0 :           ulongtobuf( p, rec->r.hlst.rnum[i]); p += 4;
    1650             :         }
    1651           0 :       break;
    1652             : 
    1653             :     case RECTYPE_TRUST:
    1654           2 :       memcpy (p, rec->r.trust.fingerprint, 20); p += 20;
    1655           2 :       *p++ = rec->r.trust.ownertrust;
    1656           2 :       *p++ = rec->r.trust.depth;
    1657           2 :       *p++ = rec->r.trust.min_ownertrust;
    1658           2 :       p++;
    1659           2 :       ulongtobuf( p, rec->r.trust.validlist); p += 4;
    1660           2 :       break;
    1661             : 
    1662             :     case RECTYPE_VALID:
    1663           0 :       memcpy (p, rec->r.valid.namehash, 20); p += 20;
    1664           0 :       *p++ = rec->r.valid.validity;
    1665           0 :       ulongtobuf( p, rec->r.valid.next); p += 4;
    1666           0 :       *p++ = rec->r.valid.full_count;
    1667           0 :       *p++ = rec->r.valid.marginal_count;
    1668           0 :       break;
    1669             : 
    1670             :     default:
    1671           0 :       BUG();
    1672             :     }
    1673             : 
    1674         224 :   rc = put_record_into_cache (recnum, buf);
    1675         224 :   if (rc)
    1676             :     ;
    1677         224 :   else if (rec->rectype == RECTYPE_TRUST)
    1678           2 :     rc = update_trusthashtbl (rec);
    1679             : 
    1680         224 :   return rc;
    1681             : }
    1682             : 
    1683             : 
    1684             : /*
    1685             :  * Delete the record at record number RECNUm from the trustdb.
    1686             :  *
    1687             :  * Return: 0 on success or an error code.
    1688             :  */
    1689             : int
    1690           0 : tdbio_delete_record (ulong recnum)
    1691             : {
    1692             :   TRUSTREC vr, rec;
    1693             :   int rc;
    1694             : 
    1695             :   /* Must read the record fist, so we can drop it from the hash tables */
    1696           0 :   rc = tdbio_read_record (recnum, &rec, 0);
    1697           0 :   if (rc)
    1698             :     ;
    1699           0 :   else if (rec.rectype == RECTYPE_TRUST)
    1700             :     {
    1701           0 :       rc = drop_from_hashtable (get_trusthashrec(),
    1702             :                                 rec.r.trust.fingerprint, 20, rec.recnum);
    1703             :     }
    1704             : 
    1705           0 :   if (rc)
    1706           0 :     return rc;
    1707             : 
    1708             :   /* Now we can chnage it to a free record.  */
    1709           0 :   rc = tdbio_read_record (0, &vr, RECTYPE_VER);
    1710           0 :   if (rc)
    1711           0 :     log_fatal (_("%s: error reading version record: %s\n"),
    1712             :                db_name, gpg_strerror (rc));
    1713             : 
    1714           0 :   rec.recnum = recnum;
    1715           0 :   rec.rectype = RECTYPE_FREE;
    1716           0 :   rec.r.free.next = vr.r.ver.firstfree;
    1717           0 :   vr.r.ver.firstfree = recnum;
    1718           0 :   rc = tdbio_write_record (&rec);
    1719           0 :   if (!rc)
    1720           0 :     rc = tdbio_write_record (&vr);
    1721             : 
    1722           0 :   return rc;
    1723             : }
    1724             : 
    1725             : 
    1726             : /*
    1727             :  * Create a new record and return its record number.
    1728             :  */
    1729             : ulong
    1730           2 : tdbio_new_recnum ()
    1731             : {
    1732             :   off_t offset;
    1733             :   ulong recnum;
    1734             :   TRUSTREC vr, rec;
    1735             :   int rc;
    1736             : 
    1737             :   /* Look for unused records.  */
    1738           2 :   rc = tdbio_read_record (0, &vr, RECTYPE_VER);
    1739           2 :   if (rc)
    1740           0 :     log_fatal( _("%s: error reading version record: %s\n"),
    1741             :                db_name, gpg_strerror (rc));
    1742           2 :   if (vr.r.ver.firstfree)
    1743             :     {
    1744           0 :       recnum = vr.r.ver.firstfree;
    1745           0 :       rc = tdbio_read_record (recnum, &rec, RECTYPE_FREE);
    1746           0 :       if (rc)
    1747             :         {
    1748           0 :           log_error (_("%s: error reading free record: %s\n"),
    1749             :                      db_name,  gpg_strerror (rc));
    1750           0 :           return rc;
    1751             :         }
    1752             :       /* Update dir record.  */
    1753           0 :       vr.r.ver.firstfree = rec.r.free.next;
    1754           0 :       rc = tdbio_write_record (&vr);
    1755           0 :       if (rc)
    1756             :         {
    1757           0 :           log_error (_("%s: error writing dir record: %s\n"),
    1758             :                      db_name, gpg_strerror (rc));
    1759           0 :           return rc;
    1760             :         }
    1761             :       /* Zero out the new record.  */
    1762           0 :       memset (&rec, 0, sizeof rec);
    1763           0 :       rec.rectype = 0; /* Mark as unused record (actually already done
    1764             :                           my the memset).  */
    1765           0 :       rec.recnum = recnum;
    1766           0 :       rc = tdbio_write_record (&rec);
    1767           0 :       if (rc)
    1768           0 :         log_fatal (_("%s: failed to zero a record: %s\n"),
    1769             :                    db_name, gpg_strerror (rc));
    1770             :     }
    1771             :   else /* Not found - append a new record.  */
    1772             :     {
    1773           2 :       offset = lseek (db_fd, 0, SEEK_END);
    1774           2 :       if (offset == (off_t)(-1))
    1775           0 :         log_fatal ("trustdb: lseek to end failed: %s\n", strerror (errno));
    1776           2 :       recnum = offset / TRUST_RECORD_LEN;
    1777           2 :       log_assert (recnum); /* this is will never be the first record */
    1778             :       /* We must write a record, so that the next call to this
    1779             :        * function returns another recnum.  */
    1780           2 :       memset (&rec, 0, sizeof rec);
    1781           2 :       rec.rectype = 0; /* unused record */
    1782           2 :       rec.recnum = recnum;
    1783           2 :       rc = 0;
    1784           2 :       if (lseek( db_fd, recnum * TRUST_RECORD_LEN, SEEK_SET) == -1)
    1785             :         {
    1786           0 :           rc = gpg_error_from_syserror ();
    1787           0 :           log_error (_("trustdb rec %lu: lseek failed: %s\n"),
    1788           0 :                      recnum, strerror (errno));
    1789             :         }
    1790             :       else
    1791             :         {
    1792             :           int n;
    1793             : 
    1794           2 :           n = write (db_fd, &rec, TRUST_RECORD_LEN);
    1795           2 :           if (n != TRUST_RECORD_LEN)
    1796             :             {
    1797           0 :               rc = gpg_error_from_syserror ();
    1798           0 :               log_error (_("trustdb rec %lu: write failed (n=%d): %s\n"),
    1799           0 :                          recnum, n, strerror (errno));
    1800             :             }
    1801             :         }
    1802             : 
    1803           2 :       if (rc)
    1804           0 :         log_fatal (_("%s: failed to append a record: %s\n"),
    1805             :                    db_name,     gpg_strerror (rc));
    1806             :     }
    1807             : 
    1808           2 :   return recnum ;
    1809             : }
    1810             : 
    1811             : 
    1812             : 
    1813             : /* Helper function for tdbio_search_trust_byfpr.  */
    1814             : static int
    1815           4 : cmp_trec_fpr ( const void *fpr, const TRUSTREC *rec )
    1816             : {
    1817           8 :   return (rec->rectype == RECTYPE_TRUST
    1818           4 :           && !memcmp (rec->r.trust.fingerprint, fpr, 20));
    1819             : }
    1820             : 
    1821             : 
    1822             : /*
    1823             :  * Given a 20 byte FINGERPRINT search its trust record and return
    1824             :  * that at REC.
    1825             :  *
    1826             :  * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
    1827             :  */
    1828             : gpg_error_t
    1829         208 : tdbio_search_trust_byfpr (const byte *fingerprint, TRUSTREC *rec)
    1830             : {
    1831             :   int rc;
    1832             : 
    1833             :   /* Locate the trust record using the hash table */
    1834         208 :   rc = lookup_hashtable (get_trusthashrec(), fingerprint, 20,
    1835             :                          cmp_trec_fpr, fingerprint, rec );
    1836         208 :   return rc;
    1837             : }
    1838             : 
    1839             : 
    1840             : /*
    1841             :  * Given a primary public key object PK search its trust record and
    1842             :  * return that at REC.
    1843             :  *
    1844             :  * Return: 0 if found, GPG_ERR_NOT_FOUND, or another error code.
    1845             :  */
    1846             : gpg_error_t
    1847         208 : tdbio_search_trust_bypk (PKT_public_key *pk, TRUSTREC *rec)
    1848             : {
    1849             :   byte fingerprint[MAX_FINGERPRINT_LEN];
    1850             :   size_t fingerlen;
    1851             : 
    1852         208 :   fingerprint_from_pk( pk, fingerprint, &fingerlen );
    1853         208 :   for (; fingerlen < 20; fingerlen++)
    1854           0 :     fingerprint[fingerlen] = 0;
    1855         208 :   return tdbio_search_trust_byfpr (fingerprint, rec);
    1856             : }
    1857             : 
    1858             : 
    1859             : /*
    1860             :  * Terminate the process with a message about a corrupted trustdb.
    1861             :  */
    1862             : void
    1863           0 : tdbio_invalid (void)
    1864             : {
    1865           0 :   log_error (_("Error: The trustdb is corrupted.\n"));
    1866           0 :   how_to_fix_the_trustdb ();
    1867           0 :   g10_exit (2);
    1868             : }

Generated by: LCOV version 1.11