LCOV - code coverage report
Current view: top level - shared - serialize.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 88 114 77.2 %
Date: 2019-08-23 13:36:53 Functions: 9 11 81.8 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 53 110 48.2 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <sys/mman.h>
       4                 :            : 
       5                 :            : #include "alloc-util.h"
       6                 :            : #include "env-util.h"
       7                 :            : #include "escape.h"
       8                 :            : #include "fileio.h"
       9                 :            : #include "missing.h"
      10                 :            : #include "parse-util.h"
      11                 :            : #include "process-util.h"
      12                 :            : #include "serialize.h"
      13                 :            : #include "strv.h"
      14                 :            : #include "tmpfile-util.h"
      15                 :            : 
      16                 :        108 : int serialize_item(FILE *f, const char *key, const char *value) {
      17         [ -  + ]:        108 :         assert(f);
      18         [ -  + ]:        108 :         assert(key);
      19                 :            : 
      20         [ +  + ]:        108 :         if (!value)
      21                 :          4 :                 return 0;
      22                 :            : 
      23                 :            :         /* Make sure that anything we serialize we can also read back again with read_line() with a maximum line size
      24                 :            :          * of LONG_LINE_MAX. This is a safety net only. All code calling us should filter this out earlier anyway. */
      25         [ +  + ]:        104 :         if (strlen(key) + 1 + strlen(value) + 1 > LONG_LINE_MAX) {
      26         [ +  - ]:         28 :                 log_warning("Attempted to serialize overly long item '%s', refusing.", key);
      27                 :         28 :                 return -EINVAL;
      28                 :            :         }
      29                 :            : 
      30                 :         76 :         fputs(key, f);
      31                 :         76 :         fputc('=', f);
      32                 :         76 :         fputs(value, f);
      33                 :         76 :         fputc('\n', f);
      34                 :            : 
      35                 :         76 :         return 1;
      36                 :            : }
      37                 :            : 
      38                 :         88 : int serialize_item_escaped(FILE *f, const char *key, const char *value) {
      39                 :         88 :         _cleanup_free_ char *c = NULL;
      40                 :            : 
      41         [ -  + ]:         88 :         assert(f);
      42         [ -  + ]:         88 :         assert(key);
      43                 :            : 
      44         [ +  + ]:         88 :         if (!value)
      45                 :          4 :                 return 0;
      46                 :            : 
      47                 :         84 :         c = cescape(value);
      48         [ -  + ]:         84 :         if (!c)
      49                 :          0 :                 return log_oom();
      50                 :            : 
      51                 :         84 :         return serialize_item(f, key, c);
      52                 :            : }
      53                 :            : 
      54                 :          8 : int serialize_item_format(FILE *f, const char *key, const char *format, ...) {
      55                 :            :         char buf[LONG_LINE_MAX];
      56                 :            :         va_list ap;
      57                 :            :         int k;
      58                 :            : 
      59         [ -  + ]:          8 :         assert(f);
      60         [ -  + ]:          8 :         assert(key);
      61         [ -  + ]:          8 :         assert(format);
      62                 :            : 
      63                 :          8 :         va_start(ap, format);
      64                 :          8 :         k = vsnprintf(buf, sizeof(buf), format, ap);
      65                 :          8 :         va_end(ap);
      66                 :            : 
      67   [ +  -  +  -  :          8 :         if (k < 0 || (size_t) k >= sizeof(buf) || strlen(key) + 1 + k + 1 > LONG_LINE_MAX) {
                   -  + ]
      68         [ #  # ]:          0 :                 log_warning("Attempted to serialize overly long item '%s', refusing.", key);
      69                 :          0 :                 return -EINVAL;
      70                 :            :         }
      71                 :            : 
      72                 :          8 :         fputs(key, f);
      73                 :          8 :         fputc('=', f);
      74                 :          8 :         fputs(buf, f);
      75                 :          8 :         fputc('\n', f);
      76                 :            : 
      77                 :          8 :         return 1;
      78                 :            : }
      79                 :            : 
      80                 :          0 : int serialize_fd(FILE *f, FDSet *fds, const char *key, int fd) {
      81                 :            :         int copy;
      82                 :            : 
      83         [ #  # ]:          0 :         assert(f);
      84         [ #  # ]:          0 :         assert(key);
      85                 :            : 
      86         [ #  # ]:          0 :         if (fd < 0)
      87                 :          0 :                 return 0;
      88                 :            : 
      89                 :          0 :         copy = fdset_put_dup(fds, fd);
      90         [ #  # ]:          0 :         if (copy < 0)
      91         [ #  # ]:          0 :                 return log_error_errno(copy, "Failed to add file descriptor to serialization set: %m");
      92                 :            : 
      93                 :          0 :         return serialize_item_format(f, key, "%i", copy);
      94                 :            : }
      95                 :            : 
      96                 :         12 : int serialize_usec(FILE *f, const char *key, usec_t usec) {
      97         [ -  + ]:         12 :         assert(f);
      98         [ -  + ]:         12 :         assert(key);
      99                 :            : 
     100         [ +  + ]:         12 :         if (usec == USEC_INFINITY)
     101                 :          4 :                 return 0;
     102                 :            : 
     103                 :          8 :         return serialize_item_format(f, key, USEC_FMT, usec);
     104                 :            : }
     105                 :            : 
     106                 :          0 : int serialize_dual_timestamp(FILE *f, const char *name, const dual_timestamp *t) {
     107         [ #  # ]:          0 :         assert(f);
     108         [ #  # ]:          0 :         assert(name);
     109         [ #  # ]:          0 :         assert(t);
     110                 :            : 
     111         [ #  # ]:          0 :         if (!dual_timestamp_is_set(t))
     112                 :          0 :                 return 0;
     113                 :            : 
     114                 :          0 :         return serialize_item_format(f, name, USEC_FMT " " USEC_FMT, t->realtime, t->monotonic);
     115                 :            : }
     116                 :            : 
     117                 :         20 : int serialize_strv(FILE *f, const char *key, char **l) {
     118                 :         20 :         int ret = 0, r;
     119                 :            :         char **i;
     120                 :            : 
     121                 :            :         /* Returns the first error, or positive if anything was serialized, 0 otherwise. */
     122                 :            : 
     123   [ +  +  +  + ]:         84 :         STRV_FOREACH(i, l) {
     124                 :         64 :                 r = serialize_item_escaped(f, key, *i);
     125   [ +  -  +  +  :         64 :                 if ((ret >= 0 && r < 0) ||
                   +  + ]
     126         [ +  - ]:          8 :                     (ret == 0 && r > 0))
     127                 :         12 :                         ret = r;
     128                 :            :         }
     129                 :            : 
     130                 :         20 :         return ret;
     131                 :            : }
     132                 :            : 
     133                 :          8 : int deserialize_usec(const char *value, usec_t *ret) {
     134                 :            :         int r;
     135                 :            : 
     136         [ -  + ]:          8 :         assert(value);
     137                 :            : 
     138                 :          8 :         r = safe_atou64(value, ret);
     139         [ -  + ]:          8 :         if (r < 0)
     140         [ #  # ]:          0 :                 return log_debug_errno(r, "Failed to parse usec value \"%s\": %m", value);
     141                 :            : 
     142                 :          8 :         return 0;
     143                 :            : }
     144                 :            : 
     145                 :         28 : int deserialize_dual_timestamp(const char *value, dual_timestamp *t) {
     146                 :            :         uint64_t a, b;
     147                 :            :         int r, pos;
     148                 :            : 
     149         [ -  + ]:         28 :         assert(value);
     150         [ -  + ]:         28 :         assert(t);
     151                 :            : 
     152                 :         28 :         pos = strspn(value, WHITESPACE);
     153         [ +  + ]:         28 :         if (value[pos] == '-')
     154                 :          4 :                 return -EINVAL;
     155                 :         24 :         pos += strspn(value + pos, DIGITS);
     156                 :         24 :         pos += strspn(value + pos, WHITESPACE);
     157         [ +  + ]:         24 :         if (value[pos] == '-')
     158                 :          4 :                 return -EINVAL;
     159                 :            : 
     160                 :         20 :         r = sscanf(value, "%" PRIu64 "%" PRIu64 "%n", &a, &b, &pos);
     161         [ +  + ]:         20 :         if (r != 2)
     162         [ -  + ]:          4 :                 return log_debug_errno(SYNTHETIC_ERRNO(EINVAL),
     163                 :            :                                        "Failed to parse dual timestamp value \"%s\".",
     164                 :            :                                        value);
     165                 :            : 
     166         [ +  + ]:         16 :         if (value[pos] != '\0')
     167                 :            :                 /* trailing garbage */
     168                 :          4 :                 return -EINVAL;
     169                 :            : 
     170                 :         12 :         t->realtime = a;
     171                 :         12 :         t->monotonic = b;
     172                 :            : 
     173                 :         12 :         return 0;
     174                 :            : }
     175                 :            : 
     176                 :         68 : int deserialize_environment(const char *value, char ***list) {
     177                 :         68 :         _cleanup_free_ char *unescaped = NULL;
     178                 :            :         int r;
     179                 :            : 
     180         [ -  + ]:         68 :         assert(value);
     181         [ -  + ]:         68 :         assert(list);
     182                 :            : 
     183                 :            :         /* Changes the *environment strv inline. */
     184                 :            : 
     185                 :         68 :         r = cunescape(value, 0, &unescaped);
     186         [ +  + ]:         68 :         if (r < 0)
     187         [ +  - ]:          8 :                 return log_error_errno(r, "Failed to unescape: %m");
     188                 :            : 
     189                 :         60 :         r = strv_env_replace(list, unescaped);
     190         [ -  + ]:         60 :         if (r < 0)
     191         [ #  # ]:          0 :                 return log_error_errno(r, "Failed to append environment variable: %m");
     192                 :            : 
     193                 :         60 :         unescaped = NULL; /* now part of 'list' */
     194                 :         60 :         return 0;
     195                 :            : }
     196                 :            : 
     197                 :         88 : int open_serialization_fd(const char *ident) {
     198                 :            :         int fd;
     199                 :            : 
     200                 :         88 :         fd = memfd_create(ident, MFD_CLOEXEC);
     201         [ -  + ]:         88 :         if (fd < 0) {
     202                 :            :                 const char *path;
     203                 :            : 
     204         [ #  # ]:          0 :                 path = getpid_cached() == 1 ? "/run/systemd" : "/tmp";
     205                 :          0 :                 fd = open_tmpfile_unlinkable(path, O_RDWR|O_CLOEXEC);
     206         [ #  # ]:          0 :                 if (fd < 0)
     207                 :          0 :                         return fd;
     208                 :            : 
     209         [ #  # ]:          0 :                 log_debug("Serializing %s to %s.", ident, path);
     210                 :            :         } else
     211         [ +  - ]:         88 :                 log_debug("Serializing %s to memfd.", ident);
     212                 :            : 
     213                 :         88 :         return fd;
     214                 :            : }

Generated by: LCOV version 1.14