s4-drs: Add DRSUAPI_DRS_NONGC_RO_REP bit to DRS_OPTIONS
[Samba/fernandojvsilva.git] / libcli / util / tstream.c
blob8911c5d541ad512242f9e27251f1362bcd75a057
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 NTSTATUS (*full_fn)(void *private_data,
34 DATA_BLOB blob,
35 size_t *packet_size);
36 void *full_private;
37 } caller;
39 DATA_BLOB pdu_blob;
40 struct iovec tmp_vector;
43 static void tstream_read_pdu_blob_done(struct tevent_req *subreq);
45 struct tevent_req *tstream_read_pdu_blob_send(TALLOC_CTX *mem_ctx,
46 struct tevent_context *ev,
47 struct tstream_context *stream,
48 size_t initial_read_size,
49 NTSTATUS (*full_fn)(void *private_data,
50 DATA_BLOB blob,
51 size_t *packet_size),
52 void *full_private)
54 struct tevent_req *req;
55 struct tstream_read_pdu_blob_state *state;
56 struct tevent_req *subreq;
57 uint8_t *buf;
59 req = tevent_req_create(mem_ctx, &state,
60 struct tstream_read_pdu_blob_state);
61 if (!req) {
62 return NULL;
65 state->caller.ev = ev;
66 state->caller.stream = stream;
67 state->caller.full_fn = full_fn;
68 state->caller.full_private = full_private;
70 if (initial_read_size == 0) {
71 tevent_req_error(req, EINVAL);
72 return tevent_req_post(req, ev);
75 buf = talloc_array(state, uint8_t, initial_read_size);
76 if (tevent_req_nomem(buf, req)) {
77 return tevent_req_post(req, ev);
79 state->pdu_blob.data = buf;
80 state->pdu_blob.length = initial_read_size;
82 state->tmp_vector.iov_base = buf;
83 state->tmp_vector.iov_len = initial_read_size;
85 subreq = tstream_readv_send(state, ev, stream, &state->tmp_vector, 1);
86 if (tevent_req_nomem(subreq, req)) {
87 return tevent_req_post(req, ev);
89 tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
91 return req;
94 static void tstream_read_pdu_blob_done(struct tevent_req *subreq)
96 struct tevent_req *req =
97 tevent_req_callback_data(subreq,
98 struct tevent_req);
99 struct tstream_read_pdu_blob_state *state =
100 tevent_req_data(req,
101 struct tstream_read_pdu_blob_state);
102 ssize_t ret;
103 int sys_errno;
104 size_t pdu_size;
105 NTSTATUS status;
106 uint8_t *buf;
108 ret = tstream_readv_recv(subreq, &sys_errno);
109 TALLOC_FREE(subreq);
110 if (ret == -1) {
111 status = map_nt_error_from_unix(sys_errno);
112 tevent_req_nterror(req, status);
113 return;
116 status = state->caller.full_fn(state->caller.full_private,
117 state->pdu_blob, &pdu_size);
118 if (NT_STATUS_IS_OK(status)) {
119 tevent_req_done(req);
120 return;
121 } else if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES)) {
122 /* more to get */
123 } else if (!NT_STATUS_IS_OK(status)) {
124 tevent_req_nterror(req, status);
125 return;
128 buf = talloc_realloc(state, state->pdu_blob.data, uint8_t, pdu_size);
129 if (tevent_req_nomem(buf, req)) {
130 return;
132 state->pdu_blob.data = buf;
133 state->pdu_blob.length = pdu_size;
135 state->tmp_vector.iov_base = buf + state->tmp_vector.iov_len;
136 state->tmp_vector.iov_len = pdu_size - state->tmp_vector.iov_len;
138 subreq = tstream_readv_send(state,
139 state->caller.ev,
140 state->caller.stream,
141 &state->tmp_vector,
143 if (tevent_req_nomem(subreq, req)) {
144 return;
146 tevent_req_set_callback(subreq, tstream_read_pdu_blob_done, req);
149 NTSTATUS tstream_read_pdu_blob_recv(struct tevent_req *req,
150 TALLOC_CTX *mem_ctx,
151 DATA_BLOB *pdu_blob)
153 struct tstream_read_pdu_blob_state *state = tevent_req_data(req,
154 struct tstream_read_pdu_blob_state);
155 NTSTATUS status;
157 if (tevent_req_is_nterror(req, &status)) {
158 tevent_req_received(req);
159 return status;
162 *pdu_blob = state->pdu_blob;
163 talloc_steal(mem_ctx, pdu_blob->data);
165 tevent_req_received(req);
166 return NT_STATUS_OK;