diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 17:47:29 +0000 |
commit | 4f5791ebd03eaec1c7da0865a383175b05102712 (patch) | |
tree | 8ce7b00f7a76baa386372422adebbe64510812d4 /source3/lib/util_file.c | |
parent | Initial commit. (diff) | |
download | samba-4f5791ebd03eaec1c7da0865a383175b05102712.tar.xz samba-4f5791ebd03eaec1c7da0865a383175b05102712.zip |
Adding upstream version 2:4.17.12+dfsg.upstream/2%4.17.12+dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'source3/lib/util_file.c')
-rw-r--r-- | source3/lib/util_file.c | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c new file mode 100644 index 0000000..ba96eee --- /dev/null +++ b/source3/lib/util_file.c @@ -0,0 +1,187 @@ +/* + * Unix SMB/CIFS implementation. + * SMB parameters and setup + * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995. + * + * This program is free software; you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 3 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "replace.h" +#include "lib/util_file.h" +#include "lib/util/debug.h" +#include "lib/util/samba_util.h" +#include "lib/util/sys_rw.h" +#include "lib/util/sys_popen.h" +#include "lib/async_req/async_sock.h" +#include "lib/util/tevent_unix.h" + +struct file_ploadv_state { + struct tevent_context *ev; + struct tevent_req *subreq; + size_t maxsize; + int fd; + uint8_t *buf; +}; + +static void file_ploadv_cleanup_fn( + struct tevent_req *req, enum tevent_req_state req_state); +static void file_ploadv_readable(struct tevent_req *subreq); + +struct tevent_req *file_ploadv_send(TALLOC_CTX *mem_ctx, + struct tevent_context *ev, + char * const argl[], size_t maxsize) +{ + struct tevent_req *req = NULL; + struct file_ploadv_state *state = NULL; + + req = tevent_req_create(mem_ctx, &state, struct file_ploadv_state); + if (req == NULL) { + return NULL; + } + state->ev = ev; + state->maxsize = maxsize; + + state->fd = sys_popenv(argl); + if (state->fd == -1) { + tevent_req_error(req, errno); + return tevent_req_post(req, ev); + } + tevent_req_set_cleanup_fn(req, file_ploadv_cleanup_fn); + + state->subreq = wait_for_read_send(state, state->ev, state->fd, false); + if (tevent_req_nomem(state->subreq, req)) { + return tevent_req_post(req, ev); + } + tevent_req_set_callback(state->subreq, file_ploadv_readable, req); + return req; +} + +static void file_ploadv_cleanup_fn( + struct tevent_req *req, enum tevent_req_state req_state) +{ + struct file_ploadv_state *state = tevent_req_data( + req, struct file_ploadv_state); + + TALLOC_FREE(state->subreq); + if (state->fd != -1) { + sys_pclose(state->fd); + state->fd = -1; + } +} + +static void file_ploadv_readable(struct tevent_req *subreq) +{ + struct tevent_req *req = tevent_req_callback_data( + subreq, struct tevent_req); + struct file_ploadv_state *state = tevent_req_data( + req, struct file_ploadv_state); + uint8_t buf[1024]; + uint8_t *tmp; + ssize_t nread; + size_t bufsize; + int err; + bool ok; + + ok = wait_for_read_recv(subreq, &err); + TALLOC_FREE(subreq); + state->subreq = NULL; + if (!ok) { + tevent_req_error(req, err); + return; + } + + nread = sys_read(state->fd, buf, sizeof(buf)); + if (nread == -1) { + tevent_req_error(req, errno); + return; + } + if (nread == 0) { + tevent_req_done(req); + return; + } + + bufsize = talloc_get_size(state->buf); + if (bufsize > 0) { + /* + * Last round we've added the trailing '\0'. Remove it + * for this round. + */ + bufsize -= 1; + } + + if (((bufsize + nread) < bufsize) || + ((bufsize + nread + 1) < bufsize)) { + /* overflow */ + tevent_req_error(req, EMSGSIZE); + return; + } + + if ((state->maxsize != 0) && ((bufsize + nread) > state->maxsize)) { + tevent_req_error(req, EMSGSIZE); + return; + } + + tmp = talloc_realloc(state, state->buf, uint8_t, bufsize + nread + 1); + if (tevent_req_nomem(tmp, req)) { + return; + } + state->buf = tmp; + + memcpy(state->buf + bufsize, buf, nread); + state->buf[bufsize+nread] = '\0'; + + state->subreq = wait_for_read_send(state, state->ev, state->fd, false); + if (tevent_req_nomem(state->subreq, req)) { + return; + } + tevent_req_set_callback(state->subreq, file_ploadv_readable, req); +} + +int file_ploadv_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx, + uint8_t **buf) +{ + struct file_ploadv_state *state = tevent_req_data( + req, struct file_ploadv_state); + int err; + + if (tevent_req_is_unix_error(req, &err)) { + return err; + } + *buf = talloc_move(mem_ctx, &state->buf); + + tevent_req_received(req); + + return 0; +} + + +/** + Load a pipe into memory and return an array of pointers to lines in the data + must be freed with TALLOC_FREE. +**/ + +char **file_lines_ploadv(TALLOC_CTX *mem_ctx, + char * const argl[], + int *numlines) +{ + char *p = NULL; + size_t size; + + p = file_ploadv(argl, &size); + if (!p) { + return NULL; + } + + return file_lines_parse(p, size, numlines, mem_ctx); +} |