LCOV - code coverage report
Current view: top level - subprojects/tinycdb-0.81 - cdb_seek.c (source / functions) Coverage Total Hit
Test: 2 coverage DB files Lines: 66.7 % 51 34
Test Date: 2025-09-15 13:55:46 Functions: 100.0 % 2 2
Branches: 47.7 % 44 21

             Branch data     Line data    Source code
       1                 :             : /* cdb_seek.c: old interface for reading cdb file
       2                 :             :  *
       3                 :             :  * This file is a part of tinycdb package.
       4                 :             :  * Copyright (C) 2001-2023 Michael Tokarev <mjt+cdb@corpit.ru>
       5                 :             :  *
       6                 :             :  * Permission is hereby granted, free of charge, to any person obtaining a
       7                 :             :  * copy of this software and associated documentation files (the "Software"),
       8                 :             :  * to deal in the Software without restriction, including without limitation
       9                 :             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      10                 :             :  * and/or sell copies of the Software, and to permit persons to whom the
      11                 :             :  * Software is furnished to do so, subject to the following conditions:
      12                 :             :  *
      13                 :             :  * The above copyright notice and this permission notice shall be included
      14                 :             :  * in all copies or substantial portions of the Software.
      15                 :             :  *
      16                 :             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      17                 :             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      18                 :             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
      19                 :             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      20                 :             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      21                 :             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      22                 :             :  * DEALINGS IN THE SOFTWARE.
      23                 :             :  */
      24                 :             : 
      25                 :             : #include <unistd.h>
      26                 :             : #include "cdb_int.h"
      27                 :             : 
      28                 :             : #ifndef SEEK_SET
      29                 :             : # define SEEK_SET 0
      30                 :             : #endif
      31                 :             : 
      32                 :             : /* read a chunk from file, ignoring interrupts (EINTR) */
      33                 :             : 
      34                 :             : int
      35                 :         126 : cdb_bread(int fd, void *buf, int len)
      36                 :             : {
      37                 :             :   int l;
      38         [ +  + ]:         252 :   while(len > 0) {
      39                 :         126 :     do l = read(fd, buf, len);
      40   [ -  +  -  - ]:         126 :     while(l < 0 && errno == EINTR);
      41         [ -  + ]:         126 :     if (l <= 0) {
      42         [ #  # ]:           0 :       if (!l)
      43                 :           0 :         errno = EIO;
      44                 :           0 :       return -1;
      45                 :             :     }
      46                 :         126 :     buf = (char*)buf + l;
      47                 :         126 :     len -= l;
      48                 :             :   }
      49                 :         126 :   return 0;
      50                 :             : }
      51                 :             : 
      52                 :             : /* find a given key in cdb file, seek a file pointer to it's value and
      53                 :             :    place data length to *dlenp. */
      54                 :             : 
      55                 :             : int
      56                 :          63 : cdb_seek(int fd, const void *key, unsigned klen, unsigned *dlenp)
      57                 :             : {
      58                 :             :   unsigned htstart;             /* hash table start position */
      59                 :             :   unsigned htsize;              /* number of elements in a hash table */
      60                 :             :   unsigned httodo;              /* hash table elements left to look */
      61                 :             :   unsigned hti;                 /* hash table index */
      62                 :             :   unsigned pos;                 /* position in a file */
      63                 :             :   unsigned hval;                        /* key's hash value */
      64                 :             :   unsigned char rbuf[64];       /* read buffer */
      65                 :          63 :   int needseek = 1;             /* if we should seek to a hash slot */
      66                 :             : 
      67                 :          63 :   hval = cdb_hash(key, klen);
      68                 :          63 :   pos = (hval & 0xff) << 3; /* position in TOC */
      69                 :             :   /* read the hash table parameters */
      70   [ +  -  -  + ]:          63 :   if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
      71                 :           0 :     return -1;
      72         [ +  + ]:          63 :   if ((htsize = cdb_unpack(rbuf + 4)) == 0)
      73                 :          44 :     return 0;
      74                 :          19 :   hti = (hval >> 8) % htsize;     /* start position in hash table */
      75                 :          19 :   httodo = htsize;
      76                 :          19 :   htstart = cdb_unpack(rbuf);
      77                 :             : 
      78                 :             :   for(;;) {
      79   [ +  -  -  + ]:          19 :     if (needseek && lseek(fd, htstart + (hti << 3), SEEK_SET) < 0)
      80                 :           0 :       return -1;
      81         [ -  + ]:          19 :     if (cdb_bread(fd, rbuf, 8) < 0)
      82                 :           0 :       return -1;
      83         [ -  + ]:          19 :     if ((pos = cdb_unpack(rbuf + 4)) == 0) /* not found */
      84                 :           0 :       return 0;
      85                 :             : 
      86         [ -  + ]:          19 :     if (cdb_unpack(rbuf) != hval) /* hash value not matched */
      87                 :           0 :       needseek = 0;
      88                 :             :     else { /* hash value matched */
      89   [ +  -  -  + ]:          19 :       if (lseek(fd, pos, SEEK_SET) < 0 || cdb_bread(fd, rbuf, 8) < 0)
      90                 :           0 :         return -1;
      91         [ +  - ]:          19 :       if (cdb_unpack(rbuf) == klen) { /* key length matches */
      92                 :             :         /* read the key from file and compare with wanted */
      93                 :          19 :         unsigned l = klen, c;
      94                 :          19 :         const char *k = (const char*)key;
      95         [ +  - ]:          19 :         if (dlenp)
      96                 :          19 :           *dlenp = cdb_unpack(rbuf + 4); /* save value length */
      97                 :             :         for(;;) {
      98         [ +  + ]:          38 :           if (!l) /* the whole key read and matches, return */
      99                 :          19 :             return 1;
     100                 :          19 :           c = l > sizeof(rbuf) ? sizeof(rbuf) : l;
     101         [ -  + ]:          19 :           if (cdb_bread(fd, rbuf, c) < 0)
     102                 :           0 :             return -1;
     103         [ -  + ]:          19 :           if (memcmp(rbuf, k, c) != 0) /* no, it differs, stop here */
     104                 :           0 :             break;
     105                 :          19 :           k += c; l -= c;
     106                 :             :         }
     107                 :             :       }
     108                 :           0 :       needseek = 1; /* we're looked to other place, should seek back */
     109                 :             :     }
     110         [ #  # ]:           0 :     if (!--httodo)
     111                 :           0 :       return 0;
     112         [ #  # ]:           0 :     if (++hti == htsize) {
     113                 :           0 :       hti = 0;
     114                 :           0 :       needseek = 1;
     115                 :             :     }
     116                 :             :   }
     117                 :             : }
        

Generated by: LCOV version 2.0-1