LCOV - code coverage report
Current view: top level - source3/lib - util_file.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 58 82 70.7 %
Date: 2024-02-28 12:06:22 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /*
       2             :  * Unix SMB/CIFS implementation.
       3             :  * SMB parameters and setup
       4             :  * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
       5             :  *
       6             :  * This program is free software; you can redistribute it and/or modify it under
       7             :  * the terms of the GNU General Public License as published by the Free
       8             :  * Software Foundation; either version 3 of the License, or (at your option)
       9             :  * any later version.
      10             :  *
      11             :  * This program is distributed in the hope that it will be useful, but WITHOUT
      12             :  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13             :  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
      14             :  * more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along with
      17             :  * this program; if not, see <http://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #include "replace.h"
      21             : #include "lib/util_file.h"
      22             : #include "lib/util/debug.h"
      23             : #include "lib/util/samba_util.h"
      24             : #include "lib/util/sys_rw.h"
      25             : #include "lib/util/sys_popen.h"
      26             : #include "lib/async_req/async_sock.h"
      27             : #include "lib/util/tevent_unix.h"
      28             : 
      29             : struct file_ploadv_state {
      30             :         struct tevent_context *ev;
      31             :         struct tevent_req *subreq;
      32             :         size_t maxsize;
      33             :         int fd;
      34             :         uint8_t *buf;
      35             : };
      36             : 
      37             : static void file_ploadv_cleanup_fn(
      38             :         struct tevent_req *req, enum tevent_req_state req_state);
      39             : static void file_ploadv_readable(struct tevent_req *subreq);
      40             : 
      41         784 : struct tevent_req *file_ploadv_send(TALLOC_CTX *mem_ctx,
      42             :                                    struct tevent_context *ev,
      43             :                                    char * const argl[], size_t maxsize)
      44             : {
      45         784 :         struct tevent_req *req = NULL;
      46         784 :         struct file_ploadv_state *state = NULL;
      47             : 
      48         784 :         req = tevent_req_create(mem_ctx, &state, struct file_ploadv_state);
      49         784 :         if (req == NULL) {
      50           0 :                 return NULL;
      51             :         }
      52         784 :         state->ev = ev;
      53         784 :         state->maxsize = maxsize;
      54             : 
      55         784 :         state->fd = sys_popenv(argl);
      56         784 :         if (state->fd == -1) {
      57           0 :                 tevent_req_error(req, errno);
      58           0 :                 return tevent_req_post(req, ev);
      59             :         }
      60         784 :         tevent_req_set_cleanup_fn(req, file_ploadv_cleanup_fn);
      61             : 
      62         784 :         state->subreq = wait_for_read_send(state, state->ev, state->fd, false);
      63         784 :         if (tevent_req_nomem(state->subreq, req)) {
      64           0 :                 return tevent_req_post(req, ev);
      65             :         }
      66         784 :         tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
      67         784 :         return req;
      68             : }
      69             : 
      70        1568 : static void file_ploadv_cleanup_fn(
      71             :         struct tevent_req *req, enum tevent_req_state req_state)
      72             : {
      73        1568 :         struct file_ploadv_state *state = tevent_req_data(
      74             :                 req, struct file_ploadv_state);
      75             : 
      76        1568 :         TALLOC_FREE(state->subreq);
      77        1568 :         if (state->fd != -1) {
      78         784 :                 sys_pclose(state->fd);
      79         784 :                 state->fd = -1;
      80             :         }
      81        1568 : }
      82             : 
      83        1568 : static void file_ploadv_readable(struct tevent_req *subreq)
      84             : {
      85        1568 :         struct tevent_req *req = tevent_req_callback_data(
      86             :                 subreq, struct tevent_req);
      87        1568 :         struct file_ploadv_state *state = tevent_req_data(
      88             :                 req, struct file_ploadv_state);
      89           0 :         uint8_t buf[1024];
      90           0 :         uint8_t *tmp;
      91           0 :         ssize_t nread;
      92           0 :         size_t bufsize;
      93           0 :         int err;
      94           0 :         bool ok;
      95             : 
      96        1568 :         ok = wait_for_read_recv(subreq, &err);
      97        1568 :         TALLOC_FREE(subreq);
      98        1568 :         state->subreq = NULL;
      99        1568 :         if (!ok) {
     100           0 :                 tevent_req_error(req, err);
     101         784 :                 return;
     102             :         }
     103             : 
     104        1568 :         nread = sys_read(state->fd, buf, sizeof(buf));
     105        1568 :         if (nread == -1) {
     106           0 :                 tevent_req_error(req, errno);
     107           0 :                 return;
     108             :         }
     109        1568 :         if (nread == 0) {
     110         784 :                 tevent_req_done(req);
     111         784 :                 return;
     112             :         }
     113             : 
     114         784 :         bufsize = talloc_get_size(state->buf);
     115         784 :         if (bufsize > 0) {
     116             :                 /*
     117             :                  * Last round we've added the trailing '\0'. Remove it
     118             :                  * for this round.
     119             :                  */
     120           0 :                 bufsize -= 1;
     121             :         }
     122             : 
     123         784 :         if (((bufsize + nread) < bufsize) ||
     124         784 :             ((bufsize + nread + 1) < bufsize)) {
     125             :                 /* overflow */
     126           0 :                 tevent_req_error(req, EMSGSIZE);
     127           0 :                 return;
     128             :         }
     129             : 
     130         784 :         if ((state->maxsize != 0) && ((bufsize + nread) > state->maxsize)) {
     131           0 :                 tevent_req_error(req, EMSGSIZE);
     132           0 :                 return;
     133             :         }
     134             : 
     135         784 :         tmp = talloc_realloc(state, state->buf, uint8_t, bufsize + nread + 1);
     136         784 :         if (tevent_req_nomem(tmp, req)) {
     137           0 :                 return;
     138             :         }
     139         784 :         state->buf = tmp;
     140             : 
     141         784 :         memcpy(state->buf + bufsize, buf, nread);
     142         784 :         state->buf[bufsize+nread] = '\0';
     143             : 
     144         784 :         state->subreq = wait_for_read_send(state, state->ev, state->fd, false);
     145         784 :         if (tevent_req_nomem(state->subreq, req)) {
     146           0 :                 return;
     147             :         }
     148         784 :         tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
     149             : }
     150             : 
     151         784 : int file_ploadv_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     152             :                     uint8_t **buf)
     153             : {
     154         784 :         struct file_ploadv_state *state = tevent_req_data(
     155             :                 req, struct file_ploadv_state);
     156           0 :         int err;
     157             : 
     158         784 :         if (tevent_req_is_unix_error(req, &err)) {
     159           0 :                 return err;
     160             :         }
     161         784 :         *buf = talloc_move(mem_ctx, &state->buf);
     162             : 
     163         784 :         tevent_req_received(req);
     164             : 
     165         784 :         return 0;
     166             : }
     167             : 
     168             : 
     169             : /**
     170             :  Load a pipe into memory and return an array of pointers to lines in the data
     171             :  must be freed with TALLOC_FREE.
     172             : **/
     173             : 
     174        1213 : char **file_lines_ploadv(TALLOC_CTX *mem_ctx,
     175             :                         char * const argl[],
     176             :                         int *numlines)
     177             : {
     178        1213 :         char *p = NULL;
     179           0 :         size_t size;
     180             : 
     181        1213 :         p = file_ploadv(argl, &size);
     182        1213 :         if (!p) {
     183           0 :                 return NULL;
     184             :         }
     185             : 
     186        1213 :         return file_lines_parse(p, size, numlines, mem_ctx);
     187             : }

Generated by: LCOV version 1.14