Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : Copyright (C) Volker Lendecke 2005 5 : 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. 10 : 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. 15 : 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/>. 18 : */ 19 : /* 20 : a composite API for loading a whole file into memory 21 : */ 22 : 23 : #include "includes.h" 24 : #include "libcli/composite/composite.h" 25 : #include "libcli/smb_composite/smb_composite.h" 26 : #include "libcli/resolve/resolve.h" 27 : 28 : enum fetchfile_stage {FETCHFILE_CONNECT, 29 : FETCHFILE_READ}; 30 : 31 : struct fetchfile_state { 32 : enum fetchfile_stage stage; 33 : struct smb_composite_fetchfile *io; 34 : struct composite_context *creq; 35 : struct smb_composite_connect *connect; 36 : struct smb_composite_loadfile *loadfile; 37 : }; 38 : 39 : static void fetchfile_composite_handler(struct composite_context *req); 40 : 41 10 : static NTSTATUS fetchfile_connect(struct composite_context *c, 42 : struct smb_composite_fetchfile *io) 43 : { 44 : NTSTATUS status; 45 : struct fetchfile_state *state; 46 10 : state = talloc_get_type(c->private_data, struct fetchfile_state); 47 : 48 10 : status = smb_composite_connect_recv(state->creq, c); 49 10 : NT_STATUS_NOT_OK_RETURN(status); 50 : 51 10 : state->loadfile = talloc(state, struct smb_composite_loadfile); 52 10 : NT_STATUS_HAVE_NO_MEMORY(state->loadfile); 53 : 54 10 : state->loadfile->in.fname = io->in.filename; 55 : 56 10 : state->creq = smb_composite_loadfile_send(state->connect->out.tree, 57 : state->loadfile); 58 10 : NT_STATUS_HAVE_NO_MEMORY(state->creq); 59 : 60 10 : state->creq->async.private_data = c; 61 10 : state->creq->async.fn = fetchfile_composite_handler; 62 : 63 10 : state->stage = FETCHFILE_READ; 64 : 65 10 : return NT_STATUS_OK; 66 : } 67 : 68 10 : static NTSTATUS fetchfile_read(struct composite_context *c, 69 : struct smb_composite_fetchfile *io) 70 : { 71 : NTSTATUS status; 72 : struct fetchfile_state *state; 73 10 : state = talloc_get_type(c->private_data, struct fetchfile_state); 74 : 75 10 : status = smb_composite_loadfile_recv(state->creq, NULL); 76 10 : NT_STATUS_NOT_OK_RETURN(status); 77 : 78 10 : io->out.data = state->loadfile->out.data; 79 10 : io->out.size = state->loadfile->out.size; 80 : 81 10 : c->state = COMPOSITE_STATE_DONE; 82 10 : if (c->async.fn) 83 10 : c->async.fn(c); 84 : 85 10 : return NT_STATUS_OK; 86 : } 87 : 88 20 : static void fetchfile_state_handler(struct composite_context *c) 89 : { 90 : struct fetchfile_state *state; 91 : NTSTATUS status; 92 : 93 20 : state = talloc_get_type(c->private_data, struct fetchfile_state); 94 : 95 : /* when this handler is called, the stage indicates what 96 : call has just finished */ 97 20 : switch (state->stage) { 98 10 : case FETCHFILE_CONNECT: 99 10 : status = fetchfile_connect(c, state->io); 100 10 : break; 101 10 : case FETCHFILE_READ: 102 10 : status = fetchfile_read(c, state->io); 103 10 : break; 104 0 : default: 105 0 : status = NT_STATUS_UNSUCCESSFUL; 106 0 : break; 107 : } 108 : 109 20 : if (!NT_STATUS_IS_OK(status)) { 110 0 : c->status = status; 111 0 : c->state = COMPOSITE_STATE_ERROR; 112 0 : if (c->async.fn) { 113 0 : c->async.fn(c); 114 : } 115 : } 116 20 : } 117 : 118 20 : static void fetchfile_composite_handler(struct composite_context *creq) 119 : { 120 20 : struct composite_context *c = talloc_get_type(creq->async.private_data, 121 : struct composite_context); 122 20 : fetchfile_state_handler(c); 123 20 : } 124 : 125 10 : struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetchfile *io, 126 : struct tevent_context *event_ctx) 127 : { 128 : struct composite_context *c; 129 : struct fetchfile_state *state; 130 : 131 10 : c = talloc_zero(NULL, struct composite_context); 132 10 : if (c == NULL) goto failed; 133 : 134 10 : state = talloc(c, struct fetchfile_state); 135 10 : if (state == NULL) goto failed; 136 : 137 10 : state->connect = talloc_zero(state, struct smb_composite_connect); 138 10 : if (state->connect == NULL) goto failed; 139 : 140 10 : state->io = io; 141 : 142 10 : state->connect->in.dest_host = io->in.dest_host; 143 10 : state->connect->in.dest_ports = io->in.ports; 144 10 : state->connect->in.socket_options = io->in.socket_options; 145 10 : state->connect->in.called_name = io->in.called_name; 146 10 : state->connect->in.service = io->in.service; 147 10 : state->connect->in.service_type = io->in.service_type; 148 10 : state->connect->in.credentials = io->in.credentials; 149 10 : state->connect->in.fallback_to_anonymous = false; 150 10 : state->connect->in.workgroup = io->in.workgroup; 151 10 : state->connect->in.gensec_settings = io->in.gensec_settings; 152 : 153 10 : state->connect->in.options = io->in.options; 154 10 : state->connect->in.session_options = io->in.session_options; 155 : 156 10 : state->creq = smb_composite_connect_send(state->connect, state, 157 : io->in.resolve_ctx, event_ctx); 158 10 : if (state->creq == NULL) goto failed; 159 : 160 10 : state->creq->async.private_data = c; 161 10 : state->creq->async.fn = fetchfile_composite_handler; 162 : 163 10 : c->state = COMPOSITE_STATE_IN_PROGRESS; 164 10 : state->stage = FETCHFILE_CONNECT; 165 10 : c->private_data = state; 166 : 167 10 : return c; 168 0 : failed: 169 0 : talloc_free(c); 170 0 : return NULL; 171 : } 172 : 173 10 : NTSTATUS smb_composite_fetchfile_recv(struct composite_context *c, 174 : TALLOC_CTX *mem_ctx) 175 : { 176 : NTSTATUS status; 177 : 178 10 : status = composite_wait(c); 179 : 180 10 : if (NT_STATUS_IS_OK(status)) { 181 10 : struct fetchfile_state *state = talloc_get_type(c->private_data, struct fetchfile_state); 182 10 : talloc_steal(mem_ctx, state->io->out.data); 183 : } 184 : 185 10 : talloc_free(c); 186 10 : return status; 187 : } 188 : 189 0 : NTSTATUS smb_composite_fetchfile(struct smb_composite_fetchfile *io, 190 : TALLOC_CTX *mem_ctx) 191 : { 192 0 : struct composite_context *c = smb_composite_fetchfile_send(io, NULL); 193 0 : return smb_composite_fetchfile_recv(c, mem_ctx); 194 : }