dirmngr: More binary I/O on Windows for CRLs
[gnupg.git] / dirmngr / cdblib.c
index de60fe9..827399f 100644 (file)
@@ -7,7 +7,7 @@
  * inclusion into Dirmngr.  By Werner Koch <wk@gnupg.org> 2003-12-12.
  */
 
-/* A cdb database is a single file used to map `keys' to `values',
+/* A cdb database is a single file used to map 'keys' to 'values',
    having records of (key,value) pairs.  File consists of 3 parts: toc
    (table of contents), data and index (hash tables).
 
@@ -59,7 +59,7 @@
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
-#include <stdlib.h> 
+#include <stdlib.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
@@ -73,6 +73,8 @@
 # endif
 #endif
 #include <sys/stat.h>
+
+#include "dirmngr-err.h"
 #include "cdb.h"
 
 #ifndef EPROTO
@@ -87,7 +89,7 @@ struct cdb_rec {
   cdbi_t hval;
   cdbi_t rpos;
 };
-  
+
 struct cdb_rl {
   struct cdb_rl *next;
   cdbi_t cnt;
@@ -113,9 +115,10 @@ cdb_init(struct cdb *cdbp, int fd)
 {
   struct stat st;
   unsigned char *mem;
-  unsigned fsize;
 #ifdef _WIN32
   HANDLE hFile, hMapping;
+#else
+  unsigned int fsize;
 #endif
 
   /* get file size */
@@ -123,13 +126,16 @@ cdb_init(struct cdb *cdbp, int fd)
     return -1;
   /* trivial sanity check: at least toc should be here */
   if (st.st_size < 2048) {
-    errno = EPROTO;
+    gpg_err_set_errno (EPROTO);
     return -1;
   }
-  fsize = (unsigned)(st.st_size & 0xffffffffu);
   /* memory-map file */
 #ifdef _WIN32
+# ifdef __MINGW32CE__
+  hFile = fd;
+# else
   hFile = (HANDLE) _get_osfhandle(fd);
+# endif
   if (hFile == (HANDLE) -1)
     return -1;
   hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
@@ -138,11 +144,13 @@ cdb_init(struct cdb *cdbp, int fd)
   mem = (unsigned char *)MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
   if (!mem)
     return -1;
-#else
+  cdbp->cdb_mapping = hMapping;
+#else /*!_WIN32*/
+  fsize = (unsigned int)(st.st_size & 0xffffffffu);
   mem = (unsigned char*)mmap(NULL, fsize, PROT_READ, MAP_SHARED, fd, 0);
   if (mem == MAP_FAILED)
     return -1;
-#endif /* _WIN32 */
+#endif /*!_WIN32*/
 
   cdbp->cdb_fd = fd;
   cdbp->cdb_fsize = st.st_size;
