s3: smbd: Make extract_snapshot_token() a wrapper for extract_snapshot_token_internal().
[Samba.git] / source3 / lib / util_file.c
blobba96eeee36575b10ee84490a2248190778301bb2
1 /*
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)
9 * any later version.
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.
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/>.
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"
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;
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);
49 if (req == NULL) {
50 return NULL;
52 state->ev = ev;
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);
67 return 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);
79 state->fd = -1;
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);
89 uint8_t buf[1024];
90 uint8_t *tmp;
91 ssize_t nread;
92 size_t bufsize;
93 int err;
94 bool ok;
96 ok = wait_for_read_recv(subreq, &err);
97 TALLOC_FREE(subreq);
98 state->subreq = NULL;
99 if (!ok) {
100 tevent_req_error(req, err);
101 return;
104 nread = sys_read(state->fd, buf, sizeof(buf));
105 if (nread == -1) {
106 tevent_req_error(req, errno);
107 return;
109 if (nread == 0) {
110 tevent_req_done(req);
111 return;
114 bufsize = talloc_get_size(state->buf);
115 if (bufsize > 0) {
117 * Last round we've added the trailing '\0'. Remove it
118 * for this round.
120 bufsize -= 1;
123 if (((bufsize + nread) < bufsize) ||
124 ((bufsize + nread + 1) < bufsize)) {
125 /* overflow */
126 tevent_req_error(req, EMSGSIZE);
127 return;
130 if ((state->maxsize != 0) && ((bufsize + nread) > state->maxsize)) {
131 tevent_req_error(req, EMSGSIZE);
132 return;
135 tmp = talloc_realloc(state, state->buf, uint8_t, bufsize + nread + 1);
136 if (tevent_req_nomem(tmp, req)) {
137 return;
139 state->buf = tmp;
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)) {
146 return;
148 tevent_req_set_callback(state->subreq, file_ploadv_readable, req);
151 int file_ploadv_recv(struct tevent_req *req, TALLOC_CTX *mem_ctx,
152 uint8_t **buf)
154 struct file_ploadv_state *state = tevent_req_data(
155 req, struct file_ploadv_state);
156 int err;
158 if (tevent_req_is_unix_error(req, &err)) {
159 return err;
161 *buf = talloc_move(mem_ctx, &state->buf);
163 tevent_req_received(req);
165 return 0;
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,
175 char * const argl[],
176 int *numlines)
178 char *p = NULL;
179 size_t size;
181 p = file_ploadv(argl, &size);
182 if (!p) {
183 return NULL;
186 return file_lines_parse(p, size, numlines, mem_ctx);