LCOV - code coverage report
Current view: top level - journal - journal-send.c (source / functions) Hit Total Coverage
Test: systemd_full.info Lines: 157 262 59.9 %
Date: 2019-08-23 13:36:53 Functions: 9 14 64.3 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 86 210 41.0 %

           Branch data     Line data    Source code
       1                 :            : /* SPDX-License-Identifier: LGPL-2.1+ */
       2                 :            : 
       3                 :            : #include <errno.h>
       4                 :            : #include <fcntl.h>
       5                 :            : #include <printf.h>
       6                 :            : #include <stddef.h>
       7                 :            : #include <sys/socket.h>
       8                 :            : #include <sys/un.h>
       9                 :            : #include <unistd.h>
      10                 :            : 
      11                 :            : #define SD_JOURNAL_SUPPRESS_LOCATION
      12                 :            : 
      13                 :            : #include "sd-journal.h"
      14                 :            : 
      15                 :            : #include "alloc-util.h"
      16                 :            : #include "errno-util.h"
      17                 :            : #include "fd-util.h"
      18                 :            : #include "io-util.h"
      19                 :            : #include "memfd-util.h"
      20                 :            : #include "socket-util.h"
      21                 :            : #include "stdio-util.h"
      22                 :            : #include "string-util.h"
      23                 :            : #include "tmpfile-util.h"
      24                 :            : 
      25                 :            : #define SNDBUF_SIZE (8*1024*1024)
      26                 :            : 
      27                 :            : #define ALLOCA_CODE_FUNC(f, func)                 \
      28                 :            :         do {                                      \
      29                 :            :                 size_t _fl;                       \
      30                 :            :                 const char *_func = (func);       \
      31                 :            :                 char **_f = &(f);                 \
      32                 :            :                 _fl = strlen(_func) + 1;          \
      33                 :            :                 *_f = newa(char, _fl + 10);       \
      34                 :            :                 memcpy(*_f, "CODE_FUNC=", 10);    \
      35                 :            :                 memcpy(*_f + 10, _func, _fl);     \
      36                 :            :         } while (false)
      37                 :            : 
      38                 :            : /* We open a single fd, and we'll share it with the current process,
      39                 :            :  * all its threads, and all its subprocesses. This means we need to
      40                 :            :  * initialize it atomically, and need to operate on it atomically
      41                 :            :  * never assuming we are the only user */
      42                 :            : 
      43                 :         64 : static int journal_fd(void) {
      44                 :            :         int fd;
      45                 :            :         static int fd_plus_one = 0;
      46                 :            : 
      47                 :         64 : retry:
      48         [ +  + ]:         64 :         if (fd_plus_one > 0)
      49                 :         60 :                 return fd_plus_one - 1;
      50                 :            : 
      51                 :          4 :         fd = socket(AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, 0);
      52         [ -  + ]:          4 :         if (fd < 0)
      53                 :          0 :                 return -errno;
      54                 :            : 
      55                 :          4 :         fd_inc_sndbuf(fd, SNDBUF_SIZE);
      56                 :            : 
      57         [ -  + ]:          4 :         if (!__sync_bool_compare_and_swap(&fd_plus_one, 0, fd+1)) {
      58                 :          0 :                 safe_close(fd);
      59                 :          0 :                 goto retry;
      60                 :            :         }
      61                 :            : 
      62                 :          4 :         return fd;
      63                 :            : }
      64                 :            : 
      65                 :          0 : _public_ int sd_journal_print(int priority, const char *format, ...) {
      66                 :            :         int r;
      67                 :            :         va_list ap;
      68                 :            : 
      69                 :          0 :         va_start(ap, format);
      70                 :          0 :         r = sd_journal_printv(priority, format, ap);
      71                 :          0 :         va_end(ap);
      72                 :            : 
      73                 :          0 :         return r;
      74                 :            : }
      75                 :            : 
      76                 :          0 : _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
      77                 :            : 
      78                 :            :         /* FIXME: Instead of limiting things to LINE_MAX we could do a
      79                 :            :            C99 variable-length array on the stack here in a loop. */
      80                 :            : 
      81                 :            :         char buffer[8 + LINE_MAX], p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
      82                 :            :         struct iovec iov[2];
      83                 :            : 
      84   [ #  #  #  # ]:          0 :         assert_return(priority >= 0, -EINVAL);
      85   [ #  #  #  # ]:          0 :         assert_return(priority <= 7, -EINVAL);
      86   [ #  #  #  # ]:          0 :         assert_return(format, -EINVAL);
      87                 :            : 
      88         [ #  # ]:          0 :         xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
      89                 :            : 
      90                 :          0 :         memcpy(buffer, "MESSAGE=", 8);
      91                 :          0 :         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
      92                 :            : 
      93                 :            :         /* Strip trailing whitespace, keep prefix whitespace. */
      94                 :          0 :         (void) strstrip(buffer);
      95                 :            : 
      96                 :            :         /* Suppress empty lines */
      97         [ #  # ]:          0 :         if (isempty(buffer+8))
      98                 :          0 :                 return 0;
      99                 :            : 
     100                 :          0 :         iov[0] = IOVEC_MAKE_STRING(buffer);
     101                 :          0 :         iov[1] = IOVEC_MAKE_STRING(p);
     102                 :            : 
     103                 :          0 :         return sd_journal_sendv(iov, 2);
     104                 :            : }
     105                 :            : 
     106                 :         16 : _printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) {
     107                 :         16 :         PROTECT_ERRNO;
     108                 :         16 :         int r, n = 0, i = 0, j;
     109                 :         16 :         struct iovec *iov = NULL;
     110                 :            : 
     111         [ -  + ]:         16 :         assert(_iov);
     112                 :            : 
     113         [ +  - ]:         16 :         if (extra > 0) {
     114                 :         16 :                 n = MAX(extra * 2, extra + 4);
     115                 :         16 :                 iov = malloc0(n * sizeof(struct iovec));
     116         [ -  + ]:         16 :                 if (!iov) {
     117                 :          0 :                         r = -ENOMEM;
     118                 :          0 :                         goto fail;
     119                 :            :                 }
     120                 :            : 
     121                 :         16 :                 i = extra;
     122                 :            :         }
     123                 :            : 
     124         [ +  + ]:         92 :         while (format) {
     125                 :            :                 struct iovec *c;
     126                 :            :                 char *buffer;
     127                 :            :                 va_list aq;
     128                 :            : 
     129         [ +  + ]:         76 :                 if (i >= n) {
     130                 :          8 :                         n = MAX(i*2, 4);
     131                 :          8 :                         c = realloc(iov, n * sizeof(struct iovec));
     132         [ -  + ]:          8 :                         if (!c) {
     133                 :          0 :                                 r = -ENOMEM;
     134                 :          0 :                                 goto fail;
     135                 :            :                         }
     136                 :            : 
     137                 :          8 :                         iov = c;
     138                 :            :                 }
     139                 :            : 
     140                 :         76 :                 va_copy(aq, ap);
     141         [ -  + ]:         76 :                 if (vasprintf(&buffer, format, aq) < 0) {
     142                 :          0 :                         va_end(aq);
     143                 :          0 :                         r = -ENOMEM;
     144                 :          0 :                         goto fail;
     145                 :            :                 }
     146                 :         76 :                 va_end(aq);
     147                 :            : 
     148   [ -  +  -  +  :         96 :                 VA_FORMAT_ADVANCE(format, ap);
          +  +  -  -  +  
             -  -  -  +  
                      + ]
     149                 :            : 
     150                 :         76 :                 (void) strstrip(buffer); /* strip trailing whitespace, keep prefixing whitespace */
     151                 :            : 
     152                 :         76 :                 iov[i++] = IOVEC_MAKE_STRING(buffer);
     153                 :            : 
     154                 :         76 :                 format = va_arg(ap, char *);
     155                 :            :         }
     156                 :            : 
     157                 :         16 :         *_iov = iov;
     158                 :            : 
     159                 :         16 :         return i;
     160                 :            : 
     161                 :          0 : fail:
     162         [ #  # ]:          0 :         for (j = 0; j < i; j++)
     163                 :          0 :                 free(iov[j].iov_base);
     164                 :            : 
     165                 :          0 :         free(iov);
     166                 :            : 
     167                 :          0 :         return r;
     168                 :            : }
     169                 :            : 
     170                 :          0 : _public_ int sd_journal_send(const char *format, ...) {
     171                 :            :         int r, i, j;
     172                 :            :         va_list ap;
     173                 :          0 :         struct iovec *iov = NULL;
     174                 :            : 
     175                 :          0 :         va_start(ap, format);
     176                 :          0 :         i = fill_iovec_sprintf(format, ap, 0, &iov);
     177                 :          0 :         va_end(ap);
     178                 :            : 
     179         [ #  # ]:          0 :         if (_unlikely_(i < 0)) {
     180                 :          0 :                 r = i;
     181                 :          0 :                 goto finish;
     182                 :            :         }
     183                 :            : 
     184                 :          0 :         r = sd_journal_sendv(iov, i);
     185                 :            : 
     186                 :          0 : finish:
     187         [ #  # ]:          0 :         for (j = 0; j < i; j++)
     188                 :          0 :                 free(iov[j].iov_base);
     189                 :            : 
     190                 :          0 :         free(iov);
     191                 :            : 
     192                 :          0 :         return r;
     193                 :            : }
     194                 :            : 
     195                 :         64 : _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
     196                 :         64 :         PROTECT_ERRNO;
     197                 :            :         int fd, r;
     198                 :         64 :         _cleanup_close_ int buffer_fd = -1;
     199                 :            :         struct iovec *w;
     200                 :            :         uint64_t *l;
     201                 :         64 :         int i, j = 0;
     202                 :            :         static const union sockaddr_union sa = {
     203                 :            :                 .un.sun_family = AF_UNIX,
     204                 :            :                 .un.sun_path = "/run/systemd/journal/socket",
     205                 :            :         };
     206                 :        128 :         struct msghdr mh = {
     207                 :            :                 .msg_name = (struct sockaddr*) &sa.sa,
     208   [ -  +  -  + ]:         64 :                 .msg_namelen = SOCKADDR_UN_LEN(sa.un),
     209                 :            :         };
     210                 :            :         ssize_t k;
     211                 :         64 :         bool have_syslog_identifier = false;
     212                 :         64 :         bool seal = true;
     213                 :            : 
     214   [ -  +  -  + ]:         64 :         assert_return(iov, -EINVAL);
     215   [ -  +  -  + ]:         64 :         assert_return(n > 0, -EINVAL);
     216                 :            : 
     217   [ -  +  -  + ]:         64 :         w = newa(struct iovec, n * 5 + 3);
     218   [ -  +  -  + ]:         64 :         l = newa(uint64_t, n);
     219                 :            : 
     220         [ +  + ]:        356 :         for (i = 0; i < n; i++) {
     221                 :            :                 char *c, *nl;
     222                 :            : 
     223   [ +  -  -  + ]:        292 :                 if (_unlikely_(!iov[i].iov_base || iov[i].iov_len <= 1))
     224                 :          0 :                         return -EINVAL;
     225                 :            : 
     226                 :        292 :                 c = memchr(iov[i].iov_base, '=', iov[i].iov_len);
     227   [ +  -  -  + ]:        292 :                 if (_unlikely_(!c || c == iov[i].iov_base))
     228                 :          0 :                         return -EINVAL;
     229                 :            : 
     230         [ +  - ]:        584 :                 have_syslog_identifier = have_syslog_identifier ||
     231   [ -  +  #  # ]:        292 :                         (c == (char *) iov[i].iov_base + 17 &&
     232                 :          0 :                          startswith(iov[i].iov_base, "SYSLOG_IDENTIFIER"));
     233                 :            : 
     234                 :        292 :                 nl = memchr(iov[i].iov_base, '\n', iov[i].iov_len);
     235         [ +  + ]:        292 :                 if (nl) {
     236         [ -  + ]:         16 :                         if (_unlikely_(nl < c))
     237                 :          0 :                                 return -EINVAL;
     238                 :            : 
     239                 :            :                         /* Already includes a newline? Bummer, then
     240                 :            :                          * let's write the variable name, then a
     241                 :            :                          * newline, then the size (64bit LE), followed
     242                 :            :                          * by the data and a final newline */
     243                 :            : 
     244                 :         16 :                         w[j++] = IOVEC_MAKE(iov[i].iov_base, c - (char*) iov[i].iov_base);
     245                 :         16 :                         w[j++] = IOVEC_MAKE_STRING("\n");
     246                 :            : 
     247                 :         16 :                         l[i] = htole64(iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
     248                 :         16 :                         w[j++] = IOVEC_MAKE(&l[i], sizeof(uint64_t));
     249                 :            : 
     250                 :         16 :                         w[j++] = IOVEC_MAKE(c + 1, iov[i].iov_len - (c - (char*) iov[i].iov_base) - 1);
     251                 :            :                 } else
     252                 :            :                         /* Nothing special? Then just add the line and
     253                 :            :                          * append a newline */
     254                 :        276 :                         w[j++] = iov[i];
     255                 :            : 
     256                 :        292 :                 w[j++] = IOVEC_MAKE_STRING("\n");
     257                 :            :         }
     258                 :            : 
     259         [ +  - ]:         64 :         if (!have_syslog_identifier &&
     260         [ +  - ]:         64 :             string_is_safe(program_invocation_short_name)) {
     261                 :            : 
     262                 :            :                 /* Implicitly add program_invocation_short_name, if it
     263                 :            :                  * is not set explicitly. We only do this for
     264                 :            :                  * program_invocation_short_name, and nothing else
     265                 :            :                  * since everything else is much nicer to retrieve
     266                 :            :                  * from the outside. */
     267                 :            : 
     268                 :         64 :                 w[j++] = IOVEC_MAKE_STRING("SYSLOG_IDENTIFIER=");
     269                 :         64 :                 w[j++] = IOVEC_MAKE_STRING(program_invocation_short_name);
     270                 :         64 :                 w[j++] = IOVEC_MAKE_STRING("\n");
     271                 :            :         }
     272                 :            : 
     273                 :         64 :         fd = journal_fd();
     274         [ -  + ]:         64 :         if (_unlikely_(fd < 0))
     275                 :          0 :                 return fd;
     276                 :            : 
     277                 :         64 :         mh.msg_iov = w;
     278                 :         64 :         mh.msg_iovlen = j;
     279                 :            : 
     280                 :         64 :         k = sendmsg(fd, &mh, MSG_NOSIGNAL);
     281         [ +  + ]:         64 :         if (k >= 0)
     282                 :         60 :                 return 0;
     283                 :            : 
     284                 :            :         /* Fail silently if the journal is not available */
     285         [ -  + ]:          4 :         if (errno == ENOENT)
     286                 :          0 :                 return 0;
     287                 :            : 
     288   [ +  -  -  + ]:          4 :         if (!IN_SET(errno, EMSGSIZE, ENOBUFS))
     289                 :          0 :                 return -errno;
     290                 :            : 
     291                 :            :         /* Message doesn't fit... Let's dump the data in a memfd or
     292                 :            :          * temporary file and just pass a file descriptor of it to the
     293                 :            :          * other side.
     294                 :            :          *
     295                 :            :          * For the temporary files we use /dev/shm instead of /tmp
     296                 :            :          * here, since we want this to be a tmpfs, and one that is
     297                 :            :          * available from early boot on and where unprivileged users
     298                 :            :          * can create files. */
     299                 :          4 :         buffer_fd = memfd_new(NULL);
     300         [ -  + ]:          4 :         if (buffer_fd < 0) {
     301         [ #  # ]:          0 :                 if (buffer_fd == -ENOSYS) {
     302                 :          0 :                         buffer_fd = open_tmpfile_unlinkable("/dev/shm", O_RDWR | O_CLOEXEC);
     303         [ #  # ]:          0 :                         if (buffer_fd < 0)
     304                 :          0 :                                 return buffer_fd;
     305                 :            : 
     306                 :          0 :                         seal = false;
     307                 :            :                 } else
     308                 :          0 :                         return buffer_fd;
     309                 :            :         }
     310                 :            : 
     311                 :          4 :         n = writev(buffer_fd, w, j);
     312         [ -  + ]:          4 :         if (n < 0)
     313                 :          0 :                 return -errno;
     314                 :            : 
     315         [ +  - ]:          4 :         if (seal) {
     316                 :          4 :                 r = memfd_set_sealed(buffer_fd);
     317         [ -  + ]:          4 :                 if (r < 0)
     318                 :          0 :                         return r;
     319                 :            :         }
     320                 :            : 
     321                 :          4 :         r = send_one_fd_sa(fd, buffer_fd, mh.msg_name, mh.msg_namelen, 0);
     322         [ -  + ]:          4 :         if (r == -ENOENT)
     323                 :            :                 /* Fail silently if the journal is not available */
     324                 :          0 :                 return 0;
     325                 :          4 :         return r;
     326                 :            : }
     327                 :            : 
     328                 :          8 : static int fill_iovec_perror_and_send(const char *message, int skip, struct iovec iov[]) {
     329                 :          8 :         PROTECT_ERRNO;
     330                 :            :         size_t n, k;
     331                 :            : 
     332         [ +  + ]:          8 :         k = isempty(message) ? 0 : strlen(message) + 2;
     333                 :          8 :         n = 8 + k + 256 + 1;
     334                 :            : 
     335                 :          0 :         for (;;) {
     336                 :          8 :                 char buffer[n];
     337                 :            :                 char* j;
     338                 :            : 
     339                 :          8 :                 errno = 0;
     340                 :          8 :                 j = strerror_r(_saved_errno_, buffer + 8 + k, n - 8 - k);
     341         [ +  - ]:          8 :                 if (errno == 0) {
     342                 :            :                         char error[STRLEN("ERRNO=") + DECIMAL_STR_MAX(int) + 1];
     343                 :            : 
     344         [ +  - ]:          8 :                         if (j != buffer + 8 + k)
     345                 :          8 :                                 memmove(buffer + 8 + k, j, strlen(j)+1);
     346                 :            : 
     347                 :          8 :                         memcpy(buffer, "MESSAGE=", 8);
     348                 :            : 
     349         [ +  + ]:          8 :                         if (k > 0) {
     350                 :          4 :                                 memcpy(buffer + 8, message, k - 2);
     351                 :          4 :                                 memcpy(buffer + 8 + k - 2, ": ", 2);
     352                 :            :                         }
     353                 :            : 
     354         [ -  + ]:          8 :                         xsprintf(error, "ERRNO=%i", _saved_errno_);
     355                 :            : 
     356                 :            :                         assert_cc(3 == LOG_ERR);
     357                 :          8 :                         iov[skip+0] = IOVEC_MAKE_STRING("PRIORITY=3");
     358                 :          8 :                         iov[skip+1] = IOVEC_MAKE_STRING(buffer);
     359                 :          8 :                         iov[skip+2] = IOVEC_MAKE_STRING(error);
     360                 :            : 
     361                 :          8 :                         return sd_journal_sendv(iov, skip + 3);
     362                 :            :                 }
     363                 :            : 
     364         [ #  # ]:          0 :                 if (errno != ERANGE)
     365                 :          0 :                         return -errno;
     366                 :            : 
     367                 :          0 :                 n *= 2;
     368                 :            :         }
     369                 :            : }
     370                 :            : 
     371                 :          0 : _public_ int sd_journal_perror(const char *message) {
     372                 :            :         struct iovec iovec[3];
     373                 :            : 
     374                 :          0 :         return fill_iovec_perror_and_send(message, 0, iovec);
     375                 :            : }
     376                 :            : 
     377                 :          0 : _public_ int sd_journal_stream_fd(const char *identifier, int priority, int level_prefix) {
     378                 :            :         static const union sockaddr_union sa = {
     379                 :            :                 .un.sun_family = AF_UNIX,
     380                 :            :                 .un.sun_path = "/run/systemd/journal/stdout",
     381                 :            :         };
     382                 :          0 :         _cleanup_close_ int fd = -1;
     383                 :            :         char *header;
     384                 :            :         size_t l;
     385                 :            :         int r;
     386                 :            : 
     387   [ #  #  #  # ]:          0 :         assert_return(priority >= 0, -EINVAL);
     388   [ #  #  #  # ]:          0 :         assert_return(priority <= 7, -EINVAL);
     389                 :            : 
     390                 :          0 :         fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
     391         [ #  # ]:          0 :         if (fd < 0)
     392                 :          0 :                 return -errno;
     393                 :            : 
     394   [ #  #  #  # ]:          0 :         r = connect(fd, &sa.sa, SOCKADDR_UN_LEN(sa.un));
     395         [ #  # ]:          0 :         if (r < 0)
     396                 :          0 :                 return -errno;
     397                 :            : 
     398         [ #  # ]:          0 :         if (shutdown(fd, SHUT_RD) < 0)
     399                 :          0 :                 return -errno;
     400                 :            : 
     401                 :          0 :         (void) fd_inc_sndbuf(fd, SNDBUF_SIZE);
     402                 :            : 
     403                 :          0 :         identifier = strempty(identifier);
     404                 :            : 
     405                 :          0 :         l = strlen(identifier);
     406   [ #  #  #  # ]:          0 :         header = newa(char, l + 1 + 1 + 2 + 2 + 2 + 2 + 2);
     407                 :            : 
     408                 :          0 :         memcpy(header, identifier, l);
     409                 :          0 :         header[l++] = '\n';
     410                 :          0 :         header[l++] = '\n'; /* unit id */
     411                 :          0 :         header[l++] = '0' + priority;
     412                 :          0 :         header[l++] = '\n';
     413         [ #  # ]:          0 :         header[l++] = '0' + !!level_prefix;
     414                 :          0 :         header[l++] = '\n';
     415                 :          0 :         header[l++] = '0';
     416                 :          0 :         header[l++] = '\n';
     417                 :          0 :         header[l++] = '0';
     418                 :          0 :         header[l++] = '\n';
     419                 :          0 :         header[l++] = '0';
     420                 :          0 :         header[l++] = '\n';
     421                 :            : 
     422                 :          0 :         r = loop_write(fd, header, l, false);
     423         [ #  # ]:          0 :         if (r < 0)
     424                 :          0 :                 return r;
     425                 :            : 
     426                 :          0 :         return TAKE_FD(fd);
     427                 :            : }
     428                 :            : 
     429                 :          8 : _public_ int sd_journal_print_with_location(int priority, const char *file, const char *line, const char *func, const char *format, ...) {
     430                 :            :         int r;
     431                 :            :         va_list ap;
     432                 :            : 
     433                 :          8 :         va_start(ap, format);
     434                 :          8 :         r = sd_journal_printv_with_location(priority, file, line, func, format, ap);
     435                 :          8 :         va_end(ap);
     436                 :            : 
     437                 :          8 :         return r;
     438                 :            : }
     439                 :            : 
     440                 :          8 : _public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
     441                 :            :         char buffer[8 + LINE_MAX], p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
     442                 :            :         struct iovec iov[5];
     443                 :            :         char *f;
     444                 :            : 
     445   [ -  +  -  + ]:          8 :         assert_return(priority >= 0, -EINVAL);
     446   [ -  +  -  + ]:          8 :         assert_return(priority <= 7, -EINVAL);
     447   [ -  +  -  + ]:          8 :         assert_return(format, -EINVAL);
     448                 :            : 
     449         [ -  + ]:          8 :         xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
     450                 :            : 
     451                 :          8 :         memcpy(buffer, "MESSAGE=", 8);
     452                 :          8 :         vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
     453                 :            : 
     454                 :            :         /* Strip trailing whitespace, keep prefixing whitespace */
     455                 :          8 :         (void) strstrip(buffer);
     456                 :            : 
     457                 :            :         /* Suppress empty lines */
     458         [ -  + ]:          8 :         if (isempty(buffer+8))
     459                 :          0 :                 return 0;
     460                 :            : 
     461                 :            :         /* func is initialized from __func__ which is not a macro, but
     462                 :            :          * a static const char[], hence cannot easily be prefixed with
     463                 :            :          * CODE_FUNC=, hence let's do it manually here. */
     464   [ -  +  -  + ]:          8 :         ALLOCA_CODE_FUNC(f, func);
     465                 :            : 
     466                 :          8 :         iov[0] = IOVEC_MAKE_STRING(buffer);
     467                 :          8 :         iov[1] = IOVEC_MAKE_STRING(p);
     468                 :          8 :         iov[2] = IOVEC_MAKE_STRING(file);
     469                 :          8 :         iov[3] = IOVEC_MAKE_STRING(line);
     470                 :          8 :         iov[4] = IOVEC_MAKE_STRING(f);
     471                 :            : 
     472                 :          8 :         return sd_journal_sendv(iov, ELEMENTSOF(iov));
     473                 :            : }
     474                 :            : 
     475                 :         16 : _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) {
     476                 :         32 :         _cleanup_free_ struct iovec *iov = NULL;
     477                 :            :         int r, i, j;
     478                 :            :         va_list ap;
     479                 :            :         char *f;
     480                 :            : 
     481                 :         16 :         va_start(ap, format);
     482                 :         16 :         i = fill_iovec_sprintf(format, ap, 3, &iov);
     483                 :         16 :         va_end(ap);
     484                 :            : 
     485         [ -  + ]:         16 :         if (_unlikely_(i < 0)) {
     486                 :          0 :                 r = i;
     487                 :          0 :                 goto finish;
     488                 :            :         }
     489                 :            : 
     490   [ -  +  -  + ]:         16 :         ALLOCA_CODE_FUNC(f, func);
     491                 :            : 
     492                 :         16 :         iov[0] = IOVEC_MAKE_STRING(file);
     493                 :         16 :         iov[1] = IOVEC_MAKE_STRING(line);
     494                 :         16 :         iov[2] = IOVEC_MAKE_STRING(f);
     495                 :            : 
     496                 :         16 :         r = sd_journal_sendv(iov, i);
     497                 :            : 
     498                 :         16 : finish:
     499         [ +  + ]:         92 :         for (j = 3; j < i; j++)
     500                 :         76 :                 free(iov[j].iov_base);
     501                 :            : 
     502                 :         16 :         return r;
     503                 :            : }
     504                 :            : 
     505                 :         16 : _public_ int sd_journal_sendv_with_location(
     506                 :            :                 const char *file, const char *line,
     507                 :            :                 const char *func,
     508                 :            :                 const struct iovec *iov, int n) {
     509                 :            : 
     510                 :            :         struct iovec *niov;
     511                 :            :         char *f;
     512                 :            : 
     513   [ -  +  -  + ]:         16 :         assert_return(iov, -EINVAL);
     514   [ -  +  -  + ]:         16 :         assert_return(n > 0, -EINVAL);
     515                 :            : 
     516   [ -  +  -  + ]:         16 :         niov = newa(struct iovec, n + 3);
     517                 :         16 :         memcpy(niov, iov, sizeof(struct iovec) * n);
     518                 :            : 
     519   [ -  +  -  + ]:         16 :         ALLOCA_CODE_FUNC(f, func);
     520                 :            : 
     521                 :         16 :         niov[n++] = IOVEC_MAKE_STRING(file);
     522                 :         16 :         niov[n++] = IOVEC_MAKE_STRING(line);
     523                 :         16 :         niov[n++] = IOVEC_MAKE_STRING(f);
     524                 :            : 
     525                 :         16 :         return sd_journal_sendv(niov, n);
     526                 :            : }
     527                 :            : 
     528                 :          8 : _public_ int sd_journal_perror_with_location(
     529                 :            :                 const char *file, const char *line,
     530                 :            :                 const char *func,
     531                 :            :                 const char *message) {
     532                 :            : 
     533                 :            :         struct iovec iov[6];
     534                 :            :         char *f;
     535                 :            : 
     536   [ -  +  -  + ]:          8 :         ALLOCA_CODE_FUNC(f, func);
     537                 :            : 
     538                 :          8 :         iov[0] = IOVEC_MAKE_STRING(file);
     539                 :          8 :         iov[1] = IOVEC_MAKE_STRING(line);
     540                 :          8 :         iov[2] = IOVEC_MAKE_STRING(f);
     541                 :            : 
     542                 :          8 :         return fill_iovec_perror_and_send(message, 3, iov);
     543                 :            : }

Generated by: LCOV version 1.14