LCOV - code coverage report
Current view: top level - libsystemd/sd-id128 - id128-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 72 96 75.0 %
Date: 2019-08-23 13:36:53 Functions: 7 8 87.5 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 53 89 59.6 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <fcntl.h>
       5                 :            : #include <unistd.h>
       6                 :            : 
       7                 :            : #include "fd-util.h"
       8                 :            : #include "fs-util.h"
       9                 :            : #include "hexdecoct.h"
      10                 :            : #include "id128-util.h"
      11                 :            : #include "io-util.h"
      12                 :            : #include "stdio-util.h"
      13                 :            : 
      14                 :         12 : char *id128_to_uuid_string(sd_id128_t id, char s[37]) {
      15                 :         12 :         unsigned n, k = 0;
      16                 :            : 
      17         [ -  + ]:         12 :         assert(s);
      18                 :            : 
      19                 :            :         /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
      20                 :            : 
      21         [ +  + ]:        204 :         for (n = 0; n < 16; n++) {
      22                 :            : 
      23   [ +  +  +  + ]:        192 :                 if (IN_SET(n, 4, 6, 8, 10))
      24                 :         48 :                         s[k++] = '-';
      25                 :            : 
      26                 :        192 :                 s[k++] = hexchar(id.bytes[n] >> 4);
      27                 :        192 :                 s[k++] = hexchar(id.bytes[n] & 0xF);
      28                 :            :         }
      29                 :            : 
      30         [ -  + ]:         12 :         assert(k == 36);
      31                 :            : 
      32                 :         12 :         s[k] = 0;
      33                 :            : 
      34                 :         12 :         return s;
      35                 :            : }
      36                 :            : 
      37                 :       7084 : bool id128_is_valid(const char *s) {
      38                 :            :         size_t i, l;
      39                 :            : 
      40         [ -  + ]:       7084 :         assert(s);
      41                 :            : 
      42                 :       7084 :         l = strlen(s);
      43         [ +  + ]:       7084 :         if (l == 32) {
      44                 :            : 
      45                 :            :                 /* Plain formatted 128bit hex string */
      46                 :            : 
      47         [ +  + ]:     176880 :                 for (i = 0; i < l; i++) {
      48                 :     171520 :                         char c = s[i];
      49                 :            : 
      50   [ +  -  +  +  :     171520 :                         if (!(c >= '0' && c <= '9') &&
                   +  - ]
      51   [ -  +  #  # ]:      59764 :                             !(c >= 'a' && c <= 'z') &&
      52         [ #  # ]:          0 :                             !(c >= 'A' && c <= 'Z'))
      53                 :          0 :                                 return false;
      54                 :            :                 }
      55                 :            : 
      56         [ +  + ]:       1724 :         } else if (l == 36) {
      57                 :            : 
      58                 :            :                 /* Formatted UUID */
      59                 :            : 
      60         [ +  + ]:        148 :                 for (i = 0; i < l; i++) {
      61                 :        144 :                         char c = s[i];
      62                 :            : 
      63   [ +  +  +  + ]:        144 :                         if (IN_SET(i, 8, 13, 18, 23)) {
      64         [ -  + ]:         16 :                                 if (c != '-')
      65                 :          0 :                                         return false;
      66                 :            :                         } else {
      67   [ +  -  +  +  :        128 :                                 if (!(c >= '0' && c <= '9') &&
                   +  - ]
      68   [ -  +  #  # ]:         24 :                                     !(c >= 'a' && c <= 'z') &&
      69         [ #  # ]:          0 :                                     !(c >= 'A' && c <= 'Z'))
      70                 :          0 :                                         return false;
      71                 :            :                         }
      72                 :            :                 }
      73                 :            : 
      74                 :            :         } else
      75                 :       1720 :                 return false;
      76                 :            : 
      77                 :       5364 :         return true;
      78                 :            : }
      79                 :            : 
      80                 :        204 : int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
      81                 :            :         char buffer[36 + 2];
      82                 :            :         ssize_t l;
      83                 :            : 
      84         [ -  + ]:        204 :         assert(fd >= 0);
      85         [ -  + ]:        204 :         assert(f < _ID128_FORMAT_MAX);
      86                 :            : 
      87                 :            :         /* Reads an 128bit ID from a file, which may either be in plain format (32 hex digits), or in UUID format, both
      88                 :            :          * optionally followed by a newline and nothing else. ID files should really be newline terminated, but if they
      89                 :            :          * aren't that's OK too, following the rule of "Be conservative in what you send, be liberal in what you
      90                 :            :          * accept". */
      91                 :            : 
      92                 :        204 :         l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
      93         [ -  + ]:        204 :         if (l < 0)
      94                 :          0 :                 return (int) l;
      95         [ -  + ]:        204 :         if (l == 0) /* empty? */
      96                 :          0 :                 return -ENOMEDIUM;
      97                 :            : 
      98   [ +  +  +  +  :        204 :         switch (l) {
                      - ]
      99                 :            : 
     100                 :         88 :         case 33: /* plain UUID with trailing newline */
     101         [ -  + ]:         88 :                 if (buffer[32] != '\n')
     102                 :          0 :                         return -EINVAL;
     103                 :            : 
     104                 :            :                 _fallthrough_;
     105                 :            :         case 32: /* plain UUID without trailing newline */
     106         [ +  + ]:         96 :                 if (f == ID128_UUID)
     107                 :          8 :                         return -EINVAL;
     108                 :            : 
     109                 :         88 :                 buffer[32] = 0;
     110                 :         88 :                 break;
     111                 :            : 
     112                 :        100 :         case 37: /* RFC UUID with trailing newline */
     113         [ -  + ]:        100 :                 if (buffer[36] != '\n')
     114                 :          0 :                         return -EINVAL;
     115                 :            : 
     116                 :            :                 _fallthrough_;
     117                 :            :         case 36: /* RFC UUID without trailing newline */
     118         [ +  + ]:        108 :                 if (f == ID128_PLAIN)
     119                 :          8 :                         return -EINVAL;
     120                 :            : 
     121                 :        100 :                 buffer[36] = 0;
     122                 :        100 :                 break;
     123                 :            : 
     124                 :          0 :         default:
     125                 :          0 :                 return -EINVAL;
     126                 :            :         }
     127                 :            : 
     128                 :        188 :         return sd_id128_from_string(buffer, ret);
     129                 :            : }
     130                 :            : 
     131                 :        160 : int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
     132                 :        160 :         _cleanup_close_ int fd = -1;
     133                 :            : 
     134                 :        160 :         fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
     135         [ -  + ]:        160 :         if (fd < 0)
     136                 :          0 :                 return -errno;
     137                 :            : 
     138                 :        160 :         return id128_read_fd(fd, f, ret);
     139                 :            : }
     140                 :            : 
     141                 :          8 : int id128_write_fd(int fd, Id128Format f, sd_id128_t id, bool do_sync) {
     142                 :            :         char buffer[36 + 2];
     143                 :            :         size_t sz;
     144                 :            :         int r;
     145                 :            : 
     146         [ -  + ]:          8 :         assert(fd >= 0);
     147         [ -  + ]:          8 :         assert(f < _ID128_FORMAT_MAX);
     148                 :            : 
     149         [ +  + ]:          8 :         if (f != ID128_UUID) {
     150                 :          4 :                 sd_id128_to_string(id, buffer);
     151                 :          4 :                 buffer[32] = '\n';
     152                 :          4 :                 sz = 33;
     153                 :            :         } else {
     154                 :          4 :                 id128_to_uuid_string(id, buffer);
     155                 :          4 :                 buffer[36] = '\n';
     156                 :          4 :                 sz = 37;
     157                 :            :         }
     158                 :            : 
     159                 :          8 :         r = loop_write(fd, buffer, sz, false);
     160         [ -  + ]:          8 :         if (r < 0)
     161                 :          0 :                 return r;
     162                 :            : 
     163         [ -  + ]:          8 :         if (do_sync) {
     164         [ #  # ]:          0 :                 if (fsync(fd) < 0)
     165                 :          0 :                         return -errno;
     166                 :            : 
     167                 :          0 :                 r = fsync_directory_of_file(fd);
     168         [ #  # ]:          0 :                 if (r < 0)
     169                 :          0 :                         return r;
     170                 :            :         }
     171                 :            : 
     172                 :          8 :         return 0;
     173                 :            : }
     174                 :            : 
     175                 :          0 : int id128_write(const char *p, Id128Format f, sd_id128_t id, bool do_sync) {
     176                 :          0 :         _cleanup_close_ int fd = -1;
     177                 :            : 
     178                 :          0 :         fd = open(p, O_WRONLY|O_CREAT|O_CLOEXEC|O_NOCTTY|O_TRUNC, 0444);
     179         [ #  # ]:          0 :         if (fd < 0)
     180                 :          0 :                 return -errno;
     181                 :            : 
     182                 :          0 :         return id128_write_fd(fd, f, id, do_sync);
     183                 :            : }
     184                 :            : 
     185                 :      20576 : void id128_hash_func(const sd_id128_t *p, struct siphash *state) {
     186                 :      20576 :         siphash24_compress(p, sizeof(sd_id128_t), state);
     187                 :      20576 : }
     188                 :            : 
     189                 :      10350 : int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) {
     190                 :      10350 :         return memcmp(a, b, 16);
     191                 :            : }
     192                 :            : 
     193                 :            : DEFINE_HASH_OPS(id128_hash_ops, sd_id128_t, id128_hash_func, id128_compare_func);

Generated by: LCOV version 1.14