LCOV - code coverage report
Current view: top level - lib/dpkg - version.c (source / functions) Hit Total Coverage
Test: dpkg 1.21.11 C code coverage Lines: 69 75 92.0 %
Date: 2022-12-03 00:40:01 Functions: 6 6 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 53 62 85.5 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * libdpkg - Debian packaging suite library routines
       3                 :            :  * version.c - version handling functions
       4                 :            :  *
       5                 :            :  * Copyright © 1995 Ian Jackson <ijackson@chiark.greenend.org.uk>
       6                 :            :  * Copyright © 2008-2014 Guillem Jover <guillem@debian.org>
       7                 :            :  *
       8                 :            :  * This is free software; you can redistribute it and/or modify
       9                 :            :  * it under the terms of the GNU General Public License as published by
      10                 :            :  * the Free Software Foundation; either version 2 of the License, or
      11                 :            :  * (at your option) any later version.
      12                 :            :  *
      13                 :            :  * This is distributed in the hope that it will be useful,
      14                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      15                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16                 :            :  * GNU General Public License for more details.
      17                 :            :  *
      18                 :            :  * You should have received a copy of the GNU General Public License
      19                 :            :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : #include <compat.h>
      24                 :            : 
      25                 :            : #include <dpkg/c-ctype.h>
      26                 :            : #include <dpkg/ehandle.h>
      27                 :            : #include <dpkg/string.h>
      28                 :            : #include <dpkg/version.h>
      29                 :            : 
      30                 :            : /**
      31                 :            :  * Turn the passed version into an empty version.
      32                 :            :  *
      33                 :            :  * This can be used to ensure the version is properly initialized.
      34                 :            :  *
      35                 :            :  * @param version The version to clear.
      36                 :            :  */
      37                 :            : void
      38                 :        325 : dpkg_version_blank(struct dpkg_version *version)
      39                 :            : {
      40                 :        325 :         version->epoch = 0;
      41                 :        325 :         version->version = NULL;
      42                 :        325 :         version->revision = NULL;
      43                 :        325 : }
      44                 :            : 
      45                 :            : /**
      46                 :            :  * Test if a version is not empty.
      47                 :            :  *
      48                 :            :  * @param version The version to test.
      49                 :            :  *
      50                 :            :  * @retval true If the version is informative (i.e. not an empty version).
      51                 :            :  * @retval false If the version is empty.
      52                 :            :  */
      53                 :            : bool
      54                 :         10 : dpkg_version_is_informative(const struct dpkg_version *version)
      55                 :            : {
      56         [ +  + ]:          9 :         return (version->epoch ||
      57   [ +  +  +  + ]:         19 :                 str_is_set(version->version) ||
      58                 :          5 :                 str_is_set(version->revision));
      59                 :            : }
      60                 :            : 
      61                 :            : /**
      62                 :            :  * Give a weight to the character to order in the version comparison.
      63                 :            :  *
      64                 :            :  * @param c An ASCII character.
      65                 :            :  */
      66                 :            : static int
      67                 :         64 : order(int c)
      68                 :            : {
      69         [ -  + ]:         64 :         if (c_isdigit(c))
      70                 :          0 :                 return 0;
      71         [ +  + ]:         64 :         else if (c_isalpha(c))
      72                 :         24 :                 return c;
      73         [ +  + ]:         40 :         else if (c == '~')
      74                 :          4 :                 return -1;
      75         [ +  - ]:         36 :         else if (c)
      76                 :         36 :                 return c + 256;
      77                 :            :         else
      78                 :          0 :                 return 0;
      79                 :            : }
      80                 :            : 
      81                 :            : static int
      82                 :         71 : verrevcmp(const char *a, const char *b)
      83                 :            : {
      84         [ +  + ]:         71 :         if (a == NULL)
      85                 :          2 :                 a = "";
      86         [ +  + ]:         71 :         if (b == NULL)
      87                 :          2 :                 b = "";
      88                 :            : 
      89   [ +  +  -  + ]:        134 :         while (*a || *b) {
      90                 :         79 :                 int first_diff = 0;
      91                 :            : 
      92   [ +  +  +  +  :        107 :                 while ((*a && !c_isdigit(*a)) || (*b && !c_isdigit(*b))) {
             +  +  -  + ]
      93                 :         32 :                         int ac = order(*a);
      94                 :         32 :                         int bc = order(*b);
      95                 :            : 
      96         [ +  + ]:         32 :                         if (ac != bc)
      97                 :          4 :                                 return ac - bc;
      98                 :            : 
      99                 :         28 :                         a++;
     100                 :         28 :                         b++;
     101                 :            :                 }
     102         [ +  + ]:        120 :                 while (*a == '0')
     103                 :         45 :                         a++;
     104         [ +  + ]:        120 :                 while (*b == '0')
     105                 :         45 :                         b++;
     106   [ +  +  +  - ]:        106 :                 while (c_isdigit(*a) && c_isdigit(*b)) {
     107         [ +  - ]:         31 :                         if (!first_diff)
     108                 :         31 :                                 first_diff = *a - *b;
     109                 :         31 :                         a++;
     110                 :         31 :                         b++;
     111                 :            :                 }
     112                 :            : 
     113         [ -  + ]:         75 :                 if (c_isdigit(*a))
     114                 :          0 :                         return 1;
     115         [ -  + ]:         75 :                 if (c_isdigit(*b))
     116                 :          0 :                         return -1;
     117         [ +  + ]:         75 :                 if (first_diff)
     118                 :         12 :                         return first_diff;
     119                 :            :         }
     120                 :            : 
     121                 :         55 :         return 0;
     122                 :            : }
     123                 :            : 
     124                 :            : /**
     125                 :            :  * Compares two Debian versions.
     126                 :            :  *
     127                 :            :  * This function follows the convention of the comparator functions used by
     128                 :            :  * qsort().
     129                 :            :  *
     130                 :            :  * @see deb-version(5)
     131                 :            :  *
     132                 :            :  * @param a The first version.
     133                 :            :  * @param b The second version.
     134                 :            :  *
     135                 :            :  * @retval 0 If a and b are equal.
     136                 :            :  * @retval <0 If a is smaller than b.
     137                 :            :  * @retval >0 If a is greater than b.
     138                 :            :  */
     139                 :            : int
     140                 :         45 : dpkg_version_compare(const struct dpkg_version *a,
     141                 :            :                      const struct dpkg_version *b)
     142                 :            : {
     143                 :            :         int rc;
     144                 :            : 
     145         [ +  + ]:         45 :         if (a->epoch > b->epoch)
     146                 :          1 :                 return 1;
     147         [ +  + ]:         44 :         if (a->epoch < b->epoch)
     148                 :          2 :                 return -1;
     149                 :            : 
     150                 :         42 :         rc = verrevcmp(a->version, b->version);
     151         [ +  + ]:         42 :         if (rc)
     152                 :         13 :                 return rc;
     153                 :            : 
     154                 :         29 :         return verrevcmp(a->revision, b->revision);
     155                 :            : }
     156                 :            : 
     157                 :            : /**
     158                 :            :  * Check if two versions have a certain relation.
     159                 :            :  *
     160                 :            :  * @param a The first version.
     161                 :            :  * @param rel The relation.
     162                 :            :  * @param b The second version.
     163                 :            :  *
     164                 :            :  * @retval true If rel is #DPKG_RELATION_NONE or the expression “a rel b” is
     165                 :            :  *              true.
     166                 :            :  * @retval false Otherwise.
     167                 :            :  *
     168                 :            :  * @warning If rel is not a valid relation, this function will terminate
     169                 :            :  *          the program.
     170                 :            :  */
     171                 :            : bool
     172                 :         16 : dpkg_version_relate(const struct dpkg_version *a,
     173                 :            :                     enum dpkg_relation rel,
     174                 :            :                     const struct dpkg_version *b)
     175                 :            : {
     176                 :            :         int rc;
     177                 :            : 
     178         [ +  + ]:         16 :         if (rel == DPKG_RELATION_NONE)
     179                 :          1 :                 return true;
     180                 :            : 
     181                 :         15 :         rc = dpkg_version_compare(a, b);
     182                 :            : 
     183   [ +  +  +  +  :         15 :         switch (rel) {
                   +  - ]
     184                 :          3 :         case DPKG_RELATION_EQ:
     185                 :          3 :                 return rc == 0;
     186                 :          3 :         case DPKG_RELATION_LT:
     187                 :          3 :                 return rc < 0;
     188                 :          3 :         case DPKG_RELATION_LE:
     189                 :          3 :                 return rc <= 0;
     190                 :          3 :         case DPKG_RELATION_GT:
     191                 :          3 :                 return rc > 0;
     192                 :          3 :         case DPKG_RELATION_GE:
     193                 :          3 :                 return rc >= 0;
     194                 :          0 :         default:
     195                 :          0 :                 internerr("unknown dpkg_relation %d", rel);
     196                 :            :         }
     197                 :            :         return false;
     198                 :            : }

Generated by: LCOV version 1.16