LCOV - code coverage report
Current view: top level - libbpfilter - helper.c (source / functions) Coverage Total Hit
Test: coverage.lcov Lines: 85.5 % 83 71
Test Date: 2026-05-09 09:49:18 Functions: 100.0 % 11 11
Branches: 51.5 % 68 35

             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                 :             : /// FNV-1a 64-bit offset basis (the initial hash value).
      24                 :             : #define _BF_FNV1A_INIT 0xcbf29ce484222325ULL
      25                 :             : /// FNV-1a 64-bit prime.
      26                 :             : #define _BF_FNV1A_PRIME 0x100000001b3ULL
      27                 :             : 
      28                 :       95080 : void closep(int *fd)
      29                 :             : {
      30         [ +  + ]:       95080 :     if (*fd < 0)
      31                 :             :         return;
      32                 :             : 
      33         [ +  + ]:       54907 :     if (close(*fd))
      34         [ +  - ]:           2 :         bf_warn_r(errno, "failed to close fd %d, assuming file is closed", *fd);
      35                 :             : 
      36                 :       54907 :     *fd = -1;
      37                 :             : }
      38                 :             : 
      39                 :       16951 : int bf_strncpy(char *dst, size_t len, const char *src)
      40                 :             : {
      41                 :             :     size_t src_len;
      42                 :             :     size_t copy_len;
      43                 :             : 
      44                 :             :     assert(dst);
      45                 :             :     assert(src);
      46                 :             :     assert(len);
      47                 :             : 
      48                 :       16951 :     src_len = strlen(src);
      49                 :       16951 :     copy_len = bf_min(src_len, len - 1);
      50                 :             : 
      51                 :       16951 :     memcpy(dst, src, copy_len);
      52                 :       16951 :     dst[copy_len] = '\0';
      53                 :             : 
      54         [ +  + ]:       16951 :     return copy_len != src_len ? -E2BIG : 0;
      55                 :             : }
      56                 :             : 
      57                 :        8669 : int bf_realloc(void **ptr, size_t size)
      58                 :             : {
      59                 :             :     _cleanup_free_ void *_ptr;
      60                 :             : 
      61                 :             :     assert(ptr);
      62                 :             : 
      63                 :        8669 :     _ptr = realloc(*ptr, size);
      64         [ +  - ]:        8669 :     if (!_ptr)
      65                 :             :         return -ENOMEM;
      66                 :             : 
      67                 :        8669 :     *ptr = TAKE_PTR(_ptr);
      68                 :             : 
      69                 :        8669 :     return 0;
      70                 :             : }
      71                 :             : 
      72                 :           6 : int bf_read_file(const char *path, void **buf, size_t *len)
      73                 :             : {
      74                 :           6 :     _cleanup_close_ int fd = -1;
      75                 :             :     _cleanup_free_ void *_buf = NULL;
      76                 :             :     size_t _len;
      77                 :             :     ssize_t r;
      78                 :             : 
      79                 :             :     assert(path);
      80                 :             :     assert(buf);
      81                 :             :     assert(len);
      82                 :             : 
      83                 :           6 :     fd = open(path, O_RDONLY);
      84         [ +  + ]:           6 :     if (fd < 0)
      85         [ +  - ]:           1 :         return bf_err_r(errno, "failed to open %s", path);
      86                 :             : 
      87                 :           5 :     _len = lseek(fd, 0, SEEK_END);
      88                 :           5 :     lseek(fd, 0, SEEK_SET);
      89                 :             : 
      90                 :           5 :     _buf = malloc(_len);
      91         [ -  + ]:           5 :     if (!_buf)
      92         [ #  # ]:           0 :         return bf_err_r(errno, "failed to allocate memory");
      93                 :             : 
      94                 :           5 :     r = read(fd, _buf, _len);
      95         [ -  + ]:           5 :     if (r < 0)
      96         [ #  # ]:           0 :         return bf_err_r(errno, "failed to read serialized data");
      97         [ -  + ]:           5 :     if ((size_t)r != _len)
      98         [ #  # ]:           0 :         return bf_err_r(EIO, "can't read full serialized data");
      99                 :             : 
     100                 :           5 :     closep(&fd);
     101                 :             : 
     102                 :           5 :     *buf = TAKE_PTR(_buf);
     103                 :           5 :     *len = _len;
     104                 :             : 
     105                 :           5 :     return 0;
     106                 :             : }
     107                 :             : 
     108                 :           6 : static int _bf_get_tmpfile_fd(const char *base,
     109                 :             :                               char tmpfile_path[static PATH_MAX])
     110                 :             : {
     111                 :             :     _cleanup_free_ char *tmp = NULL;
     112                 :             :     size_t path_len;
     113                 :             :     char *dir;
     114                 :             :     int fd;
     115                 :             : 
     116                 :             :     /* The dirname call may modify its argument. */
     117                 :           6 :     tmp = strdup(base);
     118         [ -  + ]:           6 :     if (!tmp)
     119         [ #  # ]:           0 :         return bf_err_r(ENOMEM, "could not duplicate path %s", base);
     120                 :             : 
     121                 :           6 :     dir = dirname(tmp);
     122                 :             : 
     123                 :           6 :     path_len =
     124                 :           6 :         snprintf(tmpfile_path, PATH_MAX, "%s%s", dir, "/bpfilter.tmp.XXXXXX");
     125         [ -  + ]:           6 :     if (path_len >= PATH_MAX)
     126         [ #  # ]:           0 :         return bf_err_r(ENAMETOOLONG, "tmpfile name too long (%lu bytes)",
     127                 :             :                         path_len);
     128                 :             : 
     129                 :           6 :     fd = mkstemp(tmpfile_path);
     130         [ -  + ]:           6 :     if (fd < 0)
     131         [ #  # ]:           0 :         return bf_err_r(errno, "failed to open %s", tmpfile_path);
     132                 :             : 
     133                 :             :     return fd;
     134                 :             : }
     135                 :             : 
     136                 :           6 : int bf_write_file(const char *path, const void *buf, size_t len)
     137                 :             : {
     138                 :           6 :     _cleanup_close_ int fd = -1;
     139                 :             :     ssize_t r;
     140                 :             :     int err;
     141                 :             :     char tmpfile_path[PATH_MAX];
     142                 :             : 
     143                 :             :     assert(path);
     144                 :             :     assert(buf);
     145                 :             : 
     146                 :           6 :     fd = _bf_get_tmpfile_fd(path, tmpfile_path);
     147         [ -  + ]:           6 :     if (fd < 0)
     148         [ #  # ]:           0 :         return bf_err_r(fd, "failed to get temporary file name");
     149                 :             : 
     150                 :           6 :     r = write(fd, buf, len);
     151         [ -  + ]:           6 :     if (r < 0)
     152         [ #  # ]:           0 :         return bf_err_r(errno, "failed to write to %s", tmpfile_path);
     153         [ -  + ]:           6 :     if ((size_t)r != len)
     154         [ #  # ]:           0 :         return bf_err_r(EIO, "can't write full data to %s", tmpfile_path);
     155                 :             : 
     156                 :           6 :     closep(&fd);
     157                 :             : 
     158         [ -  + ]:           6 :     if (rename(tmpfile_path, path) < 0) {
     159                 :           0 :         err = errno;
     160                 :           0 :         unlink(tmpfile_path);
     161         [ #  # ]:           0 :         return bf_err_r(err, "failed to move %s to %s", tmpfile_path, path);
     162                 :             :     }
     163                 :             : 
     164                 :             :     return 0;
     165                 :             : }
     166                 :             : 
     167                 :        1137 : char *bf_ltrim(char *str)
     168                 :             : {
     169                 :             :     assert(str);
     170                 :             : 
     171         [ +  + ]:        3067 :     while (isspace(*str))
     172                 :        1930 :         str++;
     173                 :        1137 :     return str;
     174                 :             : }
     175                 :             : 
     176                 :        1138 : char *bf_rtrim(char *str)
     177                 :             : {
     178                 :             :     assert(str);
     179                 :             : 
     180                 :        1138 :     char *back = str + strlen(str);
     181                 :             : 
     182         [ +  + ]:        1138 :     if (back == str)
     183                 :             :         return str;
     184                 :             : 
     185                 :             :     do {
     186                 :        1192 :         --back;
     187   [ +  +  +  + ]:        1192 :     } while (back > str && isspace(*back));
     188                 :             : 
     189   [ +  +  +  + ]:        1081 :     if (back == str && isspace(*back))
     190                 :           1 :         *back = '\0';
     191                 :             :     else
     192                 :        1080 :         *(back + 1) = '\0';
     193                 :             : 
     194                 :             :     return str;
     195                 :             : }
     196                 :             : 
     197                 :        1129 : char *bf_trim(char *str)
     198                 :             : {
     199                 :             :     assert(str);
     200                 :             : 
     201                 :        1129 :     return bf_rtrim(bf_ltrim(str));
     202                 :             : }
     203                 :             : 
     204                 :        4204 : uint64_t bf_fnv1a_init(void)
     205                 :             : {
     206                 :        4204 :     return _BF_FNV1A_INIT;
     207                 :             : }
     208                 :             : 
     209                 :        4205 : uint64_t bf_fnv1a(const void *data, size_t len, uint64_t hash)
     210                 :             : {
     211                 :             :     const uint8_t *bytes;
     212                 :             : 
     213                 :             :     assert(data);
     214                 :             : 
     215                 :             :     bytes = data;
     216                 :             : 
     217         [ +  + ]:       29403 :     for (size_t i = 0; i < len; ++i) {
     218                 :       25198 :         hash ^= bytes[i];
     219                 :       25198 :         hash *= _BF_FNV1A_PRIME;
     220                 :             :     }
     221                 :             : 
     222                 :        4205 :     return hash;
     223                 :             : }
        

Generated by: LCOV version 2.0-1