@@ -174,13 +182,9 @@ cdb_free(struct cdb *cdbp)
 {
   if (cdbp->cdb_mem) {
 #ifdef _WIN32
-    HANDLE hFile, hMapping;
-#endif
-#ifdef _WIN32
-    hFile = (HANDLE) _get_osfhandle(cdbp->cdb_fd);
-    hMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
-    UnmapViewOfFile((void*) cdbp->cdb_mem);
-    CloseHandle(hMapping);
+    UnmapViewOfFile ((void*) cdbp->cdb_mem);
+    CloseHandle (cdbp->cdb_mapping);
+    cdbp->cdb_mapping = NULL;
 #else
     munmap((void*)cdbp->cdb_mem, cdbp->cdb_fsize);
 #endif /* _WIN32 */
@@ -199,7 +203,7 @@ int
 cdb_read(const struct cdb *cdbp, void *buf, unsigned len, cdbi_t pos)
 {
   if (pos > cdbp->cdb_fsize || cdbp->cdb_fsize - pos < len) {
-    errno = EPROTO;
+    gpg_err_set_errno (EPROTO);
     return -1;
   }
   memcpy(buf, cdbp->cdb_mem + pos, len);
@@ -243,7 +247,7 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
       || pos > cdbp->cdb_fsize /* htab start within file ? */
       || httodo > cdbp->cdb_fsize - pos) /* entrie htab within file ? */
   {
-    errno = EPROTO;
+    gpg_err_set_errno (EPROTO);
     return -1;
   }
 
@@ -258,19 +262,19 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
       return 0;
     if (cdb_unpack(htp) == hval) {
       if (pos > cdbp->cdb_fsize - 8) { /* key+val lengths */
-       errno = EPROTO;
+       gpg_err_set_errno (EPROTO);
        return -1;
       }
       if (cdb_unpack(cdbp->cdb_mem + pos) == klen) {
        if (cdbp->cdb_fsize - klen < pos + 8) {
-         errno = EPROTO;
+         gpg_err_set_errno (EPROTO);
          return -1;
        }
        if (memcmp(key, cdbp->cdb_mem + pos + 8, klen) == 0) {
          n = cdb_unpack(cdbp->cdb_mem + pos + 4);
          pos += 8 + klen;
          if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
-           errno = EPROTO;
+           gpg_err_set_errno (EPROTO);
            return -1;
          }
          cdbp->cdb_vpos = pos;
@@ -292,18 +296,17 @@ cdb_find(struct cdb *cdbp, const void *key, cdbi_t klen)
 
 /* Sequential-find routines that used separate structure.  It is
    possible to have many than one record with the same key in a
-   database, and these routines allows to enumerate all them.
+   database, and these routines allow enumeration of all of them.
    cdb_findinit() initializes search structure pointed to by cdbfp.
-   It will return negative value on error or 0 on success.  cdb_findĀ­
-   next() attempts to find next matching key, setting value position
-   and length in cdbfp structure.  It will return positive value if
-   given key was found, 0 if there is no more such key(s), or negative
-   value on error.  To access value position and length after
+   It will return negative value on error or 0 on success.
+   cdb_findnext() attempts to find next matching key, setting value
+   position and length in cdbfp structure.  It will return positive
+   value if given key was found, 0 if there is no more such key(s), or
+   negative value on error.  To access value position and length after
    successeful call to cdb_findnext() (when it returned positive
    result), use cdb_datapos() and cdb_datalen() macros with cdbp
    pointer.  It is error to use cdb_findnext() after it returned 0 or
-   error condition.  These routines is a bit slower than
-   cdb_find(). 
+   error condition.  These routines is a bit slower than cdb_find().
 
    Setting KEY to NULL will start a sequential search through the
    entire DB.
@@ -331,7 +334,7 @@ cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
           || pos > cdbp->cdb_fsize
           || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
         {
-          errno = EPROTO;
+          gpg_err_set_errno (EPROTO);
           return -1;
         }
 
@@ -341,7 +344,7 @@ cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
     }
   else /* Walk over all entries. */
     {
-      cdbfp->cdb_hval = 0; 
+      cdbfp->cdb_hval = 0;
       /* Force stepping in findnext. */
       cdbfp->cdb_htp = cdbfp->cdb_htend = cdbp->cdb_mem;
     }
@@ -350,7 +353,7 @@ cdb_findinit(struct cdb_find *cdbfp, struct cdb *cdbp,
 
 
 /* See cdb_findinit. */
-int 
+int
 cdb_findnext(struct cdb_find *cdbfp)
 {
   cdbi_t pos, n;
@@ -368,12 +371,12 @@ cdb_findnext(struct cdb_find *cdbfp)
         cdbfp->cdb_httodo -= 8;
         if (n) {
           if (pos > cdbp->cdb_fsize - 8) {
-            errno = EPROTO;
+            gpg_err_set_errno (EPROTO);
             return -1;
           }
           if (cdb_unpack(cdbp->cdb_mem + pos) == cdbfp->cdb_klen) {
             if (cdbp->cdb_fsize - cdbfp->cdb_klen < pos + 8) {
-              errno = EPROTO;
+              gpg_err_set_errno (EPROTO);
               return -1;
             }
             if (memcmp(cdbfp->cdb_key,
@@ -381,7 +384,7 @@ cdb_findnext(struct cdb_find *cdbfp)
               n = cdb_unpack(cdbp->cdb_mem + pos + 4);
               pos += 8 + cdbfp->cdb_klen;
               if (cdbp->cdb_fsize < n || cdbp->cdb_fsize - n < pos) {
-                errno = EPROTO;
+                gpg_err_set_errno (EPROTO);
                 return -1;
               }
               cdbp->cdb_vpos = pos;
@@ -400,7 +403,7 @@ cdb_findnext(struct cdb_find *cdbfp)
             {
               if (cdbfp->cdb_hval > 255)
                 return 0; /* No more items. */
-              
+
               cdbfp->cdb_htp = cdbp->cdb_mem + cdbfp->cdb_hval * 8;
               cdbfp->cdb_hval++; /* Advance for next round. */
               pos = cdb_unpack (cdbfp->cdb_htp);     /* Offset of table. */
@@ -410,25 +413,25 @@ cdb_findnext(struct cdb_find *cdbfp)
                   || pos > cdbp->cdb_fsize
                   || cdbfp->cdb_httodo > cdbp->cdb_fsize - pos)
                 {
-                  errno = EPROTO;
+                  gpg_err_set_errno (EPROTO);
                   return -1;
                 }
-              
+
               cdbfp->cdb_htab  = cdbp->cdb_mem + pos;
               cdbfp->cdb_htend = cdbfp->cdb_htab + cdbfp->cdb_httodo;
               cdbfp->cdb_htp   = cdbfp->cdb_htab;
             }
-          
+
           pos = cdb_unpack (cdbfp->cdb_htp + 4); /* Offset of record. */
           cdbfp->cdb_htp += 8;
-        } 
+        }
       while (!pos);
       if (pos > cdbp->cdb_fsize - 8)
         {
-          errno = EPROTO;
+          gpg_err_set_errno (EPROTO);
           return -1;
         }
-      
+
       cdbp->cdb_kpos = pos + 8;
       cdbp->cdb_klen = cdb_unpack(cdbp->cdb_mem + pos);
       cdbp->cdb_vpos = pos + 8 + cdbp->cdb_klen;
@@ -436,7 +439,7 @@ cdb_findnext(struct cdb_find *cdbfp)
       n = 8 + cdbp->cdb_klen + cdbp->cdb_vlen;
       if ( pos > cdbp->cdb_fsize || pos > cdbp->cdb_fsize - n)
         {
-          errno = EPROTO;
+          gpg_err_set_errno (EPROTO);
           return -1;
         }
       return 1; /* Found. */
@@ -454,7 +457,7 @@ cdb_bread(int fd, void *buf, int len)
     while(l < 0 && errno == EINTR);
     if (l <= 0) {
       if (!l)
-        errno = EIO;
+        gpg_err_set_errno (EIO);
       return -1;
     }
     buf = (char*)buf + l;
@@ -555,7 +558,7 @@ cdb_make_add(struct cdb_make *cdbmp,
   struct cdb_rl *rl;
   if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
       vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
-    errno = ENOMEM;
+    gpg_err_set_errno (ENOMEM);
     return -1;
   }
   hval = cdb_hash(key, klen);
@@ -563,7 +566,7 @@ cdb_make_add(struct cdb_make *cdbmp,
   if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
     rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
     if (!rl) {
-      errno = ENOMEM;
+      gpg_err_set_errno (ENOMEM);
       return -1;
     }
     rl->cnt = 0;
@@ -603,7 +606,7 @@ cdb_make_put(struct cdb_make *cdbmp,
        return -1;
       if (c) {
        if (flags == CDB_PUT_INSERT) {
-         errno = EEXIST;
+         gpg_err_set_errno (EEXIST);
          return 1;
        }
        else if (flags == CDB_PUT_REPLACE) {
@@ -614,14 +617,14 @@ cdb_make_put(struct cdb_make *cdbmp,
        else
          r = 1;
       }
-      /* fall */
+      /* fall through */
 
     case CDB_PUT_ADD:
       rl = cdbmp->cdb_rec[hval&255];
       if (!rl || rl->cnt >= sizeof(rl->rec)/sizeof(rl->rec[0])) {
        rl = (struct cdb_rl*)malloc(sizeof(struct cdb_rl));
        if (!rl) {
-         errno = ENOMEM;
+         gpg_err_set_errno (ENOMEM);
          return -1;
        }
        rl->cnt = 0;
@@ -633,13 +636,13 @@ cdb_make_put(struct cdb_make *cdbmp,
       break;
 
     default:
-      errno = EINVAL;
+      gpg_err_set_errno (EINVAL);
       return -1;
   }
 
   if (klen > 0xffffffff - (cdbmp->cdb_dpos + 8) ||
       vlen > 0xffffffff - (cdbmp->cdb_dpos + klen + 8)) {
-    errno = ENOMEM;
+    gpg_err_set_errno (ENOMEM);
     return -1;
   }
   rl->rec[c].hval = hval;
@@ -692,7 +695,7 @@ make_find (struct cdb_make *cdbmp,
 {
   struct cdb_rl *rl = cdbmp->cdb_rec[hval&255];
   int r, i;
-  int seeked = 0;
+  int sought = 0;
   while(rl) {
     for(i = rl->cnt - 1; i >= 0; --i) { /* search backward */
       if (rl->rec[i].hval != hval)
@@ -707,7 +710,7 @@ make_find (struct cdb_make *cdbmp,
           return -1;
         cdbmp->cdb_bpos = cdbmp->cdb_buf;
       }
-      seeked = 1;
+      sought = 1;
       r = match(cdbmp->cdb_fd, rl->rec[i].rpos, key, klen);
       if (!r)
        continue;
@@ -721,7 +724,7 @@ make_find (struct cdb_make *cdbmp,
     }
     rl = rl->next;
   }
-  if (seeked && lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
+  if (sought && lseek(cdbmp->cdb_fd, cdbmp->cdb_dpos, SEEK_SET) < 0)
     return -1;
   return 0;
 }
@@ -812,7 +815,7 @@ cdb_make_finish_internal(struct cdb_make *cdbmp)
   unsigned t, i;
 
   if (((0xffffffff - cdbmp->cdb_dpos) >> 3) < cdbmp->cdb_rcnt) {
-    errno = ENOMEM;
+    gpg_err_set_errno (ENOMEM);
     return -1;
   }
 
@@ -837,7 +840,7 @@ cdb_make_finish_internal(struct cdb_make *cdbmp)
   /* allocate memory to hold max htable */
   htab = (struct cdb_rec*)malloc((hsize + 2) * sizeof(struct cdb_rec));
   if (!htab) {
-    errno = ENOENT;
+    gpg_err_set_errno (ENOENT);
     return -1;
   }
   p = (unsigned char *)htab;