LCOV - code coverage report
Current view: top level - shared - uid-range.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 89 96 92.7 %
Date: 2019-08-23 13:36:53 Functions: 7 7 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 57 78 73.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <stdlib.h>
       5                 :            : #include <string.h>
       6                 :            : 
       7                 :            : #include "alloc-util.h"
       8                 :            : #include "macro.h"
       9                 :            : #include "sort-util.h"
      10                 :            : #include "uid-range.h"
      11                 :            : #include "user-util.h"
      12                 :            : 
      13                 :         60 : static bool uid_range_intersect(UidRange *range, uid_t start, uid_t nr) {
      14         [ -  + ]:         60 :         assert(range);
      15                 :            : 
      16         [ +  + ]:        112 :         return range->start <= start + nr &&
      17         [ +  + ]:         52 :                 range->start + range->nr >= start;
      18                 :            : }
      19                 :            : 
      20                 :         28 : static void uid_range_coalesce(UidRange **p, unsigned *n) {
      21                 :            :         unsigned i, j;
      22                 :            : 
      23         [ -  + ]:         28 :         assert(p);
      24         [ -  + ]:         28 :         assert(n);
      25                 :            : 
      26         [ +  + ]:         72 :         for (i = 0; i < *n; i++) {
      27         [ +  + ]:         76 :                 for (j = i + 1; j < *n; j++) {
      28                 :         32 :                         UidRange *x = (*p)+i, *y = (*p)+j;
      29                 :            : 
      30         [ +  + ]:         32 :                         if (uid_range_intersect(x, y->start, y->nr)) {
      31                 :            :                                 uid_t begin, end;
      32                 :            : 
      33                 :         12 :                                 begin = MIN(x->start, y->start);
      34                 :         12 :                                 end = MAX(x->start + x->nr, y->start + y->nr);
      35                 :            : 
      36                 :         12 :                                 x->start = begin;
      37                 :         12 :                                 x->nr = end - begin;
      38                 :            : 
      39         [ +  + ]:         12 :                                 if (*n > j+1)
      40                 :          4 :                                         memmove(y, y+1, sizeof(UidRange) * (*n - j -1));
      41                 :            : 
      42                 :         12 :                                 (*n)--;
      43                 :         12 :                                 j--;
      44                 :            :                         }
      45                 :            :                 }
      46                 :            :         }
      47                 :         28 : }
      48                 :            : 
      49                 :         28 : static int uid_range_compare(const UidRange *a, const UidRange *b) {
      50                 :            :         int r;
      51                 :            : 
      52         [ +  + ]:         28 :         r = CMP(a->start, b->start);
      53         [ +  - ]:         28 :         if (r != 0)
      54                 :         28 :                 return r;
      55                 :            : 
      56         [ #  # ]:          0 :         return CMP(a->nr, b->nr);
      57                 :            : }
      58                 :            : 
      59                 :         28 : int uid_range_add(UidRange **p, unsigned *n, uid_t start, uid_t nr) {
      60                 :         28 :         bool found = false;
      61                 :            :         UidRange *x;
      62                 :            :         unsigned i;
      63                 :            : 
      64         [ -  + ]:         28 :         assert(p);
      65         [ -  + ]:         28 :         assert(n);
      66                 :            : 
      67         [ -  + ]:         28 :         if (nr <= 0)
      68                 :          0 :                 return 0;
      69                 :            : 
      70         [ +  + ]:         44 :         for (i = 0; i < *n; i++) {
      71                 :         28 :                 x = (*p) + i;
      72         [ +  + ]:         28 :                 if (uid_range_intersect(x, start, nr)) {
      73                 :         12 :                         found = true;
      74                 :         12 :                         break;
      75                 :            :                 }
      76                 :            :         }
      77                 :            : 
      78         [ +  + ]:         28 :         if (found) {
      79                 :            :                 uid_t begin, end;
      80                 :            : 
      81                 :         12 :                 begin = MIN(x->start, start);
      82                 :         12 :                 end = MAX(x->start + x->nr, start + nr);
      83                 :            : 
      84                 :         12 :                 x->start = begin;
      85                 :         12 :                 x->nr = end - begin;
      86                 :            :         } else {
      87                 :            :                 UidRange *t;
      88                 :            : 
      89                 :         16 :                 t = reallocarray(*p, *n + 1, sizeof(UidRange));
      90         [ -  + ]:         16 :                 if (!t)
      91                 :          0 :                         return -ENOMEM;
      92                 :            : 
      93                 :         16 :                 *p = t;
      94                 :         16 :                 x = t + ((*n) ++);
      95                 :            : 
      96                 :         16 :                 x->start = start;
      97                 :         16 :                 x->nr = nr;
      98                 :            :         }
      99                 :            : 
     100                 :         28 :         typesafe_qsort(*p, *n, uid_range_compare);
     101                 :         28 :         uid_range_coalesce(p, n);
     102                 :            : 
     103                 :         28 :         return *n;
     104                 :            : }
     105                 :            : 
     106                 :         28 : int uid_range_add_str(UidRange **p, unsigned *n, const char *s) {
     107                 :            :         uid_t start, nr;
     108                 :            :         const char *t;
     109                 :            :         int r;
     110                 :            : 
     111         [ -  + ]:         28 :         assert(p);
     112         [ -  + ]:         28 :         assert(n);
     113         [ -  + ]:         28 :         assert(s);
     114                 :            : 
     115                 :         28 :         t = strchr(s, '-');
     116         [ +  + ]:         28 :         if (t) {
     117                 :            :                 char *b;
     118                 :            :                 uid_t end;
     119                 :            : 
     120                 :         16 :                 b = strndupa(s, t - s);
     121                 :         16 :                 r = parse_uid(b, &start);
     122         [ -  + ]:         16 :                 if (r < 0)
     123                 :          0 :                         return r;
     124                 :            : 
     125                 :         16 :                 r = parse_uid(t+1, &end);
     126         [ -  + ]:         16 :                 if (r < 0)
     127                 :          0 :                         return r;
     128                 :            : 
     129         [ -  + ]:         16 :                 if (end < start)
     130                 :          0 :                         return -EINVAL;
     131                 :            : 
     132                 :         16 :                 nr = end - start + 1;
     133                 :            :         } else {
     134                 :         12 :                 r = parse_uid(s, &start);
     135         [ -  + ]:         12 :                 if (r < 0)
     136                 :          0 :                         return r;
     137                 :            : 
     138                 :         12 :                 nr = 1;
     139                 :            :         }
     140                 :            : 
     141                 :         28 :         return uid_range_add(p, n, start, nr);
     142                 :            : }
     143                 :            : 
     144                 :         16 : int uid_range_next_lower(const UidRange *p, unsigned n, uid_t *uid) {
     145                 :         16 :         uid_t closest = UID_INVALID, candidate;
     146                 :            :         unsigned i;
     147                 :            : 
     148         [ -  + ]:         16 :         assert(p);
     149         [ -  + ]:         16 :         assert(uid);
     150                 :            : 
     151                 :         16 :         candidate = *uid - 1;
     152                 :            : 
     153         [ +  + ]:         24 :         for (i = 0; i < n; i++) {
     154                 :            :                 uid_t begin, end;
     155                 :            : 
     156                 :         16 :                 begin = p[i].start;
     157                 :         16 :                 end = p[i].start + p[i].nr - 1;
     158                 :            : 
     159   [ +  +  +  + ]:         16 :                 if (candidate >= begin && candidate <= end) {
     160                 :          8 :                         *uid = candidate;
     161                 :          8 :                         return 1;
     162                 :            :                 }
     163                 :            : 
     164         [ +  + ]:          8 :                 if (end < candidate)
     165                 :          4 :                         closest = end;
     166                 :            :         }
     167                 :            : 
     168         [ +  + ]:          8 :         if (closest == UID_INVALID)
     169                 :          4 :                 return -EBUSY;
     170                 :            : 
     171                 :          4 :         *uid = closest;
     172                 :          4 :         return 1;
     173                 :            : }
     174                 :            : 
     175                 :         16 : bool uid_range_contains(const UidRange *p, unsigned n, uid_t uid) {
     176                 :            :         unsigned i;
     177                 :            : 
     178         [ -  + ]:         16 :         assert(p);
     179         [ -  + ]:         16 :         assert(uid);
     180                 :            : 
     181         [ +  + ]:         24 :         for (i = 0; i < n; i++)
     182   [ +  +  +  + ]:         16 :                 if (uid >= p[i].start && uid < p[i].start + p[i].nr)
     183                 :          8 :                         return true;
     184                 :            : 
     185                 :          8 :         return false;
     186                 :            : }

Generated by: LCOV version 1.14