LCOV - code coverage report
Current view: top level - libbpfilter - helper.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 84.2 % 76 64
Test Date: 2026-02-28 14:57:49 Functions: 100.0 % 9 9
Branches: 50.0 % 66 33

             Branch data     Line data    Source code
       1                 :             : /* SPDX-License-Identifier: GPL-2.0-only */
       2                 :             : /*
       3                 :             :  * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
       4                 :             :  */
       5                 :             : 
       6                 :             : #include "bpfilter/helper.h"
       7                 :             : 
       8                 :             : #include <ctype.h>
       9                 :             : #include <errno.h>
      10                 :             : #include <fcntl.h>
      11                 :             : #include <libgen.h>
      12                 :             : #include <limits.h>
      13                 :             : #include <stdio.h>
      14                 :             : #include <stdlib.h>
      15                 :             : #include <string.h>
      16                 :             : #include <sys/types.h>
      17                 :             : #include <unistd.h>
      18                 :             : 
      19                 :             : #include "bpfilter/logger.h"
      20                 :             : 
      21                 :             : #define OPEN_MODE_644 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)
      22                 :             : 
      23                 :        6481 : void closep(int *fd)
      24                 :             : {
      25         [ +  + ]:        6481 :     if (*fd < 0)
      26                 :             :         return;
      27                 :             : 
      28         [ +  + ]:        2650 :     if (close(*fd))
      29         [ +  - ]:           2 :         bf_warn_r(errno, "failed to close fd %d, assuming file is closed", *fd);
      30                 :             : 
      31                 :        2650 :     *fd = -1;
      32                 :             : }
      33                 :             : 
      34                 :        1034 : int bf_strncpy(char *dst, size_t len, const char *src)
      35                 :             : {
      36                 :             :     size_t src_len;
      37                 :             :     size_t copy_len;
      38                 :             : 
      39                 :             :     assert(dst);
      40                 :             :     assert(src);
      41                 :             :     assert(len);
      42                 :             : 
      43                 :        1034 :     src_len = strlen(src);
      44                 :        1034 :     copy_len = bf_min(src_len, len - 1);
      45                 :             : 
      46                 :        1034 :     memcpy(dst, src, copy_len);
      47                 :        1034 :     dst[copy_len] = '\0';
      48                 :             : 
      49         [ +  + ]:        1034 :     return copy_len != src_len ? -E2BIG : 0;
      50                 :             : }
      51                 :             : 
      52                 :        1865 : int bf_realloc(void **ptr, size_t size)
      53                 :             : {
      54                 :             :     _cleanup_free_ void *_ptr;
      55                 :             : 
      56                 :             :     assert(ptr);
      57                 :             : 
      58                 :        1865 :     _ptr = realloc(*ptr, size);
      59         [ +  - ]:        1865 :     if (!_ptr)
      60                 :             :         return -ENOMEM;
      61                 :             : 
      62                 :        1865 :     *ptr = TAKE_PTR(_ptr);
      63                 :             : 
      64                 :        1865 :     return 0;
      65                 :             : }
      66                 :             : 
      67                 :          11 : int bf_read_file(const char *path, void **buf, size_t *len)
      68                 :             : {
      69                 :          11 :     _cleanup_close_ int fd = -1;
      70                 :             :     _cleanup_free_ void *_buf = NULL;
      71                 :             :     size_t _len;
      72                 :             :     ssize_t r;
      73                 :             : 
      74                 :             :     assert(path);
      75                 :             :     assert(buf);
      76                 :             :     assert(len);
      77                 :             : 
      78                 :          11 :     fd = open(path, O_RDONLY);
      79         [ +  + ]:          11 :     if (fd < 0)
      80         [ +  - ]:           1 :         return bf_err_r(errno, "failed to open %s", path);
      81                 :             : 
      82                 :          10 :     _len = lseek(fd, 0, SEEK_END);
      83                 :          10 :     lseek(fd, 0, SEEK_SET);
      84                 :             : 
      85                 :          10 :     _buf = malloc(_len);
      86         [ -  + ]:          10 :     if (!_buf)
      87         [ #  # ]:           0 :         return bf_err_r(errno, "failed to allocate memory");
      88                 :             : 
      89                 :          10 :     r = read(fd, _buf, _len);
      90         [ -  + ]:          10 :     if (r < 0)
      91         [ #  # ]:           0 :         return bf_err_r(errno, "failed to read serialized data");
      92         [ -  + ]:          10 :     if ((size_t)r != _len)
      93         [ #  # ]:           0 :         return bf_err_r(EIO, "can't read full serialized data");
      94                 :             : 
      95                 :          10 :     closep(&fd);
      96                 :             : 
      97                 :          10 :     *buf = TAKE_PTR(_buf);
      98                 :          10 :     *len = _len;
      99                 :             : 
     100                 :          10 :     return 0;
     101                 :             : }
     102                 :             : 
     103                 :         122 : static int _bf_get_tmpfile_fd(const char *base,
     104                 :             :                               char tmpfile_path[static PATH_MAX])
     105                 :             : {
     106                 :             :     _cleanup_free_ char *tmp = NULL;
     107                 :             :     size_t path_len;
     108                 :             :     char *dir;
     109                 :             :     int fd;
     110                 :             : 
     111                 :             :     /* The dirname call may modify its argument. */
     112                 :         122 :     tmp = strdup(base);
     113         [ -  + ]:         122 :     if (!tmp)
     114         [ #  # ]:           0 :         return bf_err_r(ENOMEM, "could not duplicate path %s", base);
     115                 :             : 
     116                 :         122 :     dir = dirname(tmp);
     117                 :             : 
     118                 :         122 :     path_len =
     119                 :         122 :         snprintf(tmpfile_path, PATH_MAX, "%s%s", dir, "/bpfilter.tmp.XXXXXX");
     120         [ -  + ]:         122 :     if (path_len >= PATH_MAX)
     121         [ #  # ]:           0 :         return bf_err_r(ENAMETOOLONG, "tmpfile name too long (%lu bytes)",
     122                 :             :                         path_len);
     123                 :             : 
     124                 :         122 :     fd = mkstemp(tmpfile_path);
     125         [ -  + ]:         122 :     if (fd < 0)
     126         [ #  # ]:           0 :         return bf_err_r(errno, "failed to open %s", tmpfile_path);
     127                 :             : 
     128                 :             :     return fd;
     129                 :             : }
     130                 :             : 
     131                 :         122 : int bf_write_file(const char *path, const void *buf, size_t len)
     132                 :             : {
     133                 :         122 :     _cleanup_close_ int fd = -1;
     134                 :             :     ssize_t r;
     135                 :             :     int err;
     136                 :             :     char tmpfile_path[PATH_MAX];
     137                 :             : 
     138                 :             :     assert(path);
     139                 :             :     assert(buf);
     140                 :             : 
     141                 :         122 :     fd = _bf_get_tmpfile_fd(path, tmpfile_path);
     142         [ -  + ]:         122 :     if (fd < 0)
     143         [ #  # ]:           0 :         return bf_err_r(fd, "failed to get temporary file name");
     144                 :             : 
     145                 :         122 :     r = write(fd, buf, len);
     146         [ -  + ]:         122 :     if (r < 0)
     147         [ #  # ]:           0 :         return bf_err_r(errno, "failed to write to %s", tmpfile_path);
     148         [ -  + ]:         122 :     if ((size_t)r != len)
     149         [ #  # ]:           0 :         return bf_err_r(EIO, "can't write full data to %s", tmpfile_path);
     150                 :             : 
     151                 :         122 :     closep(&fd);
     152                 :             : 
     153         [ -  + ]:         122 :     if (rename(tmpfile_path, path) < 0) {
     154                 :           0 :         err = errno;
     155                 :           0 :         unlink(tmpfile_path);
     156         [ #  # ]:           0 :         return bf_err_r(err, "failed to move %s to %s", tmpfile_path, path);
     157                 :             :     }
     158                 :             : 
     159                 :             :     return 0;
     160                 :             : }
     161                 :             : 
     162                 :         951 : char *bf_ltrim(char *str)
     163                 :             : {
     164                 :             :     assert(str);
     165                 :             : 
     166         [ +  + ]:        2736 :     while (isspace(*str))
     167                 :        1785 :         str++;
     168                 :         951 :     return str;
     169                 :             : }
     170                 :             : 
     171                 :         952 : char *bf_rtrim(char *str)
     172                 :             : {
     173                 :             :     assert(str);
     174                 :             : 
     175                 :         952 :     char *back = str + strlen(str);
     176                 :             : 
     177         [ +  + ]:         952 :     if (back == str)
     178                 :             :         return str;
     179                 :             : 
     180                 :             :     do {
     181                 :         967 :         --back;
     182   [ +  +  +  + ]:         967 :     } while (back > str && isspace(*back));
     183                 :             : 
     184   [ +  +  +  + ]:         898 :     if (back == str && isspace(*back))
     185                 :           1 :         *back = '\0';
     186                 :             :     else
     187                 :         897 :         *(back + 1) = '\0';
     188                 :             : 
     189                 :             :     return str;
     190                 :             : }
     191                 :             : 
     192                 :         943 : char *bf_trim(char *str)
     193                 :             : {
     194                 :             :     assert(str);
     195                 :             : 
     196                 :         943 :     return bf_rtrim(bf_ltrim(str));
     197                 :             : }
        

Generated by: LCOV version 2.0-1