LCOV - code coverage report
Current view: top level - libsystemd/sd-id128 - id128-util.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 72 96 75.0 %
Date: 2019-08-22 15:41:25 Functions: 7 8 87.5 %

          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           3 : char *id128_to_uuid_string(sd_id128_t id, char s[37]) {
      15           3 :         unsigned n, k = 0;
      16             : 
      17           3 :         assert(s);
      18             : 
      19             :         /* Similar to sd_id128_to_string() but formats the result as UUID instead of plain hex chars */
      20             : 
      21          51 :         for (n = 0; n < 16; n++) {
      22             : 
      23          48 :                 if (IN_SET(n, 4, 6, 8, 10))
      24          12 :                         s[k++] = '-';
      25             : 
      26          48 :                 s[k++] = hexchar(id.bytes[n] >> 4);
      27          48 :                 s[k++] = hexchar(id.bytes[n] & 0xF);
      28             :         }
      29             : 
      30           3 :         assert(k == 36);
      31             : 
      32           3 :         s[k] = 0;
      33             : 
      34           3 :         return s;
      35             : }
      36             : 
      37        1771 : bool id128_is_valid(const char *s) {
      38             :         size_t i, l;
      39             : 
      40        1771 :         assert(s);
      41             : 
      42        1771 :         l = strlen(s);
      43        1771 :         if (l == 32) {
      44             : 
      45             :                 /* Plain formatted 128bit hex string */
      46             : 
      47       44220 :                 for (i = 0; i < l; i++) {
      48       42880 :                         char c = s[i];
      49             : 
      50       42880 :                         if (!(c >= '0' && c <= '9') &&
      51       14941 :                             !(c >= 'a' && c <= 'z') &&
      52           0 :                             !(c >= 'A' && c <= 'Z'))
      53           0 :                                 return false;
      54             :                 }
      55             : 
      56         431 :         } else if (l == 36) {
      57             : 
      58             :                 /* Formatted UUID */
      59             : 
      60          37 :                 for (i = 0; i < l; i++) {
      61          36 :                         char c = s[i];
      62             : 
      63          36 :                         if (IN_SET(i, 8, 13, 18, 23)) {
      64           4 :                                 if (c != '-')
      65           0 :                                         return false;
      66             :                         } else {
      67          32 :                                 if (!(c >= '0' && c <= '9') &&
      68           6 :                                     !(c >= 'a' && c <= 'z') &&
      69           0 :                                     !(c >= 'A' && c <= 'Z'))
      70           0 :                                         return false;
      71             :                         }
      72             :                 }
      73             : 
      74             :         } else
      75         430 :                 return false;
      76             : 
      77        1341 :         return true;
      78             : }
      79             : 
      80          51 : int id128_read_fd(int fd, Id128Format f, sd_id128_t *ret) {
      81             :         char buffer[36 + 2];
      82             :         ssize_t l;
      83             : 
      84          51 :         assert(fd >= 0);
      85          51 :         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          51 :         l = loop_read(fd, buffer, sizeof(buffer), false); /* we expect a short read of either 32/33 or 36/37 chars */
      93          51 :         if (l < 0)
      94           0 :                 return (int) l;
      95          51 :         if (l == 0) /* empty? */
      96           0 :                 return -ENOMEDIUM;
      97             : 
      98          51 :         switch (l) {
      99             : 
     100          22 :         case 33: /* plain UUID with trailing newline */
     101          22 :                 if (buffer[32] != '\n')
     102           0 :                         return -EINVAL;
     103             : 
     104             :                 _fallthrough_;
     105             :         case 32: /* plain UUID without trailing newline */
     106          24 :                 if (f == ID128_UUID)
     107           2 :                         return -EINVAL;
     108             : 
     109          22 :                 buffer[32] = 0;
     110          22 :                 break;
     111             : 
     112          25 :         case 37: /* RFC UUID with trailing newline */
     113          25 :                 if (buffer[36] != '\n')
     114           0 :                         return -EINVAL;
     115             : 
     116             :                 _fallthrough_;
     117             :         case 36: /* RFC UUID without trailing newline */
     118          27 :                 if (f == ID128_PLAIN)
     119           2 :                         return -EINVAL;
     120             : 
     121          25 :                 buffer[36] = 0;
     122          25 :                 break;
     123             : 
     124           0 :         default:
     125           0 :                 return -EINVAL;
     126             :         }
     127             : 
     128          47 :         return sd_id128_from_string(buffer, ret);
     129             : }
     130             : 
     131          40 : int id128_read(const char *p, Id128Format f, sd_id128_t *ret) {
     132          40 :         _cleanup_close_ int fd = -1;
     133             : 
     134          40 :         fd = open(p, O_RDONLY|O_CLOEXEC|O_NOCTTY);
     135          40 :         if (fd < 0)
     136           0 :                 return -errno;
     137             : 
     138          40 :         return id128_read_fd(fd, f, ret);
     139             : }
     140             : 
     141           2 : 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           2 :         assert(fd >= 0);
     147           2 :         assert(f < _ID128_FORMAT_MAX);
     148             : 
     149           2 :         if (f != ID128_UUID) {
     150           1 :                 sd_id128_to_string(id, buffer);
     151           1 :                 buffer[32] = '\n';
     152           1 :                 sz = 33;
     153             :         } else {
     154           1 :                 id128_to_uuid_string(id, buffer);
     155           1 :                 buffer[36] = '\n';
     156           1 :                 sz = 37;
     157             :         }
     158             : 
     159           2 :         r = loop_write(fd, buffer, sz, false);
     160           2 :         if (r < 0)
     161           0 :                 return r;
     162             : 
     163           2 :         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           2 :         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        5100 : void id128_hash_func(const sd_id128_t *p, struct siphash *state) {
     186        5100 :         siphash24_compress(p, sizeof(sd_id128_t), state);
     187        5100 : }
     188             : 
     189        2553 : int id128_compare_func(const sd_id128_t *a, const sd_id128_t *b) {
     190        2553 :         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