2 * Unix SMB/CIFS implementation.
3 * SMB parameters and setup
4 * Copyright (C) Andrew Tridgell 1992-1998 Modified by Jeremy Allison 1995.
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)
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
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/>.
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"
29 struct file_ploadv_state {
30 struct tevent_context *ev;
31 struct tevent_req *subreq;
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);
41 struct tevent_req *file_ploadv_send(TALLOC_CTX *mem_ctx,
42 struct tevent_context *ev,
43 char * const argl[], size_t maxsize)
45 struct tevent_req *req = NULL;
46 struct file_ploadv_state *state = NULL;
48 req = tevent_req_create(mem_ctx, &state, struct file_ploadv_state);
53 state->maxsize = maxsize;
55 state->fd = sys_popenv(argl);
56 if (state->fd == -1) {
57 tevent_req_error(req, errno);
58 return tevent_req_post(req, ev);
60 tevent_req_set_cleanup_fn(req, file_ploadv_cleanup_fn);
62 state->subreq = wait_for_read_send(state, state->ev, state->fd, false);
63 if (tevent_req_nomem(state->subreq, req)) {
64 return tevent_req_post(req, ev);
66 tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
70 static void file_ploadv_cleanup_fn(
71 struct tevent_req *req, enum tevent_req_state req_state)
73 struct file_ploadv_state *state = tevent_req_data(
74 req, struct file_ploadv_state);
76 TALLOC_FREE(state->subreq);
77 if (state->fd != -1) {
78 sys_pclose(state->fd);
83 static void file_ploadv_readable(struct tevent_req *subreq)
85 struct tevent_req *req = tevent_req_callback_data(
86 subreq, struct tevent_req);
87 struct file_ploadv_state *state = tevent_req_data(
88 req, struct file_ploadv_state);
96 ok = wait_for_read_recv(subreq, &err);
100 tevent_req_error(req, err);
104 nread = sys_read(state->fd, buf, sizeof(buf));
106 tevent_req_error(req, errno);
110 tevent_req_done(req);
114 bufsize = talloc_get_size(state->buf);
117 * Last round we've added the trailing '\0'. Remove it
123 if (((bufsize + nread) < bufsize) ||
124 ((bufsize + nread + 1) < bufsize)) {
126 tevent_req_error(req, EMSGSIZE);
130 if ((state->maxsize != 0) && ((bufsize + nread) > state->maxsize)) {
131 tevent_req_error(req, EMSGSIZE);
135 tmp = talloc_realloc(state, state->buf, uint8_t, bufsize + nread + 1);
136 if (tevent_req_nomem(tmp, req)) {
141 memcpy(state->buf + bufsize, buf, nread);
142 state->buf[bufsize+nread] = '\0';
144 state->subreq = wait_for_read_send(state, state->ev, state->fd, false);
145 if (tevent_req_nomem(state->subreq, req)) {
148 tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
151 int file_ploadv_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
154 struct file_ploadv_state *state = tevent_req_data(
155 req, struct file_ploadv_state);
158 if (tevent_req_is_unix_error(req, &err)) {
161 *buf = talloc_move(mem_ctx, &state->buf);
163 tevent_req_received(req);
170 Load a pipe into memory and return an array of pointers to lines in the data
171 must be freed with TALLOC_FREE.
174 char **file_lines_ploadv(TALLOC_CTX *mem_ctx,
181 p = file_ploadv(argl, &size);
186 return file_lines_parse(p, size, numlines, mem_ctx);