LCOV - code coverage report
Current view: top level - basic - io-util.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 96 178 53.9 %
Date: 2019-08-23 13:36:53 Functions: 10 19 52.6 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 55 122 45.1 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <limits.h>
       5                 :            : #include <poll.h>
       6                 :            : #include <stdio.h>
       7                 :            : #include <time.h>
       8                 :            : #include <unistd.h>
       9                 :            : 
      10                 :            : #include "io-util.h"
      11                 :            : #include "string-util.h"
      12                 :            : #include "time-util.h"
      13                 :            : 
      14                 :         84 : int flush_fd(int fd) {
      15                 :         84 :         struct pollfd pollfd = {
      16                 :            :                 .fd = fd,
      17                 :            :                 .events = POLLIN,
      18                 :            :         };
      19                 :         84 :         int count = 0;
      20                 :            : 
      21                 :            :         /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
      22                 :            :          * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
      23                 :            :          * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
      24                 :            :          * was set to non-blocking too. */
      25                 :            : 
      26                 :         56 :         for (;;) {
      27                 :            :                 char buf[LINE_MAX];
      28                 :            :                 ssize_t l;
      29                 :            :                 int r;
      30                 :            : 
      31                 :        140 :                 r = poll(&pollfd, 1, 0);
      32         [ -  + ]:        140 :                 if (r < 0) {
      33         [ #  # ]:          0 :                         if (errno == EINTR)
      34                 :          0 :                                 continue;
      35                 :            : 
      36                 :         84 :                         return -errno;
      37                 :            : 
      38         [ +  + ]:        140 :                 } else if (r == 0)
      39                 :         84 :                         return count;
      40                 :            : 
      41                 :         56 :                 l = read(fd, buf, sizeof(buf));
      42         [ -  + ]:         56 :                 if (l < 0) {
      43                 :            : 
      44         [ #  # ]:          0 :                         if (errno == EINTR)
      45                 :          0 :                                 continue;
      46                 :            : 
      47         [ #  # ]:          0 :                         if (errno == EAGAIN)
      48                 :          0 :                                 return count;
      49                 :            : 
      50                 :          0 :                         return -errno;
      51         [ -  + ]:         56 :                 } else if (l == 0)
      52                 :          0 :                         return count;
      53                 :            : 
      54                 :         56 :                 count += (int) l;
      55                 :            :         }
      56                 :            : }
      57                 :            : 
      58                 :       3034 : ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
      59                 :       3034 :         uint8_t *p = buf;
      60                 :       3034 :         ssize_t n = 0;
      61                 :            : 
      62         [ -  + ]:       3034 :         assert(fd >= 0);
      63         [ -  + ]:       3034 :         assert(buf);
      64                 :            : 
      65                 :            :         /* If called with nbytes == 0, let's call read() at least
      66                 :            :          * once, to validate the operation */
      67                 :            : 
      68         [ -  + ]:       3034 :         if (nbytes > (size_t) SSIZE_MAX)
      69                 :          0 :                 return -EINVAL;
      70                 :            : 
      71                 :            :         do {
      72                 :            :                 ssize_t k;
      73                 :            : 
      74                 :       3238 :                 k = read(fd, p, nbytes);
      75         [ -  + ]:       3238 :                 if (k < 0) {
      76         [ #  # ]:          0 :                         if (errno == EINTR)
      77                 :          0 :                                 continue;
      78                 :            : 
      79   [ #  #  #  # ]:          0 :                         if (errno == EAGAIN && do_poll) {
      80                 :            : 
      81                 :            :                                 /* We knowingly ignore any return value here,
      82                 :            :                                  * and expect that any error/EOF is reported
      83                 :            :                                  * via read() */
      84                 :            : 
      85                 :          0 :                                 (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
      86                 :          0 :                                 continue;
      87                 :            :                         }
      88                 :            : 
      89         [ #  # ]:          0 :                         return n > 0 ? n : -errno;
      90                 :            :                 }
      91                 :            : 
      92         [ +  + ]:       3238 :                 if (k == 0)
      93                 :        204 :                         return n;
      94                 :            : 
      95         [ -  + ]:       3034 :                 assert((size_t) k <= nbytes);
      96                 :            : 
      97                 :       3034 :                 p += k;
      98                 :       3034 :                 nbytes -= k;
      99                 :       3034 :                 n += k;
     100         [ +  + ]:       3034 :         } while (nbytes > 0);
     101                 :            : 
     102                 :       2830 :         return n;
     103                 :            : }
     104                 :            : 
     105                 :       2830 : int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
     106                 :            :         ssize_t n;
     107                 :            : 
     108                 :       2830 :         n = loop_read(fd, buf, nbytes, do_poll);
     109         [ -  + ]:       2830 :         if (n < 0)
     110                 :          0 :                 return (int) n;
     111         [ -  + ]:       2830 :         if ((size_t) n != nbytes)
     112                 :          0 :                 return -EIO;
     113                 :            : 
     114                 :       2830 :         return 0;
     115                 :            : }
     116                 :            : 
     117                 :        208 : int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
     118                 :        208 :         const uint8_t *p = buf;
     119                 :            : 
     120         [ -  + ]:        208 :         assert(fd >= 0);
     121         [ -  + ]:        208 :         assert(buf);
     122                 :            : 
     123         [ -  + ]:        208 :         if (_unlikely_(nbytes > (size_t) SSIZE_MAX))
     124                 :          0 :                 return -EINVAL;
     125                 :            : 
     126                 :            :         do {
     127                 :            :                 ssize_t k;
     128                 :            : 
     129                 :        208 :                 k = write(fd, p, nbytes);
     130         [ -  + ]:        208 :                 if (k < 0) {
     131         [ #  # ]:          0 :                         if (errno == EINTR)
     132                 :          0 :                                 continue;
     133                 :            : 
     134   [ #  #  #  # ]:          0 :                         if (errno == EAGAIN && do_poll) {
     135                 :            :                                 /* We knowingly ignore any return value here,
     136                 :            :                                  * and expect that any error/EOF is reported
     137                 :            :                                  * via write() */
     138                 :            : 
     139                 :          0 :                                 (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
     140                 :          0 :                                 continue;
     141                 :            :                         }
     142                 :            : 
     143                 :          0 :                         return -errno;
     144                 :            :                 }
     145                 :            : 
     146   [ +  -  -  + ]:        208 :                 if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
     147                 :          0 :                         return -EIO;
     148                 :            : 
     149         [ -  + ]:        208 :                 assert((size_t) k <= nbytes);
     150                 :            : 
     151                 :        208 :                 p += k;
     152                 :        208 :                 nbytes -= k;
     153         [ -  + ]:        208 :         } while (nbytes > 0);
     154                 :            : 
     155                 :        208 :         return 0;
     156                 :            : }
     157                 :            : 
     158                 :          0 : int pipe_eof(int fd) {
     159                 :          0 :         struct pollfd pollfd = {
     160                 :            :                 .fd = fd,
     161                 :            :                 .events = POLLIN|POLLHUP,
     162                 :            :         };
     163                 :            : 
     164                 :            :         int r;
     165                 :            : 
     166                 :          0 :         r = poll(&pollfd, 1, 0);
     167         [ #  # ]:          0 :         if (r < 0)
     168                 :          0 :                 return -errno;
     169                 :            : 
     170         [ #  # ]:          0 :         if (r == 0)
     171                 :          0 :                 return 0;
     172                 :            : 
     173                 :          0 :         return pollfd.revents & POLLHUP;
     174                 :            : }
     175                 :            : 
     176                 :         28 : int fd_wait_for_event(int fd, int event, usec_t t) {
     177                 :            : 
     178                 :         28 :         struct pollfd pollfd = {
     179                 :            :                 .fd = fd,
     180                 :            :                 .events = event,
     181                 :            :         };
     182                 :            : 
     183                 :            :         struct timespec ts;
     184                 :            :         int r;
     185                 :            : 
     186         [ +  - ]:         28 :         r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
     187         [ -  + ]:         28 :         if (r < 0)
     188                 :          0 :                 return -errno;
     189         [ -  + ]:         28 :         if (r == 0)
     190                 :          0 :                 return 0;
     191                 :            : 
     192                 :         28 :         return pollfd.revents;
     193                 :            : }
     194                 :            : 
     195                 :        232 : static size_t nul_length(const uint8_t *p, size_t sz) {
     196                 :        232 :         size_t n = 0;
     197                 :            : 
     198         [ +  + ]:        440 :         while (sz > 0) {
     199         [ +  + ]:        420 :                 if (*p != 0)
     200                 :        212 :                         break;
     201                 :            : 
     202                 :        208 :                 n++;
     203                 :        208 :                 p++;
     204                 :        208 :                 sz--;
     205                 :            :         }
     206                 :            : 
     207                 :        232 :         return n;
     208                 :            : }
     209                 :            : 
     210                 :         20 : ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
     211                 :            :         const uint8_t *q, *w, *e;
     212                 :            :         ssize_t l;
     213                 :            : 
     214                 :         20 :         q = w = p;
     215                 :         20 :         e = q + sz;
     216         [ +  + ]:        252 :         while (q < e) {
     217                 :            :                 size_t n;
     218                 :            : 
     219                 :        232 :                 n = nul_length(q, e - q);
     220                 :            : 
     221                 :            :                 /* If there are more than the specified run length of
     222                 :            :                  * NUL bytes, or if this is the beginning or the end
     223                 :            :                  * of the buffer, then seek instead of write */
     224   [ +  +  +  + ]:        232 :                 if ((n > run_length) ||
     225   [ +  +  +  + ]:        216 :                     (n > 0 && q == p) ||
     226         [ +  + ]:         28 :                     (n > 0 && q + n >= e)) {
     227         [ +  + ]:         36 :                         if (q > w) {
     228                 :         24 :                                 l = write(fd, w, q - w);
     229         [ -  + ]:         24 :                                 if (l < 0)
     230                 :          0 :                                         return -errno;
     231         [ -  + ]:         24 :                                 if (l != q -w)
     232                 :          0 :                                         return -EIO;
     233                 :            :                         }
     234                 :            : 
     235         [ -  + ]:         36 :                         if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
     236                 :          0 :                                 return -errno;
     237                 :            : 
     238                 :         36 :                         q += n;
     239                 :         36 :                         w = q;
     240         [ +  + ]:        196 :                 } else if (n > 0)
     241                 :         20 :                         q += n;
     242                 :            :                 else
     243                 :        176 :                         q++;
     244                 :            :         }
     245                 :            : 
     246         [ -  + ]:         20 :         if (q > w) {
     247                 :          0 :                 l = write(fd, w, q - w);
     248         [ #  # ]:          0 :                 if (l < 0)
     249                 :          0 :                         return -errno;
     250         [ #  # ]:          0 :                 if (l != q - w)
     251                 :          0 :                         return -EIO;
     252                 :            :         }
     253                 :            : 
     254                 :         20 :         return q - (const uint8_t*) p;
     255                 :            : }
     256                 :            : 
     257                 :          0 : char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) {
     258                 :            :         char *x;
     259                 :            : 
     260                 :          0 :         x = strjoin(field, value);
     261         [ #  # ]:          0 :         if (x)
     262                 :          0 :                 iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x);
     263                 :          0 :         return x;
     264                 :            : }
     265                 :            : 
     266                 :          0 : char* set_iovec_string_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) {
     267                 :            :         char *x;
     268                 :            : 
     269                 :          0 :         x = set_iovec_string_field(iovec, n_iovec, field, value);
     270                 :          0 :         free(value);
     271                 :          0 :         return x;
     272                 :            : }
     273                 :            : 
     274                 :          0 : struct iovec_wrapper *iovw_new(void) {
     275                 :          0 :         return malloc0(sizeof(struct iovec_wrapper));
     276                 :            : }
     277                 :            : 
     278                 :          8 : void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors) {
     279         [ -  + ]:          8 :         if (free_vectors)
     280         [ #  # ]:          0 :                 for (size_t i = 0; i < iovw->count; i++)
     281                 :          0 :                         free(iovw->iovec[i].iov_base);
     282                 :            : 
     283                 :          8 :         iovw->iovec = mfree(iovw->iovec);
     284                 :          8 :         iovw->count = 0;
     285                 :          8 :         iovw->size_bytes = 0;
     286                 :          8 : }
     287                 :            : 
     288                 :          0 : struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw) {
     289                 :          0 :         iovw_free_contents(iovw, true);
     290                 :            : 
     291                 :          0 :         return mfree(iovw);
     292                 :            : }
     293                 :            : 
     294                 :          0 : struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw) {
     295                 :          0 :         iovw_free_contents(iovw, false);
     296                 :            : 
     297                 :          0 :         return mfree(iovw);
     298                 :            : }
     299                 :            : 
     300                 :         28 : int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) {
     301         [ -  + ]:         28 :         if (iovw->count >= IOV_MAX)
     302                 :          0 :                 return -E2BIG;
     303                 :            : 
     304         [ -  + ]:         28 :         if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
     305                 :          0 :                 return log_oom();
     306                 :            : 
     307                 :         28 :         iovw->iovec[iovw->count++] = IOVEC_MAKE(data, len);
     308                 :         28 :         return 0;
     309                 :            : }
     310                 :            : 
     311                 :          0 : int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value) {
     312                 :          0 :         _cleanup_free_ char *x = NULL;
     313                 :            :         int r;
     314                 :            : 
     315                 :          0 :         x = strjoin(field, value);
     316         [ #  # ]:          0 :         if (!x)
     317                 :          0 :                 return log_oom();
     318                 :            : 
     319                 :          0 :         r = iovw_put(iovw, x, strlen(x));
     320         [ #  # ]:          0 :         if (r >= 0)
     321                 :          0 :                 TAKE_PTR(x);
     322                 :            : 
     323                 :          0 :         return r;
     324                 :            : }
     325                 :            : 
     326                 :          0 : int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value) {
     327                 :          0 :         _cleanup_free_ _unused_ char *free_ptr = value;
     328                 :            : 
     329                 :          0 :         return iovw_put_string_field(iovw, field, value);
     330                 :            : }
     331                 :            : 
     332                 :          8 : void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) {
     333                 :            :         size_t i;
     334                 :            : 
     335         [ -  + ]:          8 :         for (i = 0; i < iovw->count; i++)
     336                 :          0 :                 iovw->iovec[i].iov_base = (char *)iovw->iovec[i].iov_base - old + new;
     337                 :          8 : }
     338                 :            : 
     339                 :          0 : size_t iovw_size(struct iovec_wrapper *iovw) {
     340                 :          0 :         size_t n = 0, i;
     341                 :            : 
     342         [ #  # ]:          0 :         for (i = 0; i < iovw->count; i++)
     343                 :          0 :                 n += iovw->iovec[i].iov_len;
     344                 :            : 
     345                 :          0 :         return n;
     346                 :            : }

Generated by: LCOV version 1.14