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 28enum fetchfile_stage {FETCHFILE_CONNECT, 29 FETCHFILE_READ}; 30 31struct 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 39static void fetchfile_composite_handler(struct composite_context *req); 40 41static NTSTATUS fetchfile_connect(struct composite_context *c, 42 struct smb_composite_fetchfile *io) 43{ 44 NTSTATUS status; 45 struct fetchfile_state *state; 46 state = talloc_get_type(c->private_data, struct fetchfile_state); 47 48 status = smb_composite_connect_recv(state->creq, c); 49 NT_STATUS_NOT_OK_RETURN(status); 50 51 state->loadfile = talloc(state, struct smb_composite_loadfile); 52 NT_STATUS_HAVE_NO_MEMORY(state->loadfile); 53 54 state->loadfile->in.fname = io->in.filename; 55 56 state->creq = smb_composite_loadfile_send(state->connect->out.tree, 57 state->loadfile); 58 NT_STATUS_HAVE_NO_MEMORY(state->creq); 59 60 state->creq->async.private_data = c; 61 state->creq->async.fn = fetchfile_composite_handler; 62 63 state->stage = FETCHFILE_READ; 64 65 return NT_STATUS_OK; 66} 67 68static NTSTATUS fetchfile_read(struct composite_context *c, 69 struct smb_composite_fetchfile *io) 70{ 71 NTSTATUS status; 72 struct fetchfile_state *state; 73 state = talloc_get_type(c->private_data, struct fetchfile_state); 74 75 status = smb_composite_loadfile_recv(state->creq, NULL); 76 NT_STATUS_NOT_OK_RETURN(status); 77 78 io->out.data = state->loadfile->out.data; 79 io->out.size = state->loadfile->out.size; 80 81 c->state = COMPOSITE_STATE_DONE; 82 if (c->async.fn) 83 c->async.fn(c); 84 85 return NT_STATUS_OK; 86} 87 88static void fetchfile_state_handler(struct composite_context *c) 89{ 90 struct fetchfile_state *state; 91 NTSTATUS status = NT_STATUS_UNSUCCESSFUL; 92 93 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 switch (state->stage) { 98 case FETCHFILE_CONNECT: 99 status = fetchfile_connect(c, state->io); 100 break; 101 case FETCHFILE_READ: 102 status = fetchfile_read(c, state->io); 103 break; 104 } 105 106 if (!NT_STATUS_IS_OK(status)) { 107 c->status = status; 108 c->state = COMPOSITE_STATE_ERROR; 109 if (c->async.fn) { 110 c->async.fn(c); 111 } 112 } 113} 114 115static void fetchfile_composite_handler(struct composite_context *creq) 116{ 117 struct composite_context *c = talloc_get_type(creq->async.private_data, 118 struct composite_context); 119 fetchfile_state_handler(c); 120} 121 122struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetchfile *io, 123 struct tevent_context *event_ctx) 124{ 125 struct composite_context *c; 126 struct fetchfile_state *state; 127 128 c = talloc_zero(NULL, struct composite_context); 129 if (c == NULL) goto failed; 130 131 state = talloc(c, struct fetchfile_state); 132 if (state == NULL) goto failed; 133 134 state->connect = talloc(state, struct smb_composite_connect); 135 if (state->connect == NULL) goto failed; 136 137 state->io = io; 138 139 state->connect->in.dest_host = io->in.dest_host; 140 state->connect->in.dest_ports = io->in.ports; 141 state->connect->in.socket_options = io->in.socket_options; 142 state->connect->in.called_name = io->in.called_name; 143 state->connect->in.service = io->in.service; 144 state->connect->in.service_type = io->in.service_type; 145 state->connect->in.credentials = io->in.credentials; 146 state->connect->in.fallback_to_anonymous = false; 147 state->connect->in.workgroup = io->in.workgroup; 148 state->connect->in.gensec_settings = io->in.gensec_settings; 149 state->connect->in.iconv_convenience = io->in.iconv_convenience; 150 151 state->connect->in.options = io->in.options; 152 state->connect->in.session_options = io->in.session_options; 153 154 state->creq = smb_composite_connect_send(state->connect, state, 155 io->in.resolve_ctx, event_ctx); 156 if (state->creq == NULL) goto failed; 157 158 state->creq->async.private_data = c; 159 state->creq->async.fn = fetchfile_composite_handler; 160 161 c->state = COMPOSITE_STATE_IN_PROGRESS; 162 state->stage = FETCHFILE_CONNECT; 163 c->private_data = state; 164 165 return c; 166 failed: 167 talloc_free(c); 168 return NULL; 169} 170 171NTSTATUS smb_composite_fetchfile_recv(struct composite_context *c, 172 TALLOC_CTX *mem_ctx) 173{ 174 NTSTATUS status; 175 176 status = composite_wait(c); 177 178 if (NT_STATUS_IS_OK(status)) { 179 struct fetchfile_state *state = talloc_get_type(c->private_data, struct fetchfile_state); 180 talloc_steal(mem_ctx, state->io->out.data); 181 } 182 183 talloc_free(c); 184 return status; 185} 186 187NTSTATUS smb_composite_fetchfile(struct smb_composite_fetchfile *io, 188 TALLOC_CTX *mem_ctx) 189{ 190 struct composite_context *c = smb_composite_fetchfile_send(io, NULL); 191 return smb_composite_fetchfile_recv(c, mem_ctx); 192} 193