LCOV - code coverage report
Current view: top level - source3/lib - util_file.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 58 82 70.7 %
Date: 2024-05-31 13:13:24 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/util_file.h"
      22             : #include "source3/lib/util_file.h"
      23             : #include "lib/util/debug.h"
      24             : #include "lib/util/samba_util.h"
      25             : #include "lib/util/sys_rw.h"
      26             : #include "lib/util/sys_popen.h"
      27             : #include "lib/async_req/async_sock.h"
      28             : #include "lib/util/tevent_unix.h"
      29             : 
      30             : struct file_ploadv_state {
      31             :         struct tevent_context *ev;
      32             :         struct tevent_req *subreq;
      33             :         size_t maxsize;
      34             :         int fd;
      35             :         uint8_t *buf;
      36             : };
      37             : 
      38             : static void file_ploadv_cleanup_fn(
      39             :         struct tevent_req *req, enum tevent_req_state req_state);
      40             : static void file_ploadv_readable(struct tevent_req *subreq);
      41             : 
      42         744 : struct tevent_req *file_ploadv_send(TALLOC_CTX *mem_ctx,
      43             :                                    struct tevent_context *ev,
      44             :                                    char * const argl[], size_t maxsize)
      45             : {
      46         744 :         struct tevent_req *req = NULL;
      47         744 :         struct file_ploadv_state *state = NULL;
      48             : 
      49         744 :         req = tevent_req_create(mem_ctx, &state, struct file_ploadv_state);
      50         744 :         if (req == NULL) {
      51           0 :                 return NULL;
      52             :         }
      53         744 :         state->ev = ev;
      54         744 :         state->maxsize = maxsize;
      55             : 
      56         744 :         state->fd = sys_popenv(argl);
      57         744 :         if (state->fd == -1) {
      58           0 :                 tevent_req_error(req, errno);
      59           0 :                 return tevent_req_post(req, ev);
      60             :         }
      61         744 :         tevent_req_set_cleanup_fn(req, file_ploadv_cleanup_fn);
      62             : 
      63         744 :         state->subreq = wait_for_read_send(state, state->ev, state->fd, false);
      64         744 :         if (tevent_req_nomem(state->subreq, req)) {
      65           0 :                 return tevent_req_post(req, ev);
      66             :         }
      67         744 :         tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
      68         744 :         return req;
      69             : }
      70             : 
      71        1488 : static void file_ploadv_cleanup_fn(
      72             :         struct tevent_req *req, enum tevent_req_state req_state)
      73             : {
      74        1488 :         struct file_ploadv_state *state = tevent_req_data(
      75             :                 req, struct file_ploadv_state);
      76             : 
      77        1488 :         TALLOC_FREE(state->subreq);
      78        1488 :         if (state->fd != -1) {
      79         744 :                 sys_pclose(state->fd);
      80         744 :                 state->fd = -1;
      81             :         }
      82        1488 : }
      83             : 
      84        1488 : static void file_ploadv_readable(struct tevent_req *subreq)
      85             : {
      86        1488 :         struct tevent_req *req = tevent_req_callback_data(
      87             :                 subreq, struct tevent_req);
      88        1488 :         struct file_ploadv_state *state = tevent_req_data(
      89             :                 req, struct file_ploadv_state);
      90           0 :         uint8_t buf[1024];
      91           0 :         uint8_t *tmp;
      92           0 :         ssize_t nread;
      93           0 :         size_t bufsize;
      94           0 :         int err;
      95           0 :         bool ok;
      96             : 
      97        1488 :         ok = wait_for_read_recv(subreq, &err);
      98        1488 :         TALLOC_FREE(subreq);
      99        1488 :         state->subreq = NULL;
     100        1488 :         if (!ok) {
     101           0 :                 tevent_req_error(req, err);
     102         744 :                 return;
     103             :         }
     104             : 
     105        1488 :         nread = sys_read(state->fd, buf, sizeof(buf));
     106        1488 :         if (nread == -1) {
     107           0 :                 tevent_req_error(req, errno);
     108           0 :                 return;
     109             :         }
     110        1488 :         if (nread == 0) {
     111         744 :                 tevent_req_done(req);
     112         744 :                 return;
     113             :         }
     114             : 
     115         744 :         bufsize = talloc_get_size(state->buf);
     116         744 :         if (bufsize > 0) {
     117             :                 /*
     118             :                  * Last round we've added the trailing '\0'. Remove it
     119             :                  * for this round.
     120             :                  */
     121           0 :                 bufsize -= 1;
     122             :         }
     123             : 
     124         744 :         if (((bufsize + nread) < bufsize) ||
     125         744 :             ((bufsize + nread + 1) < bufsize)) {
     126             :                 /* overflow */
     127           0 :                 tevent_req_error(req, EMSGSIZE);
     128           0 :                 return;
     129             :         }
     130             : 
     131         744 :         if ((state->maxsize != 0) && ((bufsize + nread) > state->maxsize)) {
     132           0 :                 tevent_req_error(req, EMSGSIZE);
     133           0 :                 return;
     134             :         }
     135             : 
     136         744 :         tmp = talloc_realloc(state, state->buf, uint8_t, bufsize + nread + 1);
     137         744 :         if (tevent_req_nomem(tmp, req)) {
     138           0 :                 return;
     139             :         }
     140         744 :         state->buf = tmp;
     141             : 
     142         744 :         memcpy(state->buf + bufsize, buf, nread);
     143         744 :         state->buf[bufsize+nread] = '\0';
     144             : 
     145         744 :         state->subreq = wait_for_read_send(state, state->ev, state->fd, false);
     146         744 :         if (tevent_req_nomem(state->subreq, req)) {
     147           0 :                 return;
     148             :         }
     149         744 :         tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
     150             : }
     151             : 
     152         744 : int file_ploadv_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
     153             :                     uint8_t **buf)
     154             : {
     155         744 :         struct file_ploadv_state *state = tevent_req_data(
     156             :                 req, struct file_ploadv_state);
     157           0 :         int err;
     158             : 
     159         744 :         if (tevent_req_is_unix_error(req, &err)) {
     160           0 :                 return err;
     161             :         }
     162         744 :         *buf = talloc_move(mem_ctx, &state->buf);
     163             : 
     164         744 :         tevent_req_received(req);
     165             : 
     166         744 :         return 0;
     167             : }
     168             : 
     169             : 
     170             : /**
     171             :  Load a pipe into memory and return an array of pointers to lines in the data
     172             :  must be freed with TALLOC_FREE.
     173             : **/
     174             : 
     175         930 : char **file_lines_ploadv(TALLOC_CTX *mem_ctx,
     176             :                         char * const argl[],
     177             :                         int *numlines)
     178             : {
     179         930 :         char *p = NULL;
     180           0 :         size_t size;
     181             : 
     182         930 :         p = file_ploadv(argl, &size);
     183         930 :         if (!p) {
     184           0 :                 return NULL;
     185             :         }
     186             : 
     187         930 :         return file_lines_parse(p, size, numlines, mem_ctx);
     188             : }

Generated by: LCOV version 1.14