LCOV - code coverage report
Current view: top level - core - io.c (source / functions) Coverage Total Hit
Test: lcov.out Lines: 0.0 % 93 0
Test Date: 2025-02-26 17:59:59 Functions: 0.0 % 7 0

            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 <errno.h>
       7              : #include <stdio.h>
       8              : #include <stdlib.h>
       9              : #include <string.h>
      10              : #include <sys/stat.h>
      11              : #include <unistd.h>
      12              : 
      13              : #include "core/helper.h"
      14              : #include "core/logger.h"
      15              : #include "core/request.h"
      16              : #include "core/response.h"
      17              : 
      18              : #define BF_PERM_755 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
      19              : 
      20            0 : static ssize_t _bf_recv_in_buff(int fd, void *buf, size_t buf_len)
      21              : {
      22              :     ssize_t bytes_read = 0;
      23              :     ssize_t r;
      24              : 
      25            0 :     bf_assert(buf);
      26              : 
      27              :     do {
      28              :         /// @todo Add a timeout to the socket to prevent blocking forever.
      29            0 :         r = read(fd, buf + bytes_read, buf_len - bytes_read);
      30            0 :         if (r < 0) {
      31            0 :             (void)fprintf(stderr, "can't read from the socket: %s\n",
      32            0 :                           bf_strerror(errno));
      33            0 :             return -errno;
      34              :         }
      35              : 
      36            0 :         bytes_read += r;
      37            0 :     } while (r && (size_t)bytes_read != buf_len);
      38              : 
      39              :     return bytes_read;
      40              : }
      41              : 
      42            0 : static ssize_t _bf_send_from_buff(int fd, void *buf, size_t buf_len)
      43              : {
      44              :     ssize_t bytes_sent = 0;
      45              :     ssize_t r;
      46              : 
      47            0 :     bf_assert(buf);
      48              : 
      49            0 :     while ((size_t)bytes_sent < buf_len) {
      50            0 :         r = write(fd, buf + bytes_sent, buf_len - bytes_sent);
      51            0 :         if (r < 0) {
      52            0 :             (void)fprintf(stderr, "can't write to socket: %s\n",
      53            0 :                           bf_strerror(errno));
      54            0 :             return -errno;
      55              :         }
      56              : 
      57            0 :         bytes_sent += r;
      58              :     }
      59              : 
      60              :     return bytes_sent;
      61              : }
      62              : 
      63            0 : int bf_send_request(int fd, const struct bf_request *request)
      64              : {
      65              :     ssize_t r;
      66              : 
      67            0 :     bf_assert(request);
      68              : 
      69            0 :     r = _bf_send_from_buff(fd, (void *)request, bf_request_size(request));
      70            0 :     if (r < 0) {
      71            0 :         (void)fprintf(stderr, "Failed to send request: %s\n",
      72            0 :                       bf_strerror(errno));
      73            0 :         return -errno;
      74              :     }
      75              : 
      76            0 :     if ((size_t)r != bf_request_size(request)) {
      77            0 :         (void)fprintf(stderr,
      78              :                       "Failed to send request: %lu bytes sent, %ld expected\n",
      79              :                       (size_t)r, bf_request_size(request));
      80            0 :         return -EIO;
      81              :     }
      82              : 
      83              :     return 0;
      84              : }
      85              : 
      86            0 : int bf_recv_request(int fd, struct bf_request **request)
      87              : {
      88              :     struct bf_request req;
      89            0 :     _cleanup_bf_request_ struct bf_request *_request = NULL;
      90              :     ssize_t r;
      91              : 
      92            0 :     bf_assert(request);
      93              : 
      94            0 :     r = _bf_recv_in_buff(fd, &req, sizeof(req));
      95            0 :     if (r < 0)
      96            0 :         return (int)r;
      97              : 
      98            0 :     if ((size_t)r != sizeof(req)) {
      99            0 :         (void)fprintf(stderr,
     100              :                       "failed to read request: %lu bytes read, %lu expected\n",
     101              :                       (size_t)r, sizeof(req));
     102            0 :         return -EIO;
     103              :     }
     104              : 
     105            0 :     _request = malloc(bf_request_size(&req));
     106            0 :     if (!_request) {
     107            0 :         (void)fprintf(stderr, "failed to allocate request: %s\n",
     108            0 :                       bf_strerror(errno));
     109            0 :         return -errno;
     110              :     }
     111              : 
     112            0 :     memcpy(_request, &req, sizeof(req));
     113              : 
     114            0 :     r = _bf_recv_in_buff(fd, _request->data, _request->data_len);
     115            0 :     if (r < 0)
     116            0 :         return (int)r;
     117              : 
     118            0 :     if ((size_t)r != _request->data_len) {
     119            0 :         (void)fprintf(stderr,
     120              :                       "failed to read request: %lu bytes read, %lu expected\n",
     121              :                       (size_t)r, _request->data_len);
     122            0 :         return -EIO;
     123              :     }
     124              : 
     125            0 :     *request = TAKE_PTR(_request);
     126              : 
     127            0 :     return 0;
     128              : }
     129              : 
     130            0 : int bf_send_response(int fd, struct bf_response *response)
     131              : {
     132              :     ssize_t r;
     133              : 
     134            0 :     bf_assert(response);
     135              : 
     136            0 :     r = _bf_send_from_buff(fd, (void *)response, bf_response_size(response));
     137            0 :     if (r < 0) {
     138            0 :         (void)fprintf(stderr, "Failed to send response: %s\n",
     139            0 :                       bf_strerror(errno));
     140            0 :         return -errno;
     141              :     }
     142              : 
     143            0 :     if ((size_t)r != bf_response_size(response)) {
     144            0 :         (void)fprintf(stderr,
     145              :                       "Failed to send response: %lu bytes sent, %ld expected\n",
     146              :                       r, bf_response_size(response));
     147            0 :         return -EIO;
     148              :     }
     149              : 
     150              :     return 0;
     151              : }
     152              : 
     153            0 : int bf_recv_response(int fd, struct bf_response **response)
     154              : {
     155              :     struct bf_response res;
     156            0 :     _cleanup_bf_response_ struct bf_response *_response = NULL;
     157              :     ssize_t r;
     158              : 
     159            0 :     bf_assert(response);
     160              : 
     161            0 :     r = _bf_recv_in_buff(fd, &res, sizeof(res));
     162            0 :     if (r < 0)
     163            0 :         return -errno;
     164              : 
     165            0 :     if ((size_t)r != sizeof(res)) {
     166            0 :         (void)fprintf(stderr,
     167              :                       "failed to read response: %lu bytes read, %lu expected\n",
     168              :                       (size_t)r, sizeof(res));
     169            0 :         return -EIO;
     170              :     }
     171              : 
     172            0 :     _response = malloc(bf_response_size(&res));
     173            0 :     if (!_response) {
     174            0 :         (void)fprintf(stderr, "failed to allocate response: %s\n",
     175            0 :                       bf_strerror(errno));
     176            0 :         return -errno;
     177              :     }
     178              : 
     179            0 :     memcpy(_response, &res, sizeof(res));
     180              : 
     181            0 :     r = _bf_recv_in_buff(fd, _response->data, _response->data_len);
     182            0 :     if (r < 0)
     183            0 :         return (int)r;
     184              : 
     185            0 :     if (_response->type == BF_RES_SUCCESS && (size_t)r != _response->data_len) {
     186            0 :         (void)fprintf(stderr,
     187              :                       "failed to read response: %lu bytes read, %lu expected\n",
     188              :                       (size_t)r, _response->data_len);
     189            0 :         return -EIO;
     190              :     }
     191              : 
     192            0 :     *response = TAKE_PTR(_response);
     193              : 
     194            0 :     return 0;
     195              : }
     196              : 
     197            0 : int bf_ensure_dir(const char *dir)
     198              : {
     199              :     struct stat stats;
     200              :     int r;
     201              : 
     202            0 :     bf_assert(dir);
     203              : 
     204            0 :     r = access(dir, R_OK | W_OK);
     205            0 :     if (r && errno == ENOENT) {
     206            0 :         if (mkdir(dir, BF_PERM_755) == 0)
     207              :             return 0;
     208              : 
     209            0 :         return bf_err_r(errno, "failed to create directory '%s'", dir);
     210              :     }
     211              :     if (r)
     212            0 :         return bf_err_r(errno, "no R/W permissions on '%s'", dir);
     213              : 
     214            0 :     if (stat(dir, &stats) != 0 || !S_ISDIR(stats.st_mode))
     215            0 :         return bf_err_r(-EINVAL, "'%s' is not a valid directory", dir);
     216              : 
     217              :     return 0;
     218              : }
        

Generated by: LCOV version 2.0-1