python: Remove unused variable ‘machinesid’
[Samba.git] / libcli / util / tstream.c
blob95e31cab34aa4095e57a75e69f2745bf1ef8f4af
1 /*
2 * Unix SMB/CIFS implementation.
4 * Copyright (C) Stefan Metzmacher 2009
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include <tevent.h>
22 #include "system/filesys.h"
23 #include "system/network.h"
24 #include "../lib/tsocket/tsocket.h"
25 #include "../libcli/util/tstream.h"
26 #include "../lib/util/tevent_ntstatus.h"
28 struct tstream_read_pdu_blob_state {
29 /* this structs are owned by the caller */
30 struct {
31 struct tevent_context *ev;
32 struct tstream_context *stream;
33 tstream_read_pdu_blob_full_fn_t *full_fn;
34 void *full_private;
35 } caller;
37 DATA_BLOB pdu_blob;
38 struct iovec tmp_vector;
41 static void tstream_read_pdu_blob_done(struct tevent_req *subreq);
43 struct tevent_req *tstream_read_pdu_blob_send(TALLOC_CTX *mem_ctx,
44 struct tevent_context *ev,
45 struct tstream_context *stream,
46 size_t initial_read_size,
47 tstream_read_pdu_blob_full_fn_t *full_fn,
48 void *full_private)
50 struct tevent_req *req;
51 struct tstream_read_pdu_blob_state *state;
52 struct tevent_req *subreq;
53 uint8_t *buf;
55 req = tevent_req_create(mem_ctx, &state,
56 struct tstream_read_pdu_blob_state);
57 if (!req) {
58 return NULL;
61 state->caller.ev = ev;
62 state->caller.stream = stream;
63 state->caller.full_fn = full_fn;
64 state->caller.full_private = full_private;
66 if (initial_read_size == 0) {
67 tevent_req_error(req, EINVAL);
68 return tevent_req_post(req, ev);
71 buf = talloc_array(state, uint8_t, initial_read_size);
72 if (tevent_req_nomem(buf, req)) {
73 return tevent_req_post(req, ev);
75 state->pdu_blob.data = buf;
76 state->pdu_blob.length = initial_read_size;
78 state->tmp_vector.iov_base = (char *) buf;
79 state->tmp_vector.iov_len = initial_read_size;
81 subreq = tstream_readv_send(state, ev, stream, &state->tmp_vector, 1);
82 if (tevent_req_nomem(subreq, req)) {
83 return tevent_req_post(req, ev);
85 tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
87 return req;
90 static void tstream_read_pdu_blob_done(struct tevent_req *subreq)
92 struct tevent_req *req =
93 tevent_req_callback_data(subreq,
94 struct tevent_req);
95 struct tstream_read_pdu_blob_state *state =
96 tevent_req_data(req,
97 struct tstream_read_pdu_blob_state);
98 ssize_t ret;
99 int sys_errno;
100 size_t old_buf_size = state->pdu_blob.length;
101 size_t new_buf_size = 0;
102 size_t pdu_size = 0;
103 NTSTATUS status;
104 uint8_t *buf;
106 ret = tstream_readv_recv(subreq, &sys_errno);
107 TALLOC_FREE(subreq);
108 if (ret == -1) {
109 status = map_nt_error_from_unix_common(sys_errno);
110 tevent_req_nterror(req, status);
111 return;
114 status = state->caller.full_fn(state->caller.stream,
115 state->caller.full_private,
116 state->pdu_blob, &pdu_size);
117 if (NT_STATUS_IS_OK(status)) {
118 tevent_req_done(req);
119 return;
120 } else if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
121 /* more to get */
122 if (pdu_size > 0) {
123 new_buf_size = pdu_size;
124 } else {
125 /* we don't know the size yet, so get one more byte */
126 new_buf_size = old_buf_size + 1;
128 } else if (!NT_STATUS_IS_OK(status)) {
129 tevent_req_nterror(req, status);
130 return;
133 if (new_buf_size <= old_buf_size) {
134 tevent_req_nterror(req, NT_STATUS_INVALID_BUFFER_SIZE);
135 return;
138 buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, new_buf_size);
139 if (tevent_req_nomem(buf, req)) {
140 return;
142 state->pdu_blob.data = buf;
143 state->pdu_blob.length = new_buf_size;
145 state->tmp_vector.iov_base = (char *) (buf + old_buf_size);
146 state->tmp_vector.iov_len = new_buf_size - old_buf_size;
148 subreq = tstream_readv_send(state,
149 state->caller.ev,
150 state->caller.stream,
151 &state->tmp_vector,
153 if (tevent_req_nomem(subreq, req)) {
154 return;
156 tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
159 NTSTATUS tstream_read_pdu_blob_recv(struct tevent_req *req,
160 TALLOC_CTX *mem_ctx,
161 DATA_BLOB *pdu_blob)
163 struct tstream_read_pdu_blob_state *state = tevent_req_data(req,
164 struct tstream_read_pdu_blob_state);
165 NTSTATUS status;
167 if (tevent_req_is_nterror(req, &status)) {
168 tevent_req_received(req);
169 return status;
172 *pdu_blob = state->pdu_blob;
173 talloc_steal(mem_ctx, pdu_blob->data);
175 tevent_req_received(req);
176 return NT_STATUS_OK;
179 NTSTATUS tstream_full_request_u32(struct tstream_context *stream,
180 void *private_data,
181 DATA_BLOB blob, size_t *size)
183 if (blob.length < 4) {
184 return STATUS_MORE_ENTRIES;
186 *size = 4 + RIVAL(blob.data, 0);
187 if (*size > blob.length) {
188 return STATUS_MORE_ENTRIES;
190 return NT_STATUS_OK;
193 NTSTATUS tstream_full_request_u16(struct tstream_context *stream,
194 void *private_data,
195 DATA_BLOB blob, size_t *size)
197 if (blob.length < 2) {
198 return STATUS_MORE_ENTRIES;
200 *size = 2 + RSVAL(blob.data, 0);
201 if (*size > blob.length) {
202 return STATUS_MORE_ENTRIES;
204 return NT_STATUS_OK